Compare commits

..

No commits in common. "ecr" and "main" have entirely different histories.
ecr ... main

504 changed files with 7760 additions and 27453 deletions

38
.gitignore vendored
View File

@ -1,23 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
/.idea
/app/release/*
/app/sit/release/*
/app/uat/release/*
/app/uat
/.idea
/app/prod/release
nexdlkey-lib/build/
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

View File

@ -1 +1 @@
KBZ-Master-latest
KBZ-Master

File diff suppressed because one or more lines are too long

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AskMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Ask2AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EditMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@ -4,7 +4,7 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-01-20T10:19:44.274945Z">
<DropdownSelection timestamp="2025-10-28T19:40:02.148831Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=0123456789ABCDEF" />

View File

@ -14,11 +14,10 @@
<option value="$PROJECT_DIR$/baselib" />
<option value="$PROJECT_DIR$/ecr" />
<option value="$PROJECT_DIR$/ecr-service-lib" />
<option value="$PROJECT_DIR$/link-service-lib" />
<option value="$PROJECT_DIR$/mpulib" />
<option value="$PROJECT_DIR$/nexdlkey-lib" />
<option value="$PROJECT_DIR$/nexsdk-lib" />
<option value="$PROJECT_DIR$/paylibs" />
<option value="$PROJECT_DIR$/paysdk-lib" />
<option value="$PROJECT_DIR$/qrgen-lib" />
<option value="$PROJECT_DIR$/xpay" />
</set>

View File

@ -1,4 +0,0 @@
kotlin version: 2.0.21
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready

View File

@ -14,48 +14,32 @@ android {
applicationId "com.utsmm.kbz"
minSdk 24
targetSdk 33
versionCode 21
versionName "2.1"
versionCode 5
versionName "1.05"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// // Add CMake configuration
// externalNativeBuild {
// cmake {
// cppFlags "-std=c++14"
// }
// }
}
// -----------------------------
// 🔥 MULTI-VARIANT FLAVORS
// -----------------------------
flavorDimensions "env"
productFlavors {
sit {
dimension "env"
applicationId "com.utsmm.kbz.sit"
versionNameSuffix "-sit"
resValue "string", "app_name", "KBZ-SIT"
}
uat {
dimension "env"
applicationId "com.utsmm.kbz.uat"
versionNameSuffix "-uat"
resValue "string", "app_name", "KBZ-UAT"
}
prod {
dimension "env"
applicationId "com.utsmm.kbz"
versionNameSuffix ""
resValue "string", "app_name", "KBZ-POS"
}
}
// Configure CMake
// externalNativeBuild {
// cmake {
// path "src/main/cpp/CMakeLists.txt"
// version "3.22.1"
// }
// }
buildTypes {
release {
minifyEnabled true
shrinkResources false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
@ -73,11 +57,6 @@ android {
buildConfig = true
}
lint {
abortOnError false
checkReleaseBuilds false
}
packagingOptions {
pickFirst '**/libnative-lib.so'
pickFirst '**/libxgd_ddi_jni.so'
@ -105,17 +84,13 @@ kapt {
arg("room.incremental", "true")
arg("room.expandProjection", "true")
}
// Exclude ECR integration classes from kapt processing
javacOptions {
option("-Xmaxerrs", 500)
}
}
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
def nav_version = "2.3.2"
def lottieVersion = "3.5.0"
def fragment_version = "1.2.0"
@ -186,8 +161,8 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation "com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0"
// ViewModel with Kotlin extensions
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
// ViewModel
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'
// LiveData
implementation 'androidx.lifecycle:lifecycle-livedata:2.2.0'
@ -202,29 +177,18 @@ dependencies {
// implementation 'com.sunmi:sunmiui:1.1.27' //1.1.27
// ECR Dependencies - Modern ECR Client Library
// implementation project(path: ':ecr-client-lib')
// implementation project(path: ':ecr-service-lib')
// Core Libraries
implementation project(path: ':ecr-service-lib')
implementation project(path: ':paylibs')
implementation project(path: ':mpulib')
implementation project(path: ':baselib')
// implementation project(path: ':paysdk-lib')
implementation project(path: ':paysdk-lib')
implementation project(path: ':nexsdk-lib')
implementation project(path: ':qrgen-lib')
implementation project(path: ':xpay')
// implementation project(path: ':sunmiui-lib')
implementation project(path: ':qrgen-lib')
//// implementation project(path: ':samlSirius')
// Legacy ECR (kept for backward compatibility during migration)
implementation project(path: ':ecr')
implementation project(path: ':nexdlkey-lib')
// Coroutines for modern ECR client
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2' // 1.1.2
@ -232,16 +196,15 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
androidTestImplementation 'androidx.test:core:1.5.0'
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
// Add Mockito dependency for mocking
testImplementation 'org.mockito:mockito-core:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.9'
testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
//time picker
implementation "com.google.android.material:material:1.11.0"
}

246
app/proguard-rules.pro vendored
View File

@ -20,249 +20,7 @@
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keepattributes Signature, *Annotation*, SourceFile, LineNumberTable, InnerClasses, EnclosingMethod
-dontwarn sun.misc.**
# Hilt ProGuard Rules - CRITICAL FOR DEPENDENCY INJECTION
-dontwarn dagger.hilt.**
-keep class dagger.hilt.** { *; }
-keep class * extends dagger.hilt.** { *; }
# Keep all Hilt generated classes
-keep class **_HiltComponents { *; }
-keep class **_HiltComponents$* { *; }
-keep class **_HiltModules { *; }
-keep class **_HiltModules$* { *; }
-keep class * extends dagger.hilt.android.internal.managers.ApplicationComponentManager { *; }
-keep class * extends dagger.hilt.android.internal.managers.ActivityComponentManager { *; }
-keep class * extends dagger.hilt.android.internal.managers.FragmentComponentManager { *; }
-keep class * extends dagger.hilt.android.internal.managers.ViewComponentManager { *; }
-keep class * extends dagger.hilt.android.internal.managers.ServiceComponentManager { *; }
# Keep Hilt entry points and components
-keep @dagger.hilt.InstallIn class * { *; }
-keep @dagger.hilt.android.AndroidEntryPoint class * { *; }
-keep @dagger.hilt.android.HiltAndroidApp class * { *; }
# Keep classes annotated with @Module, @Component, @Subcomponent
-keep @dagger.Module class * { *; }
-keep @dagger.Component class * { *; }
-keep @dagger.Component.Builder class * { *; }
-keep @dagger.Subcomponent class * { *; }
-keep @dagger.Subcomponent.Builder class * { *; }
# Keep all classes that have @Inject constructors, fields, or methods
-keepclasseswithmembers class * {
@javax.inject.Inject <init>(...);
}
-keepclasseswithmembers class * {
@javax.inject.Inject <fields>;
}
-keepclasseswithmembers class * {
@javax.inject.Inject <methods>;
}
# Keep Application class and its generated Hilt class
-keep class com.utsmm.kbz.MyApplication { *; }
-keep class com.utsmm.kbz.Hilt_MyApplication { *; }
-keep class com.utsmyanmar.baselib.BaseApplication { *; }
# Keep main activity and its generated classes
-keep class com.utsmm.kbz.MainActivity { *; }
# ViewModels and Repository classes (important for injection)
-keep class * extends androidx.lifecycle.ViewModel { *; }
-keep class com.utsmyanmar.baselib.repo.Repository { *; }
-keep class com.utsmyanmar.baselib.emv.EmvParamOperation { *; }
-keep class com.utsmyanmar.baselib.emv.TerminalParamOperation { *; }
# Keep all Dagger generated classes - these are critical!
-keep class **_Factory { *; }
-keep class **_MembersInjector { *; }
-keep class **_Provide* { *; }
-keep class com.utsmyanmar.baselib.network.model.* { <fields>; }
-keep class com.utsmyanmar.baselib.network.model.sirius.* { <fields>; }
-keep class com.utsmyanmar.baselib.db.model.* { <fields>; }
-keep class com.utsmyanmar.ecr.data.* { <fields>; }
-keep class com.utsmyanmar.ecr.data.model.* { <fields>; }
-keep class com.utsmyanmar.mpulib.data.model.* { <fields>; }
-keep class * extends com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
# this is start
# Keep Bouncy Castle classes for security providers
-keep class org.bouncycastle.** { *; }
-keep interface org.bouncycastle.** { *; }
-keep class okhttp3.internal.platform.BouncyCastlePlatform { *; }
# Keep classes from the JNDI package
-keep class javax.naming.** { *; }
-keep class javax.naming.directory.** { *; }
# Keep Bouncy Castle classes
-keep class org.bouncycastle.** { *; }
# Keep Conscrypt classes
-keep class org.conscrypt.** { *; }
# Keep OpenJSSE classes
-keep class org.openjsse.** { *; }
# Keep classes from okhttp3.internal.platform.BouncyCastlePlatform
-keep class okhttp3.internal.platform.BouncyCastlePlatform { *; }
# Keep classes from okhttp3.internal.platform.ConscryptPlatform
-keep class okhttp3.internal.platform.ConscryptPlatform$Companion { *; }
#-keep class okhttp3.internal.platform.ConscryptPlatform$platformTrustManager$2 { *; }
# Keep classes from okhttp3.internal.platform.OpenJSSEPlatform
-keep class okhttp3.internal.platform.OpenJSSEPlatform { *; }
#this is end
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
# Jun9 2022
#-keep public class * implements com.bumptech.glide.module.GlideModule
#-keep class * extends com.bumptech.glide.module.AppGlideModule {
# <init>(...);
#}
#-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
# **[] $VALUES;
# public *;
#}
#-assumenosideeffects class android.util.Log {
#public static int d(...);
#public static int v(...);
#public static int i(...);
#public static int w(...);
#public static int wtf(...);
# }
-dontwarn okhttp3.internal.platform.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**
-dontwarn org.openjsse.**
# RxJava 3 Rules - Critical for Observable chains
-keep class io.reactivex.rxjava3.** { *; }
-dontwarn io.reactivex.rxjava3.**
-keep class io.reactivex.rxjava3.core.** { *; }
-keep class io.reactivex.rxjava3.android.** { *; }
-keep class io.reactivex.rxjava3.schedulers.** { *; }
# Retrofit and OkHttp rules
-keepattributes RuntimeVisibleAnnotations
-keep class retrofit2.** { *; }
-keepclassmembernames interface * {
@retrofit2.http.* <methods>;
}
# AndroidX and Lifecycle components
-keep class androidx.lifecycle.** { *; }
-keep class * extends androidx.lifecycle.ViewModel { *; }
-keep class androidx.activity.** { *; }
-keep class androidx.fragment.** { *; }
# Navigation component rules
-keep class androidx.navigation.** { *; }
-keep class * implements androidx.navigation.NavDirections { *; }
# DataBinding rules
-keep class androidx.databinding.** { *; }
-keep class * extends androidx.databinding.ViewDataBinding { *; }
# Room database rules (if using Room)
-keep class androidx.room.** { *; }
-keep class * extends androidx.room.RoomDatabase { *; }
# PayLibs and device-specific rules
-keep class com.utsmyanmar.paylibs.** { *; }
-keep class com.nexgo.** { *; }
-keep class com.sunmi.** { *; }
-keep class com.utsmyanmar.checkxread.** { *; }
-keep class com.utsmyanmar.ecr.** { *; }
-keep class com.utsmyanmar.mpulib.** { *; }
-keep class com.utsmyanmar.baselib.** { *; }
# Enum preservation for critical enums
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Keep model classes from obfuscation completely
-keep class com.utsmyanmar.paylibs.model.** { *; }
-keep class com.utsmyanmar.baselib.db.model.** { *; }
# Critical: Keep all native methods and JNI classes
-keepclasseswithmembernames class * {
native <methods>;
}
# Keep critical system params and utils
-keep class com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation { *; }
-keep class com.utsmyanmar.paylibs.utils.** { *; }
# Prevent obfuscation of classes used in reflection
-keep class * extends java.lang.Exception
-keep class * extends java.lang.Error
# CRITICAL: Keep all generated application components from obfuscation
-keep class com.utsmm.kbz.MyApplication_GeneratedInjector { *; }
#-keep class com.utsmm.kbz.MyApplication_HiltComponents$SingletonC { *; }
#-keep class com.utsmm.kbz.MyApplication_HiltComponents { *; }
# Keep all classes with "Generated" in their name (Hilt generates these)
-keep class **_Generated { *; }
-keep class **GeneratedInjector { *; }
# Additional protection for the specific classes causing crashes
-keep class **.D0.h { *; }
-keep class **.m2.f { *; }
-keep class **.J3.b { *; }
# Keep everything in the di package to prevent injection failures
-keep class com.utsmyanmar.baselib.di.** { *; }
-keep class com.utsmm.kbz.di.** { *; }
# Hilt Extension points
#-keep class * extends dagger.hilt.android.internal.managers.ApplicationComponentManager$ApplicationComponentBuilder { *; }
# Don't obfuscate any annotation processing related classes
-keep class dagger.internal.** { *; }
-keepnames class dagger.internal.** { *; }
# Keep annotation-based bindings
-keep @javax.inject.Inject class * { *; }
-keep @dagger.Provides class * { *; }
-keep @dagger.Module class * { *; }
# Keep Nexgo SDK
-keep class com.nexgo.** { *; }
# Keep DDI interface (VERY IMPORTANT)
-keep class com.xinguodu.ddiinterface.** { *; }
# Keep printer implementations
-keep class com.nexgo.oaf.apiv3.device.printer.** { *; }
# Prevent method shrinking/optimization
-dontoptimize
-dontshrink
-dontwarn com.xgd.smartpos.manager.app.UsageInfo
-dontwarn com.xgd.smartpos.manager.app.UsageStats
-dontwarn org.bouncycastle.**

Binary file not shown.

View File

@ -4,15 +4,15 @@
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.utsmm.kbz.sit",
"applicationId": "com.utsmm.kbz",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0",
"versionCode": 5,
"versionName": "1.05",
"outputFile": "app-release.apk"
}
],

View File

@ -1,37 +0,0 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.utsmm.kbz.sit",
"variantName": "sitRelease",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 2,
"versionName": "1.01-sit",
"outputFile": "app-sit-release.apk"
}
],
"elementType": "File",
"baselineProfiles": [
{
"minApi": 28,
"maxApi": 30,
"baselineProfiles": [
"baselineProfiles/1/app-sit-release.dm"
]
},
{
"minApi": 31,
"maxApi": 2147483647,
"baselineProfiles": [
"baselineProfiles/0/app-sit-release.dm"
]
}
],
"minSdkVersionForDexing": 24
}

View File

@ -10,32 +10,6 @@ import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import com.utsmm.kbz.util.MockData;
import com.utsmm.kbz.util.TransactionUtil;
import com.utsmyanmar.checkxread.model.CardDataX;
import com.utsmyanmar.checkxread.util.CardTypeX;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.isobuilder.ISOMode;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion;
import com.utsmyanmar.paylibs.model.MsgField;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.model.enums.TransCVM;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.MessageType;
import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.BaseCardType;
import com.utsmyanmar.paylibs.utils.enums.HostName;
import com.utsmyanmar.paylibs.utils.iso_utils.BitmapConfig;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionType;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.params.Params;
import java.util.Locale;
import java.util.Map;
/**
* Instrumented test, which will execute on an Android device.
*
@ -49,185 +23,4 @@ public class ExampleInstrumentedTest {
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.utsmm.kbz", appContext.getPackageName());
}
@Test
public void testVoidPacket() {
CardDataX cardDataX = MockData.getInstance().generateMPUCard();
TradeData tradeData = TransactionUtil.getInstance().initMPUTransaction(cardDataX, CardTypeX.IC);
String bitmap = BitmapConfig.MPU_NEW_VOID;
MessageType messageType = MessageType.FINANCIAL;
ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1987, ISOMode.ONLY_HEADER, HostName.FINEXUS)
.build();
TradeData transTradeData = setUpRebuildTransactions(tradeData, TransactionsType.VOID, HostName.FINEXUS);
transTradeData.getPayDetail().setAmount(50000);
PayDetail transPayDetail = transTradeData.getPayDetail();
byte[] sendBytes;
try {
sendBytes = isoMsgX.buildISOPackets(transTradeData, bitmap, messageType);
System.out.println("Hex Str : "+ ByteUtil.bytes2HexStr(sendBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testSalePacket() {
CardDataX cardDataX = MockData.getInstance().generateMPUCard();
TradeData tradeData = TransactionUtil.getInstance().initEMVTransaction(cardDataX, CardTypeX.IC);
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setProcessCode("000000");
payDetail.setTransactionType(TransactionType.SALE);
String bitmap = BitmapConfig.BPC_SALE;
MessageType messageType = MessageType.FINANCIAL;
ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU, HostName.BPC)
.build();
byte[] sendBytes;
try {
sendBytes = isoMsgX.buildISOPackets(tradeData, bitmap, messageType);
System.out.println("Hex Str : "+ ByteUtil.bytes2HexStr(sendBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testResponseSalePacket() {
String resp = "0071600000051730323130723000000A80820031363437363137333130303030303030323730303030303030303030303030353530303030313039313634353532303030303033323630313039313731353532303031303030303735343431393130303030343733343531303400048A023936";
resp = "00DB600000051730323130723000000A80820031363335373130353030333938393032373030303030303030303030303030353030303030313230313633323039303030303133323630313230313633323033303031303030303832333632393130383132333037313431303401105F2A02010482021C008407A00000006510109505808800E0009A032601209C01009F02060000000500009F03060000000000009F100807010104A09000B09F1A0201049F26080611D1D33562865F9F2701809F3303E0E8C89F34031E03009F360200049F37045A647F128A023936";
byte[] response = ByteUtil.hexStr2Bytes(resp);
String bitmap = BitmapConfig.BPC_SALE;
MessageType messageType = MessageType.FINANCIAL;
ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU, HostName.BPC)
.build();
Map<String, MsgField> responseMap = isoMsgX.parseISOPackets(response,response.length);
System.out.println("Resp Str : "+ responseMap);
// try {
// responseMap = isoMsgX.parseISOPackets(response,response.length);
//
// System.out.println("Resp Str : "+ responseMap);
// } catch (Exception e) {
// e.printStackTrace();
// }
}
private TradeData setUpRebuildTransactions(TradeData tradeData, TransactionsType transactionsType, HostName hostName) {
LogUtil.d(Constant.TAG, "Starting Online Transaction--" + hostName + "--" + transactionsType);
TradeData newTrade = Params.newTrade(true);
PayDetail newPay = newTrade.getPayDetail();
PayDetail oldPay = tradeData.getPayDetail();
newPay.setCardType(100);
newPay.setPINCipher("");
newPay.setHostName(hostName.name);
newPay.setTransType(transactionsType.name);
newPay.setProcessCode(transactionsType.processCode);
newPay.setCardNo(oldPay.getCardNo());
newPay.setCardHolderName(oldPay.getCardHolderName());
newPay.setEXPDate(oldPay.getEXPDate());
newPay.setTradeDate(oldPay.getTradeDate());
newPay.setTradeTime(oldPay.getTradeTime());
newPay.setAmount(oldPay.getAmount());
newPay.setTransactionType(transactionsType.value);
newPay.setAccountType(oldPay.getAccountType());
newPay.setCardInfo(oldPay.getCardInfo());
newPay.setSettlementEnabled(SystemParamsOperation.getInstance().getSettlementStatus());
// added on Nov, 13 2024
newPay.setICC55(oldPay.getICC55());
if(newPay.getICC55() != null && !newPay.getICC55().isEmpty()) {
newPay.setAppLabel(oldPay.getAppLabel());
newPay.setAppName(oldPay.getAppName());
newPay.setTSI(oldPay.getTSI());
newPay.setAID(oldPay.getAID());
newPay.setArqC(oldPay.getArqC());
newPay.setTVR(oldPay.getTVR());
}
if(transactionsType != TransactionsType.PRE_AUTH_COMPLETE) {
newPay.setTradeDateTime(oldPay.getTradeDateTime());
}
if (transactionsType == TransactionsType.VOID || transactionsType == TransactionsType.REFUND) {
String field60;
if(hostName == HostName.BPC) {
field60 = String.format(Locale.getDefault(), "%010d00", oldPay.getAmount());
} else {
field60 = String.format(Locale.getDefault(), "%012d", oldPay.getAmount());
}
// String field60 = String.format(Locale.getDefault(), "%010d00", oldPay.getAmount());
newPay.setReferNo(oldPay.getReferNo());
newPay.setTransCVM(TransCVM.SIGNATURE);
newTrade.setField60(field60);
} else if (transactionsType == TransactionsType.PRE_AUTH_VOID) {
newPay.setCardType(oldPay.getCardType());
newPay.setCustomOrderNo(oldPay.getVoucherNo());
newPay.setReferNo(oldPay.getReferNo());
newPay.setCardInfo(oldPay.getCardInfo());
newPay.setPINCipher(oldPay.getPINCipher());
newPay.setTempKSN(oldPay.getTempKSN());
newPay.setTransCVM(TransCVM.SIGNATURE);
// for manual entry reversal which need de 35
} else if (transactionsType == TransactionsType.TIP_ADJUSTMENT ) {
newPay.setReferNo(oldPay.getReferNo());
newPay.setApprovalCode(oldPay.getApprovalCode());
} else if (transactionsType == TransactionsType.PRE_AUTH_COMPLETE) {
newPay.setCardType(oldPay.getCardType());
newPay.setCardInfo(oldPay.getCardInfo());
newPay.setPINCipher(oldPay.getPINCipher());
newPay.setReferNo(oldPay.getReferNo());
newPay.setTempKSN(oldPay.getTempKSN());
} else if (transactionsType == TransactionsType.PRE_AUTH_COMPLETE_VOID) {
newPay.setVoucherNo(oldPay.getVoucherNo());
newPay.setCustomOrderNo(oldPay.getVoucherNo());
newPay.setReferNo(oldPay.getReferNo());
newPay.setCardInfo(oldPay.getCardInfo());
/*
* new requirements */
newPay.setCardType(BaseCardType.IC.getValue());
newPay.setPINCipher("55");
newPay.setTransCVM(TransCVM.SIGNATURE);
}
if(oldPay.getAccountType().equals("MPU")){
// newPay.setIsFreeSign(true);
newPay.setTransCVM(TransCVM.SIGNATURE);
}
newTrade.setPayDetail(newPay);
return newTrade;
}
}

View File

@ -9,8 +9,7 @@
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@ -28,14 +27,6 @@
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- Permission for exact alarms on Android 12+ -->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<!-- Permissions for background auto settlement -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<!-- android:noHistory="true"-->
<!-- android:excludeFromRecents="true"-->
@ -55,32 +46,30 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar">
android:theme="@style/AppTheme.NoActionBar"
>
<!-- android:manageSpaceActivity="com.utsmyanmar.upos.config.UTSManageSpaceActivity"-->
<!-- <activity-->
<!-- android:screenOrientation="portrait"-->
<!-- android:name=".config.UTSManageSpaceActivity"/>-->
<activity android:name="com.utsmm.kbz.MainActivity"
android:exported="true"
android:showWhenLocked="true"
android:turnScreenOn="true">
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="fullSensor"
tools:replace="screenOrientation" />
<receiver android:name="com.utsmm.kbz.service.AutoAlarmReceiver" />
<receiver android:name="com.utsmm.kbz.service.SmileAlarmReceiver" />
<service
android:name="com.utsmm.kbz.service.AutoSettleService"
android:name="com.utsmm.kbz.service.SmileSettleService"
android:enabled="true"
android:exported="false">
<meta-data

View File

@ -4,7 +4,6 @@ import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
@ -17,39 +16,23 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.Toast;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.navigation.NavigationView;
import com.nexgo.downloadkey.downloadflow.DownloadFEntity;
import com.nexgo.downloadkey.downloadflow.DownloadFlow;
import com.nexgo.downloadkey.downloadflow.DownloadFlowProcessListener;
import com.nexgo.downloadkey.downloadflow.DownloadFlowResultEntity;
import com.nexgo.downloadkey.downloadflow.DownloadResult;
import com.nexgo.oaf.apiv3.device.pinpad.PinPad;
import com.nexgo.oaf.apiv3.device.pinpad.WorkKeyTypeEnum;
import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.baselib.ui.AnimationDialog;
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.SettleData;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsSettings;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.databinding.ActivityMainNewBinding;
import com.utsmm.kbz.service.AutoAlarmReceiver;
import com.utsmm.kbz.service.SmileAlarmReceiver;
import com.utsmm.kbz.ui.core_ui.InputPasswordFragment;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.navigation.NaviAdminFragment;
@ -60,7 +43,6 @@ import com.utsmm.kbz.util.tms.TMSUtil;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -74,8 +56,6 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.params.Params;
/**
* Main Activity handling application navigation and fragment interactions
*/
@ -115,8 +95,6 @@ public class MainActivity extends AppCompatActivity implements
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
// Keep screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@ -146,35 +124,8 @@ public class MainActivity extends AppCompatActivity implements
// Initialize special back handling fragments
initSpecialBackHandlingFragments();
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
initKey();
}
}, 500);
}
private void initKey(){
// SystemParamsOperation.getInstance().setTmsAddress("https://api-tms-uat.kbzbank.com:8443/sirius");
SystemParamsOperation.getInstance().setTmsAddress("https://sirius-nest.utsmyanmar.com");
// SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms-uat.kbzbank.com:8443/receipt");
SystemParamsOperation.getInstance().setEReceiptAddress("https://receipt-nest.utsmyanmar.com");
PinPad pinPad = MyApplication.getInstance().deviceEngine.getPinPad();
byte[] encryptedPIK = SystemParamsOperation.getInstance().getPIK();
if (encryptedPIK != null && encryptedPIK.length != 0) {
int result = pinPad.writeWKey(9, WorkKeyTypeEnum.PINKEY, encryptedPIK, encryptedPIK.length);
LogUtil.d(TAG, "save PIK key result: "+result);
} else {
LogUtil.d(TAG, "There's no PIK key!");
}
}
private void initViewModels() {
sharedViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
}
@ -289,7 +240,7 @@ public class MainActivity extends AppCompatActivity implements
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this,
0,
new Intent(this, AutoAlarmReceiver.class),
new Intent(this, SmileAlarmReceiver.class),
PendingIntent.FLAG_UPDATE_CURRENT
);
@ -431,124 +382,20 @@ public class MainActivity extends AppCompatActivity implements
SystemParamsOperation.getInstance().setSetupEcr(false);
SystemParamsOperation.getInstance().setDownloadedParams(false);
handleAutoSettlementIntent(getIntent());
BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
}
@Override
public void onStop(){
super.onStop();
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
// BaseApplication.getInstance().deviceEngine.getPlatform().enableHomeButton();
// BaseApplication.getInstance().deviceEngine.getPlatform().enableTaskButton();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
handleAutoSettlementIntent(intent);
}
private void handleAutoSettlementIntent(Intent intent) {
if (intent == null) return;
boolean hasPOS = intent.getBooleanExtra("AUTO_SETTLEMENT", false);
boolean hasQR = intent.getBooleanExtra("AUTO_QR_SETTLEMENT", false);
if (hasPOS) {
PayDetail payDetail = (PayDetail) intent.getSerializableExtra("EXTRA_PAY_DETAIL");
if (payDetail != null) {
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT);
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount()));
try {
navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) {
LogUtil.e(TAG, "Navigation error: " + e.getMessage());
}
// If QR also exists, trigger it AFTER POS result is done
if (hasQR) {
navigateToQRSettlementAfterPOS(intent);
}
} else {
// POS had no data, go straight to QR if available
if (hasQR) {
handleQRSettlement(intent);
}
}
} else if (hasQR) {
// Only QR settlement, no POS
handleQRSettlement(intent);
}
}
private void navigateToQRSettlementAfterPOS(Intent intent) {
// Observe transactionResultFragment's completion via ViewModel
// When POS result screen signals "done" (print complete / user dismissed),
// then navigate to QR result
sharedViewModel.onSettlementResultDone.observe(this, new Observer<Boolean>() {
@Override
public void onChanged(Boolean done) {
if (done != null && done) {
// Remove observer so it only fires once
sharedViewModel.onSettlementResultDone.removeObserver(this);
// Reset flag
sharedViewModel.onSettlementResultDone.postValue(false);
// Now navigate to QR
handleQRSettlement(intent);
}
}
});
}
private void handleQRSettlement(Intent intent) {
int qrSaleCount = intent.getIntExtra("QR_SALE_COUNT", 0);
long qrSaleAmount = intent.getLongExtra("QR_SALE_AMOUNT", 0L);
int qrRefundCount = intent.getIntExtra("QR_REFUND_COUNT", 0);
long qrRefundAmount = intent.getLongExtra("QR_REFUND_AMOUNT", 0L);
long totalAmount = intent.getLongExtra("QR_TOTAL_AMOUNT", 0L);
List<PayDetail> qrTransList = (List<PayDetail>) intent.getSerializableExtra("QR_TRANS_LIST");
SettleData settleData = new SettleData(
qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
TradeData tradeData = Params.newTrade(false);
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setSettleDataObj(settleData);
payDetail.setTransactionType(TransactionsType.MMQR_SETTLEMENT.value);
payDetail.setTransType(TransactionsType.MMQR_SETTLEMENT.name);
payDetail.setAmount(totalAmount);
payDetail.setTradeAnswerCode("000");
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount));
sharedViewModel.payDetails.setValue(qrTransList);
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR_SETTLEMENT);
try {
navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) {
LogUtil.e(TAG, "QR Auto Settlement navigation error: " + e.getMessage());
}
}
@Override
public void onDestroy() {
super.onDestroy();
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
// BaseApplication.getInstance().deviceEngine.getPlatform().enableHomeButton();
// BaseApplication.getInstance().deviceEngine.getPlatform().enableTaskButton();
// Clean up RxJava disposables
compositeDisposable.clear();
// Reset screen mode
// Disconnect ECR
ECRHelper.INSTANCE.disconnect();
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
}
// Navigation drawer interaction listeners
@ -559,12 +406,6 @@ public class MainActivity extends AppCompatActivity implements
navController.navigate(R.id.inputPasswordFragment);
}
@Override
public void onPause(){
super.onPause();
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
}
@Override
public void onClickFunction() {
closeDrawer();

View File

@ -20,14 +20,8 @@ import androidx.lifecycle.Observer;
import com.denzcoskun.imageslider.ImageSlider;
import com.denzcoskun.imageslider.constants.ScaleTypes;
import com.denzcoskun.imageslider.models.SlideModel;
import com.nexgo.oaf.apiv3.emv.AidEntity;
import com.nexgo.oaf.apiv3.emv.CapkEntity;
//import com.pos.connection.bridge.binder.ECRConstant;
import com.pos.connection.bridge.binder.ECRConstant;
import com.utsmm.kbz.util.MockData;
//import com.utsmm.kbz.util.ecr.ModernECRFactory;
//import com.utsmm.kbz.util.ecr.ModernECRManager;
import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
@ -35,14 +29,13 @@ import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.DialogCallback;
import com.utsmyanmar.baselib.util.TerminalUtil;
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.ecr.ECRProcess;
import com.utsmyanmar.ecr.data.ResultOf;
import com.utsmyanmar.ecr.data.model.Transactions;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.print.PrintHelper;
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
@ -50,6 +43,7 @@ import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.config.data.model.ValidityStatus;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
@ -80,11 +74,6 @@ import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.params.Params;
//import com.utsmm.kbz.util.ecr.ModernECRFactory;
//import com.utsmm.kbz.util.ecr.ModernECRManager;
import androidx.lifecycle.ViewModelProvider;
@AndroidEntryPoint
public class MainFragment extends DataBindingFragment {
@ -93,7 +82,6 @@ public class MainFragment extends DataBindingFragment {
private SharedViewModel sharedViewModel;
private MainViewModel mainViewModel;
private TMSProcessViewModel tmsProcessViewModel;
// private ModernECRManager modernECRManager;
private int routeId;
private ImageSlider imgSlider;
private final ArrayList<SlideModel> imgList = new ArrayList<>();
@ -118,26 +106,24 @@ public class MainFragment extends DataBindingFragment {
return routeId;
}
@Override
protected void initViewModel() {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
mainViewModel = getFragmentScopeViewModel(MainViewModel.class);
tmsProcessViewModel = getFragmentScopeViewModel(TMSProcessViewModel.class);
// Initialize ModernECRManager
// ModernECRFactory factory = new ModernECRFactory(requireContext(), sharedViewModel);
// modernECRManager = new ViewModelProvider(this, factory).get(ModernECRManager.class);
}
@Override
public void onResume() {
super.onResume();
setNavBarIconWithTitle(getResourceString(R.string.menu_dashboard));
// Setup ECR Service
// logcat is resetting cuz of this setup , because it is using serial port
if(SystemParamsOperation.getInstance().getECRStatus()){
setUpECR();
// setUpECR();
}
sharedViewModel.isEcrFinished.postValue(true);
@ -148,41 +134,16 @@ public class MainFragment extends DataBindingFragment {
sharedViewModel.setAmountExist(false);
sharedViewModel.setCardDataExist(false);
sharedViewModel.setTransMenu(null);
updateButtonStatus();
delayFunctionCall(this::checkTerminalStatus);
delayFunctionCall(() -> {
delayFunctionCall(()-> {
NexGoSDK.getInstance().cancelCheckCard();
NexGoSDK.getInstance().closeReader();
enableHomeButton();
// disableTaskButton();
// BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
});
}
private void disableHomeButton() {
int result = BaseApplication.getInstance().deviceEngine.getPlatform().disableHomeButton();
LogUtil.d(TAG, "Disable Home Button Result:" + result);
}
private void disableTaskButton() {
int result = BaseApplication.getInstance().deviceEngine.getPlatform().disableTaskButton();
LogUtil.d(TAG, "Disable Task Button Result:" + result);
}
private void enableHomeButton() {
int result = BaseApplication.getInstance().deviceEngine.getPlatform().enableHomeButton();
LogUtil.d(TAG, "Enable Home Button Result:" + result);
}
private void enableTaskButton() {
int result = BaseApplication.getInstance().deviceEngine.getPlatform().enableTaskButton();
LogUtil.d(TAG, "Disable Task Button Result:" + result);
}
private void checkTerminalStatus() {
if (!SystemParamsOperation.getInstance().isActive()) {
@ -196,7 +157,7 @@ public class MainFragment extends DataBindingFragment {
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (SystemParamsOperation.getInstance().isAlertSound()) {
if(SystemParamsOperation.getInstance().isAlertSound()) {
delayFunctionCall(this::checkPrinter);
}
@ -205,8 +166,13 @@ public class MainFragment extends DataBindingFragment {
mainViewModel.observeSettlementPOS();
}
private void checkDownload() {
Log.d(TAG, "Calling from Check download: ");
if (!SystemParamsOperation.getInstance().isDownloadedParams() && SystemParamsOperation.getInstance().isActive() && tmsProcessViewModel.getIsCalled().getValue() == null) {
@ -221,18 +187,12 @@ public class MainFragment extends DataBindingFragment {
@Override
public void onDestroy() {
super.onDestroy();
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
// enableTaskButton();
// enableHomeButton();
}
}
@Override
public void onPause() {
super.onPause();
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
// enableTaskButton();
// enableHomeButton();
}
@Override
@ -243,43 +203,34 @@ public class MainFragment extends DataBindingFragment {
setUpCarouselImages();
if (TextUtils.equals(SystemParamsOperation.getInstance().getCurrentSerialNum(), "000001")) {
if(TextUtils.equals(SystemParamsOperation.getInstance().getCurrentSerialNum(),"000001")) {
setPreviousTraceNum();
}
sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus());
// queryAidCAPKList();
queryAidCAPKList();
// generateMockQR();
}
/*
* @param
*
* value - 0 = AID, 1 = CAPK
* */
private void queryAidCAPKList() {
private void queryAidCAPKList(int value) {
List<String> aidlist = new ArrayList<>();
List<CapkEntity> capkList = MyApplication.getInstance().deviceEngine.getEmvHandler2("app2").getCapkList();
List<AidEntity> aidList = MyApplication.getInstance().deviceEngine.getEmvHandler2("app2").getAidList();
int noCAPK = MyApplication.getInstance().deviceEngine.getEmvHandler2("app2").getCapkListNum();
LogUtil.d(TAG, "Total CAPK :" + noCAPK);
for (CapkEntity capkEntity : capkList) {
LogUtil.d(TAG, "CAPK Entity :" + capkEntity.getRid());
if(capkEntity.getRid().equals("A000000004")) {
LogUtil.d(TAG, "CAPK Entity check sum:" + capkEntity.getCheckSum());
LogUtil.d(TAG, "CAPK Entity modulus:" + capkEntity.getModulus());
LogUtil.d(TAG, "CAPK Entity index:" + capkEntity.getCapkIdx());
try {
int result = MyApplication.getInstance().mEMVOptV2.queryAidCapkList(value,aidlist);
LogUtil.d(TAG,"Query "+(value == 0?"AID":"CAPK")+" List result:"+result);
if(result == 0) {
for (String aid : aidlist) {
LogUtil.d(TAG,(value == 0?"AID:":"CAPK:")+aid);
}
}
} catch (RemoteException e) {
throw new RuntimeException(e);
}
// for (AidEntity aidEntity : aidList) {
// LogUtil.d(TAG, "AID Entity :" + aidEntity.getAid());
// }
}
private void setPreviousTraceNum() {
@ -287,7 +238,7 @@ public class MainFragment extends DataBindingFragment {
mainViewModel.lastTrans.observe(getViewLifecycleOwner(), new Observer<PayDetail>() {
@Override
public void onChanged(PayDetail payDetail) {
if (payDetail == null) {
if(payDetail == null) {
return;
}
@ -301,29 +252,47 @@ public class MainFragment extends DataBindingFragment {
private void setUpECR() {
if (checkECRServiceAppExistOrNot()) {
// Initialize Modern ECR Manager
// modernECRManager.init();
////
//// // Observe navigation requests
// modernECRManager.getNavigationRequest().observe(getViewLifecycleOwner(), destinationId -> {
// if (destinationId != null) {
// delayFunctionCall(() -> isRouteValidAndNavigateToRoute(destinationId));
// }
// });
showShortToast("ECR Service initialized");
if(!SystemParamsOperation.getInstance().isSetupEcr()){
initECR();
delayFunctionCall(this::createECRInstance);
SystemParamsOperation.getInstance().setSetupEcr(true);
onReceivedEcrCommand();
} else {
onReceivedEcrCommand();
}
} else {
Toast.makeText(getContext(), "ECR Service Not Found!", Toast.LENGTH_SHORT).show();
}
}
// Legacy ECR methods removed
private void createECRInstance() {
//
// currently will test with Bluetooth , afterward will switch to VSP mode
if(SystemParamsOperation.getInstance().isBluetoothMode()) {
Bundle bundle = new Bundle();
bundle.putString(ECRConstant.Configuration.MODE, ECRConstant.Mode.Bluetooth);
bundle.putString(ECRConstant.Configuration.TYPE, ECRConstant.Type.MASTER);
bundle.putString(ECRConstant.Configuration.BLUETOOTH_MAC_ADDRESS, "");
// mainViewModel.ecrConnectionStatus.setValue(ECRConnectionStatus.CREATED);
ECRHelper.INSTANCE.connect(bundle);
showShortToast("ECR service is created!");
} else {
Bundle bundle = new Bundle();
bundle.putString(ECRConstant.Configuration.MODE, ECRConstant.Mode.VSP);
bundle.putString(ECRConstant.Configuration.TYPE, ECRConstant.Type.MASTER); // MASTER
ECRHelper.INSTANCE.connect(bundle);
// mainViewModel.ecrConnectionStatus.setValue(ECRConnectionStatus.CREATED);
showShortToast("ECR service is created!");
}
}
private void updateButtonStatus() {
mainViewModel.settlementStatus.setValue(SystemParamsOperation.getInstance().getSettlementStatus());
mainViewModel.kPayStatus.setValue(SystemParamsOperation.getInstance().getQRPayStatus());
mainViewModel.voidStatus.setValue(SystemParamsOperation.getInstance().getVoidStatus());
mainViewModel.kPayStatus.setValue(SystemParamsOperation.getInstance().getWavePayStatus());
}
private void setUpCarouselImages() {
@ -332,16 +301,16 @@ public class MainFragment extends DataBindingFragment {
imgList.clear();
if (imgUrls == null || imgUrls.isEmpty()) {
if(imgUrls == null || imgUrls.isEmpty() ) {
String defaultUrl = getResourceString(R.string.txt_default_carousel_img_url);
imgList.add(new SlideModel(defaultUrl, "", ScaleTypes.CENTER_CROP));
imgList.add(new SlideModel(defaultUrl,"", ScaleTypes.CENTER_CROP));
imgSlider.setImageList(imgList);
return;
}
ArrayList<String> urls = TMSUtil.getInstance().convertToArray(imgUrls);
for (String url : urls) {
imgList.add(new SlideModel(url.trim(), "", ScaleTypes.CENTER_CROP));
for(String url : urls) {
imgList.add(new SlideModel(url.trim(),"", ScaleTypes.CENTER_CROP));
}
@ -349,10 +318,11 @@ public class MainFragment extends DataBindingFragment {
}
private boolean checkECRServiceAppExistOrNot() {
PackageInfo packageInfo;
try {
packageInfo = requireActivity().getPackageManager().getPackageInfo("com.kizzy.ecrservice", 0);
packageInfo = requireActivity().getPackageManager().getPackageInfo("com.pos.ecr.service", 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
@ -362,6 +332,7 @@ public class MainFragment extends DataBindingFragment {
}
@Override
protected DataBindingConfig getDataBindingConfig() {
@ -371,9 +342,11 @@ public class MainFragment extends DataBindingFragment {
}
private void checkPrinter() {
if (PrintHelper.getInstance().paperRollStatus() == 2) {
} else if (PrintHelper.getInstance().paperRollStatus() == 4) {
}
else if (PrintHelper.getInstance().paperRollStatus() == 4) {
mainViewModel.playAtOnce.setValue(false);
showPrinterAlertDialog(getResourceString(R.string.txt_paper_roll_not_ready), new DialogCallback() {
@ -389,32 +362,168 @@ public class MainFragment extends DataBindingFragment {
}
});
// startSound(getResourceString(R.string.txt_audio_printer_alert));
} else if (PrintHelper.getInstance().paperRollStatus() == 1) {
} else if (PrintHelper.getInstance().paperRollStatus() == 1) {
if (mainViewModel.playAtOnce.getValue() != null && !mainViewModel.playAtOnce.getValue()) {
if( mainViewModel.playAtOnce.getValue() != null && !mainViewModel.playAtOnce.getValue()) {
startSound(getResourceString(R.string.txt_audio_paper_ready_alert));
mainViewModel.playAtOnce.setValue(true);
}
} else if (PrintHelper.getInstance().paperRollStatus() == 0) {
LogUtil.d(TAG, "Printer not found! ");
LogUtil.d(TAG,"Printer not found!");
// showDeclineDialog(getResourceString(R.string.txt_alert_printer_not_found));
}
}
private void isRouteValidAndNavigateToRoute(int routeId) {
if (Objects.requireNonNull(getNavController(Constants.NAV_HOST_ID).getCurrentDestination()).getId() == R.id.nav_main) {
getNavController(Constants.NAV_HOST_ID).navigate(routeId);
} else {
sharedViewModel.isEcr.postValue(false);
sharedViewModel.isEcrFinished.postValue(true);
ECRHelper.INSTANCE.send(getResourceString(R.string.txt_finish_current_process).getBytes());
showDeclineDialog(getResourceString(R.string.txt_finish_current_process));
}
}
// ECR Legacy methods removed
/**
* init ECR service
*/
private void initECR() {
ECRHelper.INSTANCE.registerECRListener();
ECRHelper.INSTANCE.setOnBindSuccess(() -> {
ECRHelper.INSTANCE.registerECRListener();
LogUtil.d(TAG, "on bind success!");
return null;
});
ECRHelper.INSTANCE.setOnBindFailure(() -> {
LogUtil.d(TAG, "on bind failure!");
return null;
});
ECRHelper.INSTANCE.setOnECRConnected(() -> {
delayFunctionCall(() -> mainViewModel.ecrConnectionStatus.postValue(ECRConnectionStatus.CONNECTED));
LogUtil.d(TAG, "On ECR Connected!");
return null;
});
ECRHelper.INSTANCE.setOnECRDisconnected((integer, s) -> {
delayFunctionCall(() -> mainViewModel.ecrConnectionStatus.postValue(ECRConnectionStatus.DISCONNECTED));
LogUtil.d(TAG, "On ECR Disconnected! Code:" + integer + ":Msg:" + s);
return null;
});
ECRHelper.INSTANCE.bindECRService();
LogUtil.d(TAG,"Bind ECR Service successfully!");
}
private void onReceivedEcrCommand() {
ECRHelper.INSTANCE.setOnECRReceive(bytes -> {
String msg = new String(bytes, StandardCharsets.UTF_8);
LogUtil.d(TAG, "Received : " + msg);
if (sharedViewModel.isEcrFinished.getValue() != null) {
if (sharedViewModel.isEcrFinished.getValue()) {
ECRAction(msg);
}
} else {
ECRAction(msg);
}
return null;
});
}
/**
* @param msg ECR Transaction Type
*/
private void ECRAction(String msg) {
// LogUtil.d(TAG, "ECR msg here : " + msg);
String ecrKey = SystemParamsOperation.getInstance().getEcrKey().toUpperCase();
String pkgName = BuildConfig.APPLICATION_ID;
String serialNo = TerminalUtil.getInstance().getSerialNo();
ResultOf<Transactions> result = ECRProcess.INSTANCE.parseECRRequest(ecrKey,pkgName,serialNo,msg);
if (result instanceof ResultOf.Success) {
Transactions trans = ((ResultOf.Success<Transactions>) result).getValue();
CoreUtils.getInstance(sharedViewModel).logTrans(trans);
sharedViewModel.ecrCMD.postValue(trans.getCMD());
sharedViewModel.ecrTrans.postValue(trans);
switch (Objects.requireNonNull(trans.getCMD())) {
case ECHO:
CoreUtils.getInstance(sharedViewModel).setUpECREchoTest();
break;
case SALE:
if (CoreUtils.getInstance(sharedViewModel).setUpECRSale(trans)) {
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
}
break;
case VOID:
if(!SystemParamsOperation.getInstance().getVoidStatus()) {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(trans,"Void is disabled!");
return;
}
if (CoreUtils.getInstance(sharedViewModel).setUpECRVoid(trans)) {
delayFunctionCall(() -> {
if(Objects.requireNonNull(getNavController(Constants.NAV_HOST_ID).getCurrentDestination()).getId() == R.id.nav_main) {
setToolBarTitle(getResourceString(R.string.menu_sale_void));
}
isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_inputPasswordFragment);
});
}
break;
case CASH_ADVANCE: {
if (CoreUtils.getInstance(sharedViewModel).setUpECRCashAdvance(trans)) {
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
}
break;
}
case QR_SALE: {
if (CoreUtils.getInstance(sharedViewModel).setUpECRQR(trans)) {
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_QRConnectingFragment));
}
break;
}
case SETTLEMENT: {
if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(trans,"Settlement is disabled!");
return;
}
CoreUtils.getInstance(sharedViewModel).setUpECRSettlement();
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_inputPasswordFragment));
break;
}
default:
showDeclineDialog("No Action found on \n" + trans.getCMD());
break;
}
} else {
String errorMsg = ((ResultOf.Failure) result).getMessage();
showDeclineDialog("No Action found on \n" + errorMsg);
}
}
private void navigateToAmount() {
routeId = R.id.action_nav_main_to_inputAmountFragment;
@ -429,25 +538,25 @@ public class MainFragment extends DataBindingFragment {
mainViewModel.observeSettlementPOS();
observeLastTrans = payDetail -> {
if (payDetail == null) {
if(payDetail == null) {
return;
}
// SystemParamsOperation.getInstance().saveSerialNumber(payDetail.getVoucherNo());
// SystemParamsOperation.getInstance().saveInvoiceNumber(payDetail.getInvoiceNo());
if (lastPay != null) {
if(lastPay != null) {
Date lastPayDate = POSUtil.getInstance().getDateByString(lastPay.getTransDate());
Date observePayDate = POSUtil.getInstance().getDateByString(payDetail.getTransDate());
if (lastPayDate.compareTo(observePayDate) < 0) {
if(lastPayDate.compareTo(observePayDate) < 0) {
payDetail = lastPay;
}
}
// LogUtil.d(TAG,"TransDetail :"+payDetail.getTransType() + "- Trans Time :"+payDetail.getTransDate());
if (payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value) {
if(payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value){
return;
}
@ -471,7 +580,7 @@ public class MainFragment extends DataBindingFragment {
String configRawDay = SystemParamsOperation.getInstance().getClearBatchDay();
if (configRawDay != null && !configRawDay.trim().isEmpty()) {
if(configRawDay != null && !configRawDay.trim().isEmpty()) {
try {
configDay = Integer.parseInt(configRawDay);
} catch (Exception e) {
@ -481,7 +590,7 @@ public class MainFragment extends DataBindingFragment {
}
if (configTimer != null && !configTimer.trim().isEmpty() && checkValidTime(configTimer.trim())) {
if(configTimer != null && !configTimer.trim().isEmpty() && checkValidTime(configTimer.trim())) {
configTime = configTimer.trim();
}
Date configDateTime = POSUtil.getInstance().getDateTime(configTime);
@ -491,22 +600,22 @@ public class MainFragment extends DataBindingFragment {
Date yesterdayDate = POSUtil.getInstance().getYesterdayDate();
if (today.compareTo(transDate) == 0) {
if(today.compareTo(transDate) == 0) {
// LogUtil.d(TAG,"Last Trans is Today!");
// LogUtil.d(TAG,"date current :!"+current);
// LogUtil.d(TAG,"date config :!"+configDateTime);
// Today
if (current.compareTo(configDateTime) > 0) {
if(current.compareTo(configDateTime) > 0) {
// clear batch and force update param
// LogUtil.d(TAG,"Last Trans is Today! Config time is passed!");
// if (!SystemParamsOperation.getInstance().isClearBatch()) {
if (checkSyncTrans() || !SystemParamsOperation.getInstance().isClearBatch()) {
if (checkSyncTrans() || !SystemParamsOperation.getInstance().isClearBatch() ) {
// LogUtil.d(TAG,"Clearing....");
if (!SystemParamsOperation.getInstance().getSettlementStatus()) {
clearBatchAndDownload(configDay, payDetail);
if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
clearBatchAndDownload(configDay,payDetail);
}
}
@ -519,35 +628,36 @@ public class MainFragment extends DataBindingFragment {
} else {
// LogUtil.d(TAG,"Last Trans is Before Today!");
Date yest;
if (configTime.equals("00:00")) {
if(configTime.equals("00:00")) {
yest = configDateTime;
} else {
yest = yesterdayConfigDateTime;
}
Date lastTransDateTime = POSUtil.getInstance().getDateByTransDateTime(lastTransDate, lastTransTime);
Date lastTransDateTime = POSUtil.getInstance().getDateByTransDateTime(lastTransDate,lastTransTime);
// LogUtil.d(TAG,"Compare Result : "+lastTransDateTime.compareTo(yest));
if (yest.compareTo(lastTransDateTime) < 0) {
if(yest.compareTo(lastTransDateTime) < 0) {
// LogUtil.d(TAG,"Trans is yesterday, but after config time, no action!");
} else {
// LogUtil.d(TAG,"Trans is yesterday, before config time,");
// if(!checkSyncTrans()) {
// LogUtil.d(TAG,"Clearing....");
if (!SystemParamsOperation.getInstance().getSettlementStatus()) {
clearBatchAndDownload(configDay, payDetail);
if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
clearBatchAndDownload(configDay,payDetail);
}
// }
}
}
};
if (mainViewModel.lastTrans.hasActiveObservers()) {
if(mainViewModel.lastTrans.hasActiveObservers()) {
mainViewModel.lastTrans.removeObserver(observeLastTrans);
}
mainViewModel.lastTrans.observe(getViewLifecycleOwner(), observeLastTrans);
mainViewModel.lastTrans.observe(getViewLifecycleOwner(),observeLastTrans);
}
@ -556,16 +666,16 @@ public class MainFragment extends DataBindingFragment {
mainViewModel.allTrans.observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetails) {
if (payDetails == null || payDetails.isEmpty()) {
if(payDetails == null || payDetails.isEmpty()) {
return;
}
PayDetail tempPay = payDetails.get(0);
for (int i = 0; i < payDetails.size(); i++) {
for (int i = 0; i < payDetails.size() ; i++) {
Date tempDate = POSUtil.getInstance().getDateByString(tempPay.getTransDate());
Date indexDate = POSUtil.getInstance().getDateByString(payDetails.get(i).getTransDate());
if (tempDate.compareTo(indexDate) > 0) {
if(tempDate.compareTo(indexDate) > 0) {
// if before
tempPay = payDetails.get(i);
}
@ -588,7 +698,7 @@ public class MainFragment extends DataBindingFragment {
private boolean checkSyncTrans() {
String transDateString = SystemParamsOperation.getInstance().getSyncTransDate();
Date today = POSUtil.getInstance().getCurrentDate();
if (transDateString == null || transDateString.isEmpty()) {
if(transDateString == null || transDateString.isEmpty()) {
return true;
}
Date transDate = POSUtil.getInstance().getDateByString(transDateString);
@ -597,7 +707,8 @@ public class MainFragment extends DataBindingFragment {
}
private void clearBatchAndDownload(int configDay, PayDetail payDetail) {
private void clearBatchAndDownload(int configDay,PayDetail payDetail) {
Date yesterday = POSUtil.getInstance().getYesterdayDate();
@ -606,11 +717,11 @@ public class MainFragment extends DataBindingFragment {
Date transDate;
if (list == null || list.size() == 0) {
if(list == null || list.size() == 0) {
return;
}
for (PayDetail pay : list) {
for (PayDetail pay:list) {
/*
* To Hold One day transaction!
* */
@ -618,11 +729,11 @@ public class MainFragment extends DataBindingFragment {
transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
if (pay.getTransactionType() == TransactionsType.SALE.value) {
if (lastInputDay.compareTo(transDate) > 0) {
if(lastInputDay.compareTo(transDate) > 0) {
mainViewModel.deletePayDetail(pay);
}
} else {
if (yesterday.compareTo(transDate) > 0) {
if(yesterday.compareTo(transDate) > 0 ) {
mainViewModel.deletePayDetail(pay);
}
}
@ -634,11 +745,11 @@ public class MainFragment extends DataBindingFragment {
mainViewModel.deleteTrans.observe(getViewLifecycleOwner(), lists -> {
Date transDate;
if (lists == null || lists.size() == 0) {
if(lists == null || lists.size() == 0) {
return;
}
for (PayDetail pay : lists) {
for (PayDetail pay:lists) {
/*
* To Hold One day transaction!
* */
@ -648,7 +759,7 @@ public class MainFragment extends DataBindingFragment {
// LogUtil.d(TAG,"Yesterday Date: "+yesterday.toString());
// LogUtil.d(TAG,"Compare result :"+yesterday.compareTo(transDate));
if (yesterday.compareTo(transDate) > 0) {
if(yesterday.compareTo(transDate) > 0) {
mainViewModel.deletePayDetail(pay);
}
@ -657,11 +768,11 @@ public class MainFragment extends DataBindingFragment {
mainViewModel.preAuthTrans.observe(getViewLifecycleOwner(), lists -> {
Date transDate;
if (lists == null || lists.size() == 0) {
if(lists == null || lists.size() == 0) {
return;
}
for (PayDetail pay : lists) {
for (PayDetail pay:lists) {
transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
@ -677,21 +788,21 @@ public class MainFragment extends DataBindingFragment {
*
* Need to think about his problem .... Nov 7, 2024
* */
if (!SystemParamsOperation.getInstance().isClearBatch()) {
if(!SystemParamsOperation.getInstance().isClearBatch()) {
// downloadParams(payDetail.getTransType(),String.valueOf(payDetail.getTransNum()),TMSUpdate.UPDATE,false);
}
}
private void generateMockQR() {
String transDate = "24/12/25";
String transTime = "12:06:30";
TradeData tradeData = MockData.getInstance().generateMockDataWithTime(TransactionsType.MMQR, 1, transDate, transTime);
PayDetail payDetail = tradeData.getPayDetail();
sharedViewModel.insertPayDetail(payDetail);
LogUtil.d(TAG, "------------------- Inserted Mocked Data ------------------");
LogUtil.d(TAG, "trans date : " + payDetail.getTransDate() + "- Trans Time: " + payDetail.getTransTime());
}
// private void generateMockPreAuth() {
// String transDate = "01/03/24";
// String transTime = "12:27:30";
// TradeData tradeData = MockData.getInstance().generateMockDataWithTime(TransactionsType.PRE_AUTH_SALE, AidlConstantsV2.CardType.IC.getValue(),transDate,transTime);
// PayDetail payDetail = tradeData.getPayDetail();
// sharedViewModel.insertPayDetail(payDetail);
// LogUtil.d(TAG,"------------------- Inserted Mocked Data ------------------");
// LogUtil.d(TAG,"trans date : "+payDetail.getTransDate() +"- Trans Time: "+payDetail.getTransTime());
// }
public class ClickEvent {
@ -701,16 +812,16 @@ public class MainFragment extends DataBindingFragment {
if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
} else if (TMSUtil.getInstance().checkParams().isStatus() == ValidityStatus.FAILURE) {
showDeclineDialog(getResourceString(R.string.txt_please_download_config) + "\n" + TMSUtil.getInstance().checkParams().getMessage());
} else if (SystemParamsOperation.getInstance().isNeedSettlement()) {
showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkParams().getMessage());
} else if(SystemParamsOperation.getInstance().isNeedSettlement()) {
AlertXDialog.getInstance().showDialog(requireContext(), getResourceString(R.string.title_need_settle), getResourceString(R.string.txt_do_you_want_to_continue), () -> {
int mainToDashboard = R.id.action_nav_main_to_dashboardTransFragment;
safeRouteTo(R.id.nav_main, mainToDashboard, Constants.NAV_HOST_ID);
safeRouteTo(R.id.nav_main,mainToDashboard,Constants.NAV_HOST_ID);
});
} else {
int mainToDashboard = R.id.action_nav_main_to_dashboardTransFragment;
safeRouteTo(R.id.nav_main, mainToDashboard, Constants.NAV_HOST_ID);
safeRouteTo(R.id.nav_main,mainToDashboard,Constants.NAV_HOST_ID);
}
}
@ -719,10 +830,10 @@ public class MainFragment extends DataBindingFragment {
if (mainViewModel.payDetailSingle.getValue() != null) {
mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue());
} else if (TMSUtil.getInstance().checkParams().isStatus() == ValidityStatus.FAILURE) {
showDeclineDialog(getResourceString(R.string.txt_please_download_config) + "\n" + TMSUtil.getInstance().checkParams().getMessage());
showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkParams().getMessage());
} else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
} else if (SystemParamsOperation.getInstance().isNeedSettlement()) {
} else if(SystemParamsOperation.getInstance().isNeedSettlement()) {
AlertXDialog.getInstance().showDialog(requireContext(), getResourceString(R.string.title_need_settle), getResourceString(R.string.txt_do_you_want_to_continue), () -> {
processBatch();
sharedViewModel.transactionsType.setValue(TransactionsType.SALE);
@ -733,23 +844,11 @@ public class MainFragment extends DataBindingFragment {
} else {
processBatch();
sharedViewModel.transactionsType.setValue(TransactionsType.SALE);
sharedViewModel.setTransMenu(TransMenu.SALE);
sharedViewModel.processCode.postValue(ProcessCode.SALE_PURCHASE + ProcessCode.SMART + ProcessCode.TO_ACCOUNT);
navigateToAmount();
}
}
public void onClickQR() {
if (TMSUtil.getInstance().checkQRParams().isStatus() == ValidityStatus.FAILURE) {
showDeclineDialog(getResourceString(R.string.txt_please_download_config) + "\n" + TMSUtil.getInstance().checkQRParams().getMessage());
} else {
routeId = R.id.action_nav_main_to_qrFragment;
safeNavigateToRouteId();
}
}
public void onClickQRPay() {
String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress();
@ -779,13 +878,11 @@ public class MainFragment extends DataBindingFragment {
if (mainViewModel.payDetailSingle.getValue() != null) {
mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue());
}
// else if (TMSUtil.getInstance().checkParams().isStatus() == ValidityStatus.FAILURE) {
// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkParams().getMessage());
// } else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
// showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
// }
else {
} else if (TMSUtil.getInstance().checkParams().isStatus() == ValidityStatus.FAILURE) {
showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkParams().getMessage());
} else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
} else {
sharedViewModel.settlementType.setValue(SettlementType.NORMAL);
sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT);
sharedViewModel.setTransMenu(TransMenu.SETTLEMENT);
@ -825,29 +922,5 @@ public class MainFragment extends DataBindingFragment {
safeNavigateToRouteId();
}
}
public void onClickVoid() {
if (mainViewModel.payDetailSingle.getValue() != null) {
mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue());
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
sharedViewModel.setTransactionsType(TransactionsType.VOID);
// sharedViewModel.transMenu.postValue(TransMenu.TRANSACTIONS);
sharedViewModel.setTransMenu(TransMenu.TRANSACTIONS);
routeId = R.id.action_nav_main_to_inputPasswordFragment;
safeRouteTo(currentId(), routeId, hostId());
}
}
public void onClickHistory(){
routeId = R.id.action_nav_main_to_dashboardHistoryFragment;
safeRouteTo(currentId(), routeId, hostId());
}
public void onClickReport() {
routeId = R.id.action_nav_main_to_manageFunctionFragment;
safeRouteTo(currentId(), routeId, hostId());
}
}
}

View File

@ -11,7 +11,6 @@ import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.utsmm.kbz.service.AutoSettleService;
import com.utsmyanmar.baselib.db.model.EmvDetail;
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest;
import com.utsmyanmar.baselib.network.model.sirius.SiriusResponse;
@ -23,6 +22,7 @@ import com.utsmyanmar.paylibs.reversal.ReversalAction;
import com.utsmyanmar.paylibs.reversal.ReversalListener;
import com.utsmyanmar.paylibs.system.SingleLiveEvent;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.service.SmileSettleService;
import com.utsmm.kbz.util.enums.ReversalStatus;
import com.utsmm.kbz.util.ecr.ECRConnectionStatus;
@ -58,9 +58,6 @@ public class MainViewModel extends ViewModel {
public MutableLiveData<Boolean> kPayStatus = new MutableLiveData<>();
public MutableLiveData<Boolean> voidStatus = new MutableLiveData<>();
public SingleLiveEvent<String> disabledMsg = new SingleLiveEvent<>();
public SingleLiveEvent<List<PayDetail>> settlementPOS = new SingleLiveEvent<>();
@ -78,8 +75,8 @@ public class MainViewModel extends ViewModel {
private BroadcastReceiver dataReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(AutoSettleService.ACTION_DATA_RECEIVED)) {
String data = intent.getStringExtra(AutoSettleService.EXTRA_DATA);
if (intent.getAction().equals(SmileSettleService.ACTION_DATA_RECEIVED)) {
String data = intent.getStringExtra(SmileSettleService.EXTRA_DATA);
}
}
@ -93,15 +90,13 @@ public class MainViewModel extends ViewModel {
playAtOnce.setValue(false);
LocalBroadcastManager.getInstance(context).registerReceiver(dataReceiver,
new IntentFilter(AutoSettleService.ACTION_DATA_RECEIVED));
new IntentFilter(SmileSettleService.ACTION_DATA_RECEIVED));
settlementStatus.setValue(SystemParamsOperation.getInstance().getSettlementStatus());
kPayStatus.setValue(SystemParamsOperation.getInstance().getQRPayStatus());
kPayStatus.setValue(SystemParamsOperation.getInstance().getWavePayStatus());
disabledMsg.setValue(SystemParamsOperation.getInstance().getDisabledMsg());
voidStatus.setValue(SystemParamsOperation.getInstance().getVoidStatus());
}
@Override

View File

@ -5,6 +5,5 @@ public enum CardTransactionType {
MPU,
EMV,
MAG,
FALLBACK,
MOCK
FALLBACK
}

View File

@ -1,156 +0,0 @@
package com.utsmm.kbz.service;
import android.app.AlarmManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import androidx.core.app.NotificationCompat;
import com.utsmm.kbz.R;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import java.util.Calendar;
public class AutoAlarmReceiver extends BroadcastReceiver {
private static final String TAG = AutoAlarmReceiver.class.getSimpleName();
private static final String WAKE_LOCK_TAG = "KBZAutoSettle::AlarmWakeLock";
private static final String NOTIFICATION_CHANNEL_ID = "AUTO_SETTLEMENT_ALARM";
@Override
public void onReceive(Context context, Intent intent) {
LogUtil.d(TAG, "AutoAlarmReceiver triggered at: " + new java.util.Date().toString());
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
wakeLock.acquire(60000);
try {
showAlarmTriggeredNotification(context);
scheduleNextDayAlarm(context);
try {
Intent serviceIntent = new Intent(context, AutoSettleService.class);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent);
LogUtil.d(TAG, "AutoSettleService started as foreground service");
} else {
context.startService(serviceIntent);
LogUtil.d(TAG, "AutoSettleService started successfully");
}
} catch (Exception e) {
LogUtil.e(TAG, "Failed to start AutoSettleService: " + e.getMessage());
e.printStackTrace();
}
} finally {
// Release wake lock
if (wakeLock.isHeld()) {
wakeLock.release();
}
}
}
private void scheduleNextDayAlarm(Context context) {
try {
String timeStr = SystemParamsOperation.getInstance().getClearBatchTime();
LogUtil.d(TAG, " Rescheduling next day's alarm for timeStr: " + timeStr);
if (timeStr == null || timeStr.trim().isEmpty()) {
LogUtil.d(TAG, "Clear batch time is empty, cannot reschedule");
return;
}
String[] parts = timeStr.trim().split(":");
if (parts.length != 2) {
LogUtil.d(TAG, "Invalid time format: " + timeStr);
return;
}
int hour = Integer.parseInt(parts[0]);
int minute = Integer.parseInt(parts[1]);
// Validate time range
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
LogUtil.d(TAG, "Invalid time values - hour: " + hour + ", minute: " + minute);
return;
}
// Set up next day's alarm
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, 1); // Next day
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
long nextTriggerTime = calendar.getTimeInMillis();
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager == null) {
LogUtil.e(TAG, "AlarmManager is null, cannot reschedule");
return;
}
Intent intent = new Intent(context, AutoAlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
1001,
intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
if (alarmManager.canScheduleExactAlarms()) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextTriggerTime, pendingIntent);
} else {
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextTriggerTime, pendingIntent);
}
} else {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextTriggerTime, pendingIntent);
}
} else {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextTriggerTime, pendingIntent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void showAlarmTriggeredNotification(Context context) {
try {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"Auto Settlement Alarms",
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("Notifications for auto settlement alarm triggers");
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Auto Settlement Triggered")
.setContentText("Auto settlement alarm triggered at " + new java.util.Date().toString())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true);
notificationManager.notify(1001, builder.build());
} catch (Exception e) {
LogUtil.e(TAG, "Failed to show alarm notification: " + e.getMessage());
}
}
}

View File

@ -1,692 +0,0 @@
package com.utsmm.kbz.service;
import android.annotation.SuppressLint;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.lifecycle.Observer;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.google.gson.Gson;
import com.utsmm.kbz.MainActivity;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmm.kbz.util.enums.TransactionStatus;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmm.kbz.BuildConfig;
import com.utsmm.kbz.R;
import com.utsmm.kbz.ui.settlement.SettlementViewModel;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers;
import retrofit2.HttpException;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.batch_upload.BatchListener;
import com.utsmyanmar.paylibs.batch_upload.BatchUploadProcess;
import com.utsmyanmar.paylibs.isobuilder.ISOMode;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion;
import com.utsmyanmar.paylibs.model.MsgField;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.QRSettleData;
import com.utsmyanmar.paylibs.model.SettleData;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.network.ISOCallback;
import com.utsmyanmar.paylibs.network.ISOSocket;
import com.utsmyanmar.paylibs.sign_on.EchoTestProcess;
import com.utsmyanmar.paylibs.sign_on.SignOnListener;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.MessageType;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.HostName;
import com.utsmyanmar.paylibs.utils.iso_utils.BitmapConfig;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionType;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.params.Params;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@AndroidEntryPoint
public class AutoSettleService extends Service {
private static final String TAG = AutoSettleService.class.getSimpleName();
public static final String ACTION_DATA_RECEIVED = BuildConfig.APPLICATION_ID + ".ACTION_DATA_RECEIVED";
public static final String EXTRA_DATA = BuildConfig.APPLICATION_ID + ".EXTRA_DATA";
private Handler handler;
private SettlementViewModel settlementViewModel;
// Flags to prevent infinite loops
private boolean regularSettlementCompleted = false;
private boolean qrSettlementCompleted = false;
private boolean posHasData = false; // true = POS actually ran and has result
private boolean qrHasData = false; // true = QR actually ran and has result
// Observers to keep reference for cleanup
private Observer<List<PayDetail>> regularSettlementObserver;
private Observer<List<PayDetail>> qrSettlementObserver;
private int i = 0;
private boolean flag = false;
@Inject
Repository repository;
private PayDetail pendingPayDetail = null;
private Bundle pendingQrData = null;
private boolean posSettlementReady = false;
private boolean qrSettlementReady = false;
ArrayList<PayDetail> payDetails = new ArrayList<>();
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
private void startForegroundService() {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Create notification channel for Android 8+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"Auto Settlement Service",
NotificationManager.IMPORTANCE_LOW // Use LOW importance for foreground service
);
channel.setDescription("Auto settlement background service");
notificationManager.createNotificationChannel(channel);
}
// Create foreground notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Auto Settlement Active")
.setContentText("Processing scheduled settlement...")
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true) // Make it non-dismissible
.setAutoCancel(false);
// Start foreground service
startForeground(1002, builder.build());
}
private void createNotification() {
NotificationManager mNotificationManager = (NotificationManager)getSystemService( NOTIFICATION_SERVICE ) ;
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext() , default_notification_channel_id ) ;
mBuilder.setContentTitle( "Auto Settlement Running" ) ;
mBuilder.setContentText( "Processing transactions..." ) ;
mBuilder.setTicker( "Auto Settlement Service" ) ;
mBuilder.setSmallIcon(R.drawable. ic_launcher_foreground ) ;
mBuilder.setAutoCancel( true ) ;
if (android.os.Build.VERSION. SDK_INT >= android.os.Build.VERSION_CODES. O ) {
int importance = NotificationManager. IMPORTANCE_HIGH ;
NotificationChannel notificationChannel = new NotificationChannel( NOTIFICATION_CHANNEL_ID , "AUTO_SETTLEMENT_CHANNEL" , importance) ;
mBuilder.setChannelId( NOTIFICATION_CHANNEL_ID ) ;
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel) ;
}
assert mNotificationManager != null;
mNotificationManager.notify(( int ) System. currentTimeMillis () , mBuilder.build()) ;
}
private void sendDataToViewModel(String data) {
Intent intent = new Intent(ACTION_DATA_RECEIVED);
intent.putExtra(EXTRA_DATA, data);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
@SuppressLint("CheckResult")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtil.d(TAG, "<<<<<<<<<<<<<<< Auto Settlement Service Started >>>>>>>>>>>>>>>>.");
try {
// Start as foreground service for Android 8+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
startForegroundService();
}
sendDataToViewModel("Auto settlement initiated");
// Also create regular notification
createNotification();
if (SystemParamsOperation.getInstance().getSettlementStatus()) {
performSettlement();
// regularSettlementCompleted = true;
performQRSettlement();
} else {
LogUtil.d(TAG, "Settlement is disabled in system parameters");
stopSelf();
}
} catch (Exception e) {
LogUtil.e(TAG, "Error in onStartCommand: " + e.getMessage());
e.printStackTrace();
stopSelf();
}
return START_NOT_STICKY;
}
private void performSettlement() {
if (regularSettlementCompleted) {
return;
}
final ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder(
ISOVersion.VERSION_1993,
ISOMode.BOTH_HEADER_TPDU,
HostName.BPC
).build();
regularSettlementObserver = new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> list) {
if (regularSettlementCompleted) {
return;
}
payDetails.clear();
payDetails.addAll(list);
regularSettlementCompleted = true;
repository.getSettlementPOS().removeObserver(this);
int saleCount = 0;
long saleAmount = 0L;
int preCount = 0;
long preAmount = 0L;
int refundCount = 0;
long refundAmount = 0L;
int caCount = 0;
long caAmount = 0L;
if (list != null && !list.isEmpty()) {
for (PayDetail pay : list) {
if (pay.getTransactionType() == TransactionType.SALE && !pay.isCanceled) {
saleCount++;
saleAmount += pay.getAmount();
} else if (pay.getTransactionType() == TransactionType.PRE_SALE_COMPLETE && !pay.isCanceled) {
preCount++;
preAmount += pay.getAmount();
} else if (pay.getTransactionType() == TransactionType.REFUND) {
refundCount++;
refundAmount += pay.getAmount();
} else if (pay.getTransactionType() == TransactionType.CASH_ADVANCE) {
caCount++;
caAmount += pay.getAmount();
}
}
}
TradeData tradeData = Params.newTrade(true);
PayDetail payDetail = tradeData.getPayDetail();
String bitmap = BitmapConfig.BPC_SETTLEMENT;
payDetail.setTransType(TransactionsType.SETTLEMENT.name);
payDetail.setTransactionType(TransactionType.SETTLEMENT);
if(!flag) {
payDetail.setProcessCode(TransactionsType.SETTLEMENT.processCode);
} else {
bitmap = BitmapConfig.BPC_SETTLEMENT_TRAILER;
payDetail.setProcessCode("910000");
}
payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum());
SettleData settleData = new SettleData(
saleCount, saleAmount, preCount, preAmount, refundCount, refundAmount, caCount, caAmount);
payDetail.setSettleDataObj(settleData);
long totalAmount = saleAmount + preAmount + refundAmount + caAmount;
String settlementData;
if (refundAmount != 0L) {
long creditTotal = saleAmount + preAmount + caAmount;
long subTotal = creditTotal - refundAmount;
if (subTotal < 0L) {
settlementData = "D" + String.format(Locale.getDefault(), "%012d", Math.abs(subTotal));
} else {
settlementData = "C" + String.format(Locale.getDefault(), "%012d", subTotal);
}
} else {
settlementData = "C" + String.format(Locale.getDefault(), "%012d", totalAmount);
}
if(totalAmount == 0 && (saleCount == 0 || preCount == 0 || refundCount == 0 || caCount == 0)) {
posSettlementReady = true;
posHasData = false;
checkAndLaunch();
checkIfBothSettlementsComplete();
return;
}
payDetail.setSettleData(settlementData);
payDetail.setAmount(totalAmount);
tradeData.setPayDetail(payDetail);
tradeData.setField60(SystemParamsOperation.getInstance().getCurrentBatchNum());
byte[] sendBytes = isoMsgX.buildISOPackets(tradeData, bitmap, MessageType.SETTLEMENT);
ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, new ISOCallback() {
@Override
public void onReceive(byte[] bytes, int length) {
Map<String, MsgField> responseMap = isoMsgX.parseISOPackets(bytes, length);
if (responseMap != null) {
String resultStr = "";
try {
resultStr = responseMap.get("F039").getDataStr();
} catch (NullPointerException e) {
e.printStackTrace();
payDetail.setIsNeedReversal(true);
return;
}
payDetail.setTradeAnswerCode(resultStr);
if (TextUtils.equals(resultStr, Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, Constant.ANSWER_CODE_APPROVED)) {
payDetail.setIsNeedReversal(false);
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
payDetail.setIsNeedReversal(!flag);
}
}
}
@Override
public void onError(String msg) {
ISOSocket.getInstance().switchIp();
ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, this);
}
@Override
public void onComplete() {
LogUtil.d(TAG, "Auto settlement transaction completed successfully");
if(payDetail.getIsNeedReversal()) {
flag = true;
batchUploadProcess();
} else {
flag = false;
if (!list.isEmpty()) {
for (PayDetail p : list) {
repository.deletePayDetail(p);
}
}
repository.insertPayDetail(payDetail);
networkCutOver(payDetail);
}
}
});
}
};
repository.getSettlementPOS().observeForever(regularSettlementObserver);
}
private void batchUploadProcess() {
if(payDetails == null || payDetails.isEmpty()){
regularSettlementCompleted = false;
performSettlement();
return;
}
PayDetail payDetail = payDetails.get(i);
TradeData tradeData = new TradeData();
tradeData.setPayDetail(payDetail);
BatchUploadProcess.getInstance().enqueue(tradeData).startBatchUpload(new BatchListener() {
@Override
public void onSuccessBatch() {
if (i < payDetails.size() - 1) {
LogUtil.d(TAG, "Pay detail Size:" + payDetails.size());
LogUtil.d(TAG, "Count value:" + i);
i++;
batchUploadProcess();
} else {
regularSettlementCompleted = false;
performSettlement();
}
LogUtil.e(TAG, "Batch Upload Success");
}
@Override
public void onFailBatch() {
LogUtil.e(TAG, "Batch Upload Fail");
}
});
}
private void performQRSettlement() {
if (qrSettlementCompleted) {
return;
}
qrSettlementObserver = new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetailList) {
if (qrSettlementCompleted) {
return;
}
qrSettlementCompleted = true;
repository.getTransactionHistory().removeObserver(this);
if (payDetailList != null) {
int qrSaleCount = 0;
long qrSaleAmount = 0;
int qrRefundCount = 0;
long qrRefundAmount = 0;
ArrayList<PayDetail> qrTransactionsList = new ArrayList<>();
ArrayList<PayDetail> qrTransListAll = new ArrayList<>();
try {
for (PayDetail payDetail : payDetailList) {
if ((payDetail.getTransactionType() == TransactionsType.MMQR.value
|| payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value)
&& payDetail.getQrTransStatus() == 1) {
qrTransactionsList.add(payDetail);
if (payDetail.getTransactionType() == TransactionsType.MMQR.value) {
qrSaleCount++;
qrSaleAmount += payDetail.getAmount();
} else if (payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
qrRefundCount++;
qrRefundAmount += payDetail.getAmount();
}
} else if (payDetail.getTransactionType() == TransactionsType.MMQR.value
|| payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
qrTransListAll.add(payDetail);
}
}
} catch (IllegalStateException e) {
LogUtil.e(TAG, "QR Auto Settlement: Database cursor error - likely due to large data size: " + e);
qrSettlementReady = true;
qrHasData = false;
checkAndLaunch();
checkIfBothSettlementsComplete();
return;
}
if (!qrTransactionsList.isEmpty()) {
LogUtil.d(TAG, "Processing QR Auto Settlement with " + qrTransactionsList.size() + " transactions");
long totalAmount = qrSaleAmount - qrRefundAmount;
// Increment batch number for QR settlement
SystemParamsOperation.getInstance().getIncrementBatchNo();
// Create settlement data for QR transactions
SettleData settleData = new SettleData(
qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
TradeData tradeData = Params.newTrade(false);
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setSettleDataObj(settleData);
payDetail.setTransactionType(TransactionsType.MMQR_SETTLEMENT.value);
payDetail.setTransType(TransactionsType.MMQR_SETTLEMENT.name);
payDetail.setAmount(totalAmount);
payDetail.setTradeAnswerCode("000");
payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum());
payDetail.setQrSettleData(QRSettleData.convertFromPayDetail(qrTransactionsList));
// Insert QR settlement record
repository.insertPayDetail(payDetail);
// Delete settled QR transactions
for (PayDetail pay : qrTransactionsList) {
repository.deletePayDetail(pay);
}
// Delete all other QR transactions (failed ones)
for (PayDetail pay : qrTransListAll) {
repository.deletePayDetail(pay);
}
// Push e-receipt data using repository directly
try {
EReceiptRequest request = EReceiptUtil.getInstance().generateQRSettlement(payDetail, QRSettleData.convertFromPayDetail(qrTransactionsList));
sendEReceipt(request);
LogUtil.d(TAG, "QR Settlement e-receipt data prepared and sent");
} catch (Exception e) {
LogUtil.e(TAG, "Error preparing QR settlement e-receipt: " + e.getMessage());
}
try {
// Create QR settlement data bundle
Bundle qrData = new Bundle();
qrData.putInt("QR_SALE_COUNT", qrSaleCount);
qrData.putLong("QR_SALE_AMOUNT", qrSaleAmount);
qrData.putInt("QR_REFUND_COUNT", qrRefundCount);
qrData.putLong("QR_REFUND_AMOUNT", qrRefundAmount);
qrData.putLong("QR_TOTAL_AMOUNT", totalAmount);
qrData.putSerializable("QR_TRANS_LIST", qrTransactionsList);
// Use notification-based approach to reliably launch the app
pendingQrData = qrData;
qrHasData = true;
// launchAppWithSettlementResult("AUTO_QR_SETTLEMENT", null, qrData,false);
} catch (Exception e) {
LogUtil.e(TAG, "Error launching app for QR settlement: " + e.getMessage());
qrHasData = false;
e.printStackTrace();
}
LogUtil.d(TAG, "QR Auto Settlement completed successfully");
} else {
LogUtil.d(TAG, "No QR transactions found for auto settlement");
qrHasData = false;
}
}
qrSettlementReady = true;
checkAndLaunch();
checkIfBothSettlementsComplete();
}
};
repository.getTransactionHistory().observeForever(qrSettlementObserver);
}
private void checkIfBothSettlementsComplete() {
if (regularSettlementCompleted && qrSettlementCompleted) {
LogUtil.d(TAG, "Both settlements completed, stopping service");
stopSelf();
}
}
@Override
public void onCreate() {
super.onCreate();
handler = new Handler();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
// Clean up observers to prevent memory leaks
if (regularSettlementObserver != null && repository != null) {
repository.getSettlementPOS().removeObserver(regularSettlementObserver);
}
if (qrSettlementObserver != null && repository != null) {
repository.getTransactionHistory().removeObserver(qrSettlementObserver);
}
}
private void networkCutOver(PayDetail payDetail) {
EchoTestProcess.getInstance().enqueueCutOver().startSignOn(new SignOnListener() {
@Override
public void onSuccessSignOn() {
pendingPayDetail = payDetail;
posHasData = true;
posSettlementReady = true;
checkAndLaunch();
checkIfBothSettlementsComplete();
}
@Override
public void onFailureSignOn(Integer resultCode) {
LogUtil.d(TAG,"Failure Cut Over message: "+resultCode);
// POS done but cutover failed still mark ready
posSettlementReady = true;
posHasData = false;
checkAndLaunch();
checkIfBothSettlementsComplete();
}
@Override
public void onNetworkFailSignOn(String message) {
LogUtil.d(TAG,"Network Fail Cut Over message: "+message);
posSettlementReady = true;
posHasData = false;
checkAndLaunch();
checkIfBothSettlementsComplete();
}
});
}
private void checkAndLaunch() {
// !!!! need to add flag, if don't want both at once
if (!posSettlementReady || !qrSettlementReady) {
LogUtil.d(TAG, "Waiting for both settlements... POS=" + posSettlementReady + " QR=" + qrSettlementReady);
return;
}
LogUtil.d(TAG, "Both settlements ready. POS has data=" + posHasData + ", QR has data=" + qrHasData);
if (!posHasData && !qrHasData) {
LogUtil.d(TAG, "No settlement data to display");
return;
}
launchMainActivity();
}
private void launchMainActivity() {
try {
Intent launchIntent = new Intent(this, MainActivity.class);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (posHasData && pendingPayDetail != null) {
launchIntent.putExtra("AUTO_SETTLEMENT", true);
launchIntent.putExtra("EXTRA_TRANSACTION_TYPE", TransactionsType.SETTLEMENT.value);
launchIntent.putExtra("EXTRA_PAY_DETAIL", pendingPayDetail);
}
if (qrHasData && pendingQrData != null) {
launchIntent.putExtra("AUTO_QR_SETTLEMENT", true);
launchIntent.putExtra("EXTRA_QR_TRANSACTION_TYPE", TransactionsType.MMQR_SETTLEMENT.value);
launchIntent.putExtras(pendingQrData);
}
PendingIntent pendingIntent = PendingIntent.getActivity(
this,
(int) System.currentTimeMillis(),
launchIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"SETTLEMENT_COMPLETE", "Settlement Complete", NotificationManager.IMPORTANCE_HIGH);
channel.setDescription("Auto settlement completion notifications");
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "SETTLEMENT_COMPLETE")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Auto Settlement Complete")
.setContentText("Tap to view settlement results and print receipt")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setFullScreenIntent(pendingIntent, true);
notificationManager.notify(2001, builder.build());
// Reset state
pendingPayDetail = null;
pendingQrData = null;
posSettlementReady = false;
qrSettlementReady = false;
posHasData = false;
qrHasData = false;
startActivity(launchIntent);
} catch (Exception e) {
LogUtil.e(TAG, "Error launching MainActivity: " + e.getMessage());
e.printStackTrace();
}
}
private void sendEReceipt(EReceiptRequest request) {
try {
LogUtil.d(TAG, "Sending e-receipt: " + new Gson().toJson(request));
repository.sendReceipt(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> LogUtil.d(TAG, "E-Receipt sent successfully: " + response.getMessage()),
error -> {
if (error instanceof HttpException) {
HttpException httpEx = (HttpException) error;
try {
String errorJson = httpEx.response().errorBody().string();
LogUtil.e(TAG, "E-Receipt error: " + errorJson);
} catch (Exception e) {
LogUtil.e(TAG, "E-Receipt send failed: " + error.getMessage());
}
} else {
LogUtil.e(TAG, "E-Receipt send failed: " + error.getMessage());
}
}
);
} catch (Exception e) {
LogUtil.e(TAG, "Error sending e-receipt: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,14 @@
package com.utsmm.kbz.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class SmileAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// Start the service to send the API request
Intent serviceIntent = new Intent(context, SmileSettleService.class);
context.startService(serviceIntent);
}
}

View File

@ -0,0 +1,183 @@
package com.utsmm.kbz.service;
import android.annotation.SuppressLint;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmm.kbz.BuildConfig;
import com.utsmm.kbz.R;
import com.utsmm.kbz.ui.settlement.SettlementViewModel;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import com.utsmyanmar.paylibs.utils.LogUtil;
// Temporarily disabled Hilt
// @AndroidEntryPoint
public class SmileSettleService extends Service {
private static final String TAG = SmileSettleService.class.getSimpleName();
public static final String ACTION_DATA_RECEIVED = BuildConfig.APPLICATION_ID + ".ACTION_DATA_RECEIVED";
public static final String EXTRA_DATA = BuildConfig.APPLICATION_ID + ".EXTRA_DATA";
private Handler handler;
private SettlementViewModel settlementViewModel;
@Inject
Repository repository;
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
private void createNotification() {
NotificationManager mNotificationManager = (NotificationManager)getSystemService( NOTIFICATION_SERVICE ) ;
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext() , default_notification_channel_id ) ;
mBuilder.setContentTitle( "Alarm manager is running!" ) ;
mBuilder.setContentText( "Wiping out the transactions!" ) ;
mBuilder.setTicker( "Notification Listener Service Example" ) ;
mBuilder.setSmallIcon(R.drawable. ic_launcher_foreground ) ;
mBuilder.setAutoCancel( true ) ;
if (android.os.Build.VERSION. SDK_INT >= android.os.Build.VERSION_CODES. O ) {
int importance = NotificationManager. IMPORTANCE_HIGH ;
NotificationChannel notificationChannel = new NotificationChannel( NOTIFICATION_CHANNEL_ID , "NOTIFICATION_CHANNEL_NAME" , importance) ;
mBuilder.setChannelId( NOTIFICATION_CHANNEL_ID ) ;
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel) ;
}
assert mNotificationManager != null;
mNotificationManager.notify(( int ) System. currentTimeMillis () , mBuilder.build()) ;
}
private void sendDataToViewModel(String data) {
Intent intent = new Intent(ACTION_DATA_RECEIVED);
intent.putExtra(EXTRA_DATA, data);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
@SuppressLint("CheckResult")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Perform the Settlement request here
// ...
LogUtil.d(TAG,"<<<<<<<<<<<<<<< This action was called >>>>>>>>>>>>>>>>.");
sendDataToViewModel("Hello there");
createNotification();
// Observer<List<PayDetail>> settleObserver = new Observer<List<PayDetail>>() {
// @Override
// public void onChanged(List<PayDetail> list) {
//
//
// if(list == null || list.size() == 0) {
// LogUtil.d(TAG, "Settle is null");
// return;
// }
// LogUtil.d(TAG,"Size Settle : "+list.size());
//
// for (PayDetail pay:list) {
// repository.deletePayDetail(pay);
// }
//
//
// }
// };
//
//
// repository.getSettlementPOS().observeForever(settleObserver);
//
// repository.getSettlementPOS().removeObserver(settleObserver);
//
// Observer<List<PayDetail>> deleteTransObserver = new Observer<List<PayDetail>>() {
// @Override
// public void onChanged(List<PayDetail> lists) {
// if(lists == null || lists.size() == 0) {
// return;
// }
//
// LogUtil.d(TAG,"Size Delete Trans : "+lists.size());
// for (PayDetail pay:lists) {
// repository.deletePayDetail(pay);
// }
// }
// };
//
// repository.getDeleteTrans(SystemParamsOperation.getInstance().getCurrentBatchNum()).observeForever(deleteTransObserver);
//
// repository.getDeleteTrans(SystemParamsOperation.getInstance().getCurrentBatchNum()).removeObserver(deleteTransObserver);
//
//
// try{
// handler.post(new Runnable() {
// @Override
// public void run() {
// // Create and show the dialog
// AlertDialog.Builder builder = new AlertDialog.Builder(SmileSettleService.this);
// builder.setTitle("Auto Settle!")
// .setMessage("Settlement process is going to start!")
// .setPositiveButton("OK", new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface dialog, int which) {
// // Handle OK button click
// dialog.dismiss(); // Dismiss the dialog
// }
// })
// .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface dialog, int which) {
// // Handle Cancel button click
// dialog.dismiss(); // Dismiss the dialog
// }
// });
//
//
// AlertDialog dialog = builder.create();
//// dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
//// dialog.show();
// }
// });
// }catch (Exception e){
// e.printStackTrace();
// }
return START_NOT_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
handler = new Handler();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}

View File

@ -1,24 +1,17 @@
package com.utsmm.kbz.ui;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import com.google.gson.Gson;
import com.google.gson.stream.MalformedJsonException;
import com.utsmm.kbz.config.Constants;
import com.nexgo.downloadkey.downloadflow.DownloadFEntity;
import com.nexgo.downloadkey.downloadflow.DownloadFlow;
import com.nexgo.downloadkey.downloadflow.DownloadFlowProcessListener;
import com.nexgo.downloadkey.downloadflow.DownloadFlowResultEntity;
import com.nexgo.downloadkey.downloadflow.DownloadResult;
import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusError;
@ -30,14 +23,11 @@ import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.baselib.util.URLValidator;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.MainViewModel;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.data.model.TMSUpdate;
import com.utsmm.kbz.databinding.FragmentSettingsModernBinding;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.settlement.SettlementViewModel;
import com.utsmm.kbz.util.tms.TMSUtil;
@ -58,10 +48,9 @@ public class SettingsFragment extends DataBindingFragment {
private SettlementViewModel settlementViewModel;
private MainViewModel mainViewModel;
private SharedViewModel sharedViewModel;
private int count = 0;
// Data binding will handle view access automatically
private FragmentSettingsModernBinding binding;
@Inject
@ -69,13 +58,14 @@ public class SettingsFragment extends DataBindingFragment {
@Override
protected void initViewModel() {
// Initialize ViewModels in initViewModel as per pattern
settlementViewModel = getFragmentScopeViewModel(SettlementViewModel.class);
mainViewModel = getFragmentScopeViewModel(MainViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
// This is the key method that links the XML and fragment properly
return new DataBindingConfig(R.layout.fragment_settings_modern, 0, null)
.addBindingParam(BR.click, new ClickEvent());
}
@ -99,23 +89,30 @@ public class SettingsFragment extends DataBindingFragment {
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
try {
SystemParamsOperation.getInstance().setDemoStatus(false);
LogUtil.d(TAG, "onViewCreated called");
// Get the binding from the base class - this is automatically created
binding = (FragmentSettingsModernBinding) mBinding;
updateDemoSettings();
LogUtil.d(TAG, "Updating settings...");
updateSettings();
LogUtil.d(TAG, "Settings fragment initialized successfully");
} catch (Exception e) {
LogUtil.e(TAG, "Error initializing fragment: " + e.getMessage());
e.printStackTrace();
}
}
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon("Settings");
try {
setToolBarTitleWithBackIcon("Settings");
LogUtil.d(TAG, "Settings screen resumed");
} catch (Exception e) {
LogUtil.e(TAG, "Error in onResume: " + e.getMessage());
}
}
@ -147,20 +144,21 @@ public class SettingsFragment extends DataBindingFragment {
private void updateDemoSettings() {
boolean isDemo = SystemParamsOperation.getInstance().getDemoStatus();
// binding.demoSwitch.setChecked(isDemo);
// binding.demoSummary.setText(isDemo ?
// "Demo mode active - Test transactions without real processing" :
// "Simulator mode active - Real transaction processing");
binding.demoSwitch.setChecked(isDemo);
binding.demoSummary.setText(isDemo ?
"Demo mode active - Test transactions without real processing" :
"Simulator mode active - Real transaction processing");
}
private void updateAlertSoundSettings() {
boolean isEnabled = SystemParamsOperation.getInstance().isAlertSound();
// binding.alertSoundSwitch.setChecked(isEnabled);
// binding.alertSoundSummary.setText(isEnabled ?
// "Sound alerts enabled for notifications" :
// "Sound alerts disabled - Silent mode");
binding.alertSoundSwitch.setChecked(isEnabled);
binding.alertSoundSummary.setText(isEnabled ?
"Sound alerts enabled for notifications" :
"Sound alerts disabled - Silent mode");
}
private void updateReversalSettings() {
boolean isEnabled = SystemParamsOperation.getInstance().isReversalOn();
binding.reversalSwitch.setChecked(isEnabled);
@ -171,10 +169,10 @@ public class SettingsFragment extends DataBindingFragment {
private void updateMultiHostSettings() {
boolean isEnabled = SystemParamsOperation.getInstance().isMultiHost();
// binding.multiHostSwitch.setChecked(isEnabled);
// binding.multiHostSummary.setText(isEnabled ?
// "Multiple host support enabled" :
// "Single host mode - Primary host only");
binding.multiHostSwitch.setChecked(isEnabled);
binding.multiHostSummary.setText(isEnabled ?
"Multiple host support enabled" :
"Single host mode - Primary host only");
}
private void updateTmsAddressSettings() {
@ -185,12 +183,6 @@ public class SettingsFragment extends DataBindingFragment {
// ClickEvent class for data binding - this is the proper pattern
public class ClickEvent {
public void onHostConfigClick(){
int routeId = R.id.action_nav_settings_to_hostConfigFragment;
int currentId = R.id.nav_settings;
int hostId = Constants.NAV_HOST_ID;
safeRouteTo(currentId, routeId, hostId);
}
public void onVersionClick() {
try {
@ -205,16 +197,6 @@ public class SettingsFragment extends DataBindingFragment {
}
}
public void onInjectKeyClick() {
try {
LogUtil.d(TAG, "Inject Key clicked");
Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)
.navigate(R.id.action_nav_settings_to_injectKeyFragment);
} catch (Exception e) {
LogUtil.e(TAG, "Error navigating to inject key: " + e.getMessage());
}
}
public void onDemoClick() {
try {
boolean newValue = !SystemParamsOperation.getInstance().getDemoStatus();
@ -296,6 +278,7 @@ public class SettingsFragment extends DataBindingFragment {
public void onUpdateConfigClick() {
try {
LogUtil.d(TAG, "Update config clicked");
settlementViewModel.getSettlementPOS().observe(getViewLifecycleOwner(), payDetails -> {
try {
if (payDetails != null && payDetails.size() > 0) {
@ -316,17 +299,6 @@ public class SettingsFragment extends DataBindingFragment {
}
}
public void onClearBatchClick() {
try {
sharedViewModel.transactionsType.postValue(TransactionsType.CLEAR_BATCH);
sharedViewModel.setTransMenu(TransMenu.CLEAR_BATCH);
Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)
.navigate(R.id.inputPasswordFragment);
} catch (Exception e) {
LogUtil.e(TAG, "Error in clear batch click: " + e.getMessage());
}
}
public void onTmsConfigClick() {
try {
LogUtil.d(TAG, "TMS Config clicked");
@ -462,4 +434,4 @@ public class SettingsFragment extends DataBindingFragment {
showDeclineDialog(getResourceString(R.string.txt_error_occurred));
}
}
}
}

View File

@ -3,8 +3,6 @@ package com.utsmm.kbz.ui.adapters;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
@ -296,12 +294,9 @@ public class MyBindingAdapter {
@BindingAdapter({"isTrace"})
public static void checkIsTraceOrInvoice(TextView textView, PayDetail payDetail) {
if(payDetail.getTransactionType() == TransactionsType.MMQR.value || payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
// textView.setText("INV:"+payDetail.getInvoiceNo());
//tempo fix for qr trace num
textView.setText("TRC:"+payDetail.getVoucherNo());
textView.setText("INV:"+payDetail.getInvoiceNo());
} else {
textView.setText("TRC:"+payDetail.getVoucherNo());
}
}
}

View File

@ -1,78 +0,0 @@
package com.utsmm.kbz.ui.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.ItemQrPayButtonBinding;
import com.utsmm.kbz.ui.qr_pay.QRPayItem;
import java.util.List;
public class QRPayAdapter extends RecyclerView.Adapter<QRPayAdapter.ViewHolder> {
public interface OnItemClickListener {
void onItemClick(int position);
}
private final List<QRPayItem> items;
private final OnItemClickListener listener;
public QRPayAdapter(List<QRPayItem> item, OnItemClickListener listener) {
this.items = item;
this.listener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemQrPayButtonBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_qr_pay_button,
parent,
false
);
return new ViewHolder(binding);
}
private final int[] colors = new int[]{
R.color.colorPrimary,
R.color.amber,
R.color.forestGreen
};
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
QRPayItem item = items.get(position);
holder.binding.setItem(item);
holder.binding.executePendingBindings();
holder.binding.btnItem.setOnClickListener(v -> {
if(item.isActive && listener != null){
listener.onItemClick(position);
}
});
}
@Override
public int getItemCount() {
return items == null ? 0 : items.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
final ItemQrPayButtonBinding binding;
public ViewHolder(@NonNull ItemQrPayButtonBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}

View File

@ -8,19 +8,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum;
import com.utsmm.kbz.ui.pinpad.PinPadViewModel;
import com.utsmm.kbz.util.TransactionUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TerminalUtil;
import com.utsmyanmar.baselib.util.TimeoutCallback;
import com.utsmyanmar.checkxread.checkcard.CheckCardResultX;
import com.utsmyanmar.checkxread.model.CardDataX;
import com.utsmyanmar.checkxread.readcard.MPUXReadCard;
import com.utsmyanmar.checkxread.readcard.ReadCardResultX;
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.checkxread.util.CardTypeX;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
@ -45,8 +37,6 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
private TransProcessViewModel transProcessViewModel;
private PinPadViewModel pinPadViewModel;
private static final String TAG = CardWaitingFragment.class.getSimpleName();
private static final int cardWaitingTimeOut = 60;
@ -69,8 +59,6 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
transProcessViewModel = getFragmentScopeViewModel(TransProcessViewModel.class);
pinPadViewModel = getFragmentScopeViewModel(PinPadViewModel.class);
}
@Override
@ -118,13 +106,9 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
public void onClickManualEntry() {
routeId = R.id.action_cardWaitingFragment_to_manualEntryFragment;
safeNavigateToRouteId();
}
// showSingleInfoDialogAutoHide("Coming Soon!");
public void onClickTap() {
cardReadViewModel.setCardTransactionType(CardTransactionType.MOCK);
routeId = R.id.action_cardWaitingFragment_to_processingCardFragment;
routeId = R.id.action_cardWaitingFragment_to_manualEntryFragment;
safeNavigateToRouteId();
}
}
@ -148,12 +132,6 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
if(sharedViewModel.getIsFallback().getValue() != null && sharedViewModel.getIsFallback().getValue()) {
cardReadViewModel.setCheckCardAlertMsg("Fallback!\nPlease stripe!",false);
setupCardReadProcess(true);
}else if(sharedViewModel.getIsSeePhone().getValue() != null && sharedViewModel.getIsSeePhone().getValue()) {
cardReadViewModel.setCheckCardAlertMsg("Please Tap!",false);
setupCardReadProcess(true);
} else if(sharedViewModel.getIsCardAppBlock().getValue() != null && sharedViewModel.getIsCardAppBlock().getValue()) {
cardReadViewModel.setCheckCardAlertMsg("Magstripe not allowed!",false);
setupCardReadProcess(true);
} else {
setupCardReadProcess(false);
}
@ -165,7 +143,6 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
super.onPause();
sharedViewModel.setIsFallback(false);
sharedViewModel.setIsSeePhone(false);
// cardReadViewModel.cancelCheckCard();
@ -237,8 +214,6 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
private void initCheckCard(boolean isFallback) {
int waitTimeout = cardWaitingTimeOut + 5;
// int allType = AidlConstants.CardType.NFC.getValue() | AidlConstants.CardType.IC.getValue() | AidlConstants.CardType.MAGNETIC.getValue();
//
//
@ -252,23 +227,12 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
// }
// }
HashSet<CardSlotTypeEnum> allType = new HashSet<>();
allType.clear();
if(sharedViewModel.getIsSeePhone().getValue() != null && sharedViewModel.getIsSeePhone().getValue()) {
allType.add(CardSlotTypeEnum.RF);
waitTimeout = 20;
} else {
allType.add(CardSlotTypeEnum.ICC1);
allType.add(CardSlotTypeEnum.RF);
allType.add(CardSlotTypeEnum.SWIPE);
}
allType.add(CardSlotTypeEnum.ICC1);
allType.add(CardSlotTypeEnum.RF);
// int allType = AidlConstants.CardType.IC.getValue() | AidlConstants.CardType.MAGNETIC.getValue();
cardReadViewModel.startCheckXProcessNex(allType, waitTimeout, new CheckCardResultX() {
cardReadViewModel.startCheckXProcessNex(allType, cardWaitingTimeOut + 5, new CheckCardResultX() {
@Override
public void onSuccess(CardTypeX cardType, boolean isMPU) {
LogUtil.d(TAG,"**** on success *****");
@ -290,20 +254,17 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
} else if (isFallback && cardType == CardTypeX.MAG) {
/* do fallback transactions */
sharedViewModel.isEmv.postValue(false);
sharedViewModel.isEmv.setValue(false);
cardReadViewModel.setCardTransactionType(CardTransactionType.FALLBACK);
} else if (cardType == CardTypeX.IC || cardType == CardTypeX.NFC) {
cardReadViewModel.cardTypeData.postValue(cardType.value);
if(isMPU) {
sharedViewModel.isEmv.setValue(false);
cardReadViewModel.setCardTransactionType(CardTransactionType.MPU);
} else {
// cardReadViewModel.cardTypeData.postValue(cardType.value);
cardReadViewModel.cardTypeData.postValue(cardType.value);
cardReadViewModel.setCardTransactionType(CardTransactionType.EMV);
}
// cardReadViewModel.cardTypeData.postValue(cardType.value);
// cardReadViewModel.setCardTransactionType(CardTransactionType.EMV);
}
delayFunctionCall(()->{
routeId = R.id.action_cardWaitingFragment_to_processingCardFragment;

View File

@ -106,10 +106,6 @@ public class ConfirmTransactionFragment extends DataBindingFragment implements D
setToolBarTitleWithBackIcon(getResourceString(R.string.txt_title_trans_info));
isMerchantCopy = true;
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
if (sharedViewModel.getTransMenu().getValue() != TransMenu.REPRINT) {
sharedViewModel.suppressReprintButtons.setValue(false);
}
if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW) {
@ -126,17 +122,9 @@ public class ConfirmTransactionFragment extends DataBindingFragment implements D
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.REPRINT) {
sharedViewModel.reprintTransTypeMsg.setValue(getResourceString(R.string.txt_print_merchant_copy));
boolean suppress = sharedViewModel.suppressReprintButtons.getValue() != null
&& sharedViewModel.suppressReprintButtons.getValue();
if (suppress) {
sharedViewModel.oneBtnLayout.setValue(8);
sharedViewModel.twoBtnLayout.setValue(8);
sharedViewModel.reprintBtnLayout.setValue(8);
} else {
sharedViewModel.oneBtnLayout.setValue(8);
sharedViewModel.twoBtnLayout.setValue(8);
sharedViewModel.reprintBtnLayout.setValue(sharedViewModel.printerDisabled.getValue() != null && sharedViewModel.printerDisabled.getValue() ? 8 : 0);
}
sharedViewModel.oneBtnLayout.setValue(8);
sharedViewModel.twoBtnLayout.setValue(8);
sharedViewModel.reprintBtnLayout.setValue(0);
// printReceipt(true);
@ -270,10 +258,6 @@ public class ConfirmTransactionFragment extends DataBindingFragment implements D
}
public void onPrint() {
if (!SystemParamsOperation.getInstance().getPrinterEnabled()) {
showDeclineDialog("Printer is disabled!");
return;
}
printReceipt(isMerchantCopy);

View File

@ -0,0 +1,295 @@
package com.utsmm.kbz.ui.core_ui;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import com.sunmi.pay.hardware.aidlv2.bean.EMVCandidateV2;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.ui.ListDialog;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.params.Params;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.EmvReadCardViewModel;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.core_viewmodel.TransProcessViewModel;
import com.utsmm.kbz.ui.pre_auth.PreAuthCompViewModel;
import com.utsmm.kbz.util.enums.EmvReadStatus;
import com.utsmm.kbz.util.ecr.CoreUtils;
import java.util.ArrayList;
import java.util.List;
import com.utsmyanmar.paylibs.utils.LogUtil;
/**
* Currently this class is not used
*/
public class EmvReadCardFragment extends DataBindingFragment {
private EmvReadCardViewModel emvReadCardViewModel;
private SharedViewModel sharedViewModel;
private PreAuthCompViewModel preAuthCompViewModel;
private TransProcessViewModel transProcessViewModel;
private ListDialog mListDialog;
private static final String TAG = EmvReadCardFragment.class.getSimpleName();
private int routeID;
private int popBackID;
private List<PayDetail> lists = new ArrayList<>();
private String currentCardNo = "";
@Override
protected void initViewModel() {
emvReadCardViewModel = getFragmentScopeViewModel(EmvReadCardViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
preAuthCompViewModel = getFragmentScopeViewModel(PreAuthCompViewModel.class);
transProcessViewModel = getFragmentScopeViewModel(TransProcessViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_emv_card_read, BR.emv,emvReadCardViewModel)
.addBindingParam(BR.click,new ClickEvent());
}
@Override
protected int currentId() {
return 0;
}
@Override
protected int hostId() {
return 0;
}
@Override
protected int routeId() {
return 0;
}
@Override
public void onResume() {
super.onResume();
observeData();
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
@Override
public void onDestroy() {
super.onDestroy();
emvReadCardViewModel.terminateTrans();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
emvReadCardViewModel.startProcess();
emvReadCardViewModel.resultStatus.observe(getViewLifecycleOwner(), new Observer<EmvReadStatus>() {
@Override
public void onChanged(EmvReadStatus emvReadStatus) {
switch (emvReadStatus){
case SUCCESS: emvReadCardViewModel.isButtonVisible.postValue(true);
currentCardNo = emvReadCardViewModel.cardNum.getValue();
break;
case FAIL: cardReadFailAction(emvReadCardViewModel.errorCode.getValue()); break;
case SELECT_APP: observeList();break;
}
}
});
}
private void cardReadFailAction(String message){
try{
if(message == null){
message = getResourceString(R.string.txt_card_read_fail);
}else if(message.contains(":")){
message = message.split(":")[1];
}
getNavController(Constants.NAV_HOST_ID).navigate(popBackID);
showSingleInfoDialog(message);
if(sharedViewModel.isEcr.getValue() != null){
if(sharedViewModel.isEcr.getValue()){
sharedViewModel.isEcr.postValue(false);
sharedViewModel.isEcrFinished.postValue(true);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(message);
// ECRHelper.INSTANCE.send(message.getBytes());
}
}
}catch (IllegalArgumentException e){
e.printStackTrace();
getNavController(Constants.NAV_HOST_ID).navigate(popBackID);
}
}
private void observeData(){
switch (sharedViewModel.transactionsType.getValue()){
case PRE_AUTH_COMPLETE:
observePreAuthComp();
routeID = R.id.action_emvReadCardFragment_to_inputRRNFragment;
popBackID = R.id.action_emvReadCardFragment_to_nav_main;
break;
case PRE_AUTH_VOID:
routeID = R.id.action_emvReadCardFragment_to_inputRRNFragment;
popBackID = R.id.action_emvReadCardFragment_to_nav_main;
break;
}
}
private void observePreAuthComp() {
preAuthCompViewModel.getPreAuthComData().observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetails) {
if(payDetails.size() > 0) {
LogUtil.d(TAG,"Pre Auth Comp size :"+payDetails.size());
lists.addAll(payDetails);
sharedViewModel.payDetailList.postValue(payDetails);
} else {
LogUtil.d(TAG,"Pre Auth Comp data not found!");
}
}
});
}
private boolean checkPreAuthCardNo() {
if(sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_VOID) {
return sharedViewModel.payDetail.getValue().getCardNo().equals(currentCardNo);
} else if (sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_COMPLETE) {
for(PayDetail payDetail: lists) {
if(payDetail.getCardNo().equals(currentCardNo)){
sharedViewModel.cardNo.postValue(currentCardNo);
return true;
}else{
LogUtil.d(TAG,"not found 1!");
}
}
return false;
}
else {
return true;
}
}
private void observeList(){
emvReadCardViewModel.emvList.observe(getViewLifecycleOwner(), new Observer<List<EMVCandidateV2>>() {
@Override
public void onChanged(List<EMVCandidateV2> emvCandidateV2s) {
showListDialog(emvCandidateV2s);
}
});
}
private void showListDialog(List<EMVCandidateV2> list) {
if (mListDialog == null) {
mListDialog = new ListDialog(getContext());
mListDialog.setTitleText(R.string.index_select_app);
mListDialog.setCancelable(true);
mListDialog.setCanceledOnTouchOutside(true);
}
List<String> tempList = new ArrayList<>();
for (EMVCandidateV2 emvCandidateV2 : list) {
tempList.add(emvCandidateV2.appLabel);
}
mListDialog.setData(tempList);
mListDialog.setOnItemClickListener(
position -> {
emvReadCardViewModel.setEmvAppSelect(position);
}
);
try {
mListDialog.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private void buildCardData(){
TradeData tradeData = Params.newTrade(false);
PayDetail payDetails = tradeData.getPayDetail();
payDetails.setCardNo(emvReadCardViewModel.cardNum.getValue());
payDetails.setEXPDate(emvReadCardViewModel.expDate.getValue());
payDetails.setCardType(1);
payDetails.setAccountType("VISA");
payDetails.setCardHolderName("card holder");
// payDetails.setCardInfo();
transProcessViewModel.setTradeData(tradeData);
transProcessViewModel.transType.postValue(sharedViewModel.transactionsType.getValue());
}
private void checkRoute(){
buildCardData();
if(checkPreAuthCardNo()){
getNavController(Constants.NAV_HOST_ID).navigate(routeID);
}else{
showDeclineDialog("Mismatch Card No!");
}
}
public class ClickEvent {
public void onConfirm() {
checkRoute();
}
public void onCancel() {
if(sharedViewModel.isEcr.getValue() != null){
if(sharedViewModel.isEcr.getValue()){
sharedViewModel.isEcr.postValue(false);
sharedViewModel.isEcrFinished.postValue(true);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg("Canceled Transactions!");
// ECRHelper.INSTANCE.send("Canceled Transactions!".getBytes());
}
}
getNavController(Constants.NAV_HOST_ID).navigate(popBackID);
}
}
}

View File

@ -3,7 +3,6 @@ package com.utsmm.kbz.ui.core_ui;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -11,14 +10,12 @@ import androidx.appcompat.app.AlertDialog;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import com.utsmm.kbz.ui.core_viewmodel.CardReadViewModel;
import com.utsmm.kbz.ui.pinpad.PinPadViewModel;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.ui.CustomPinPadKeyboard;
import com.utsmyanmar.baselib.ui.ListDialog;
import com.utsmyanmar.baselib.util.CardDetectCallback;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.checkxread.util.CardTypeX;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
@ -44,8 +41,6 @@ public class EmvTransactionFragment extends DataBindingFragment {
private EmvTransactionProcessViewModel emvTransactionViewModel;
private CardReadViewModel cardReadViewModel;
private PinPadViewModel pinPadViewModel;
private SharedViewModel sharedViewModel;
@ -80,7 +75,6 @@ public class EmvTransactionFragment extends DataBindingFragment {
emvTransactionViewModel = getFragmentScopeViewModel(EmvTransactionProcessViewModel.class);
pinPadViewModel = getFragmentScopeViewModel(PinPadViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
cardReadViewModel = getFragmentScopeViewModel(CardReadViewModel.class);
}
@Override
@ -140,8 +134,6 @@ public class EmvTransactionFragment extends DataBindingFragment {
emvTransactionViewModel.customPinPadKeyboard = binding.customPinPad;
initSharedData();
initData();
@ -159,7 +151,6 @@ public class EmvTransactionFragment extends DataBindingFragment {
}
observeEmvResultStatus();
observePinWarning();
}
private boolean isNotManualTransaction() {
@ -212,20 +203,6 @@ public class EmvTransactionFragment extends DataBindingFragment {
});
break;
case SEE_PHONE:
isCardTaped("Please check your phone!",new CardDetectCallback() {
@Override
public void onComplete() {
sharedViewModel.setIsSeePhone(true);
navigateToCheckCard();
}
});
break;
case OTHER_INTERFACE:
sharedViewModel.set_errorFragmentMsg("Please use other interface!");
navigateToError();
break;
case PIN_PAD_CANCEL:
navigateToMain();
break;
@ -233,54 +210,15 @@ public class EmvTransactionFragment extends DataBindingFragment {
navigateToRRNScreen();
break;
case READ_CARD_RETRY:
LogUtil.d(TAG,"Card type :"+cardReadViewModel.cardTypeData.getValue());
if(cardReadViewModel.cardTypeData.getValue()!= null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.IC.value) {
isCardInserted(new CardDetectCallback() {
@Override
public void onComplete() {
sharedViewModel.setIsFallback(true);
navigateToCheckCard();
}
});
} else if(cardReadViewModel.cardTypeData.getValue() != null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.NFC.value) {
isCardTaped("Please try again",new CardDetectCallback() {
@Override
public void onComplete() {
sharedViewModel.setIsSeePhone(false);
navigateToCheckCard();
}
});
}
break;
case CARD_APP_BLOCKED:
if(cardReadViewModel.cardTypeData.getValue()!= null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.IC.value) {
isCardInserted(new CardDetectCallback() {
@Override
public void onComplete() {
sharedViewModel.setIsCardAppBlock(true);
navigateToCheckCard();
}
});
} else if(cardReadViewModel.cardTypeData.getValue() != null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.NFC.value) {
isCardTaped("Please try again",new CardDetectCallback() {
@Override
public void onComplete() {
sharedViewModel.setIsCardAppBlock(true);
navigateToCheckCard();
}
});
}
// sharedViewModel.set_errorFragmentMsg("Interface not found!");
// navigateToError();
sharedViewModel.set_errorFragmentMsg("Interface not found!");
navigateToError();
break;
case READ_CARD_NO_APP:
isCardTaped("Terminal has no APP!");
break;
case TRY_AGAIN:
// sharedViewModel.set_errorFragmentMsg("Please replace the card");
// navigateToError();
showSingleInfoDialog("Please check your phone!");
navigateToCheckCard();
sharedViewModel.set_errorFragmentMsg("Please replace the card");
navigateToError();
break;
case OFFLINE_DECLINE:
@ -351,15 +289,6 @@ public class EmvTransactionFragment extends DataBindingFragment {
});
}
private void observePinWarning() {
emvTransactionViewModel.pinRemainingCount.observe(getViewLifecycleOwner(), msg -> {
if (!TextUtils.isEmpty(msg)) {
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show();
emvTransactionViewModel.pinRemainingCount.setValue("");
}
});
}
private void observeEmvErrorCode() {
dismissLoadingDialog();
emvTransactionViewModel.errorCodeMsg.observe(getViewLifecycleOwner(), pair -> {

View File

@ -7,7 +7,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.ui.NumberKeyboard;
import com.utsmyanmar.baselib.util.CardDetectCallback;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TimeoutCallback;
@ -72,7 +71,7 @@ public class InputAmountFragment extends DataBindingFragment implements DataBind
super.onViewCreated(view, savedInstanceState);
// setUpTimer();
setUpTimer();
setupBackButtonPressDetection(this);
}
@ -99,22 +98,6 @@ public class InputAmountFragment extends DataBindingFragment implements DataBind
setToolBarTitleWithBackIcon(getResourceString(R.string.txt_subtitle_amount));
boolean decimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
boolean qrDecimalEnabled = SystemParamsOperation.getInstance().isQrDecimalEnable();
boolean isDecimalEnabled;
if(sharedViewModel.transactionsType.getValue() == TransactionsType.MMQR){
isDecimalEnabled = qrDecimalEnabled;
}else {
isDecimalEnabled = decimalEnabled;
}
View keyboardView = getView().findViewById(R.id.numberKeyboard);
if (keyboardView instanceof NumberKeyboard) {
((NumberKeyboard) keyboardView).setDecimalEnable(isDecimalEnabled);
}
if(sharedViewModel.isEcr.getValue() != null){
if(sharedViewModel.isEcr.getValue()){
@ -221,17 +204,7 @@ public class InputAmountFragment extends DataBindingFragment implements DataBind
if(isInputValid(Objects.requireNonNull(inputAmountViewModel.inputAmountView.getValue()))){
inputAmountViewModel.invalidAmountMsg.setValue("");
// boolean decimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
boolean cardDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
boolean qrDecimalEnabled = SystemParamsOperation.getInstance().isQrDecimalEnable();
boolean decimalEnabled;
if(sharedViewModel.transactionsType.getValue() == TransactionsType.MMQR){
decimalEnabled = qrDecimalEnabled;
}else {
decimalEnabled = cardDecimalEnabled;
}
boolean decimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
String inputValue = inputAmountViewModel.inputAmountView.getValue();
if (decimalEnabled) {

View File

@ -142,10 +142,6 @@ public class InputPasswordFragment extends DataBindingFragment implements DataBi
private void checkRoute() {
switch (Objects.requireNonNull(sharedViewModel.transactionsType.getValue())) {
case MMQR_REFUND:
inputPasswordViewModel.passwordType.setValue(InputPasswordType.SYSTEM);
routeId = R.id.action_inputPasswordFragment_to_QRRefundProcessFragment;
break;
case PRE_AUTH_COMPLETE_VOID:
inputPasswordViewModel.passwordType.setValue(InputPasswordType.SYSTEM);
sharedViewModel.transactionName.postValue(getResourceString(R.string.title_pre_auth_complete));
@ -176,7 +172,7 @@ public class InputPasswordFragment extends DataBindingFragment implements DataBi
break;
case REFUND:
inputPasswordViewModel.passwordType.setValue(InputPasswordType.SYSTEM);
routeId = R.id.action_inputPasswordFragment_to_inputAmountFragment;
routeId = R.id.action_inputPasswordFragment_to_selectRefundFragment;
break;
case PRE_AUTH_COMPLETE:
inputPasswordViewModel.passwordType.setValue(InputPasswordType.SYSTEM);
@ -184,7 +180,7 @@ public class InputPasswordFragment extends DataBindingFragment implements DataBi
break;
case SETTLEMENT:
inputPasswordViewModel.passwordType.setValue(InputPasswordType.SETTLEMENT);
routeId = R.id.action_inputPasswordFragment_to_selectSettlementFragment;
routeId = R.id.action_inputPasswordFragment_to_settlementTransactionFragment;
break;
case SETTING:
inputPasswordViewModel.passwordType.setValue(InputPasswordType.SETTING);

View File

@ -220,13 +220,11 @@ public class InputRRNFragment extends DataBindingFragment {
newPay = transProcessViewModel.getPayDetail();
}
newPay.setReferNo(rrnNo);
if(sharedViewModel.getTransMenu().getValue() == TransMenu.PRE_AUTH_FULL_VOID) {
newPay.setAmount(payDetail.getAmount());
}
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountFormat(payDetail.getAmount()));
newPay.setTradeDateTime(payDetail.getTradeDateTime());
if(isEmvTrans()) {
@ -313,9 +311,7 @@ public class InputRRNFragment extends DataBindingFragment {
}
newPay.setReferNo(rrnNo);
newPay.setApprovalCode(payDetail.getApprovalCode());
newPay.setTradeTime(payDetail.getTradeTime());
newPay.setTradeDate(payDetail.getTradeDate());
if(newPay.getAmount() > payDetail.getAmount()) {
newPay.setTradeAnswerCode("C1"); // ---> refer to BaseErrorCode class// ,
newPay.setTransType(sharedViewModel.transactionsType.getValue().name);
@ -479,19 +475,15 @@ public class InputRRNFragment extends DataBindingFragment {
}
private void refundProcessEmv(boolean isECR) {
rrnViewModel.searchPayDetail(cardNo, rrnNo).observe(getViewLifecycleOwner(), payDetail -> {
if (payDetail != null && isCurrentBatchUnsettled(payDetail)) {
terminatedTransRefund(isECR);
return;
}
PayDetail payDetail = emvTransactionProcessViewModel.getPayDetail();
payDetail.setReferNo(rrnNo);
PayDetail newPay = emvTransactionProcessViewModel.getPayDetail();
newPay.setReferNo(rrnNo);
emvTransactionProcessViewModel.setPayDetail(newPay);
sharedViewModel.rrNNo.setValue(rrnNo);
callNextScreen();
});
emvTransactionProcessViewModel.setPayDetail(payDetail);
sharedViewModel.rrNNo.setValue(rrnNo);
callNextScreen();
}
private void checkRRNRefund(boolean isECR) {
@ -522,11 +514,6 @@ public class InputRRNFragment extends DataBindingFragment {
LogUtil.d(TAG,"Trans Type:"+payDetail.getTransactionType());
if (isCurrentBatchUnsettled(payDetail)) {
terminatedTransRefund(isECR);
return;
}
if(payDetail.getTransactionType() != TransactionsType.SALE.value) {
terminatedTransRefund(isECR);
return;
@ -535,7 +522,7 @@ public class InputRRNFragment extends DataBindingFragment {
String date = payDetail.getTransDate();
String time = payDetail.getTransTime();
// if(checkRefund(configTime,date,time)) {
if(checkRefund(configTime,date,time)) {
PayDetail newPay = transProcessViewModel.getPayDetail();
newPay.setReferNo(rrnNo);
@ -546,21 +533,20 @@ public class InputRRNFragment extends DataBindingFragment {
callNextScreen();
// } else {
// terminatedTransRefund(isECR);
// }
} else {
terminatedTransRefund(isECR);
}
} else {
terminatedTransRefund(isECR);
// PayDetail newPay = transProcessViewModel.getPayDetail();
// newPay.setReferNo(rrnNo);
//
// transProcessViewModel.setPayDetail(newPay);
//
// sharedViewModel.rrNNo.setValue(rrnNo);
//
// callNextScreen();
PayDetail newPay = transProcessViewModel.getPayDetail();
newPay.setReferNo(rrnNo);
transProcessViewModel.setPayDetail(newPay);
sharedViewModel.rrNNo.setValue(rrnNo);
callNextScreen();
}
}
@ -568,17 +554,6 @@ public class InputRRNFragment extends DataBindingFragment {
}
private boolean isCurrentBatchUnsettled(PayDetail payDetail) {
if (payDetail == null) {
return false;
}
String currentBatch = SystemParamsOperation.getInstance().getCurrentBatchNum();
String batchNo = payDetail.getBatchNo();
return batchNo != null
&& batchNo.equals(currentBatch)
&& !payDetail.isSettle;
}
private void terminatedTransRefund(boolean isECR) {
showDeclineDialog(getResourceString(R.string.txt_refund_not_allow));
if (isECR) {

View File

@ -175,17 +175,10 @@ public class InputTraceNoFragment extends DataBindingFragment {
sharedViewModel.payDetail.setValue(payDetail);
if(sharedViewModel.hostType.getValue() == HostType.MPU) {
boolean isMpu = "MPU".equals(payDetail.getAccountType());
if (isMpu) {
sharedViewModel.isEmv.setValue(false);
transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
transProcessViewModel.setOldTransPayDetail(payDetail);
transProcessViewModel.setPayDetail(payDetail);
} else {
sharedViewModel.isEmv.setValue(true);
emvTransactionProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
emvTransactionProcessViewModel.setPayDetail(payDetail);
}
sharedViewModel.isEmv.setValue(false);
transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
transProcessViewModel.setOldTransPayDetail(payDetail);
transProcessViewModel.setPayDetail(payDetail);
} else {
sharedViewModel.isEmv.setValue(true);
emvTransactionProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
@ -306,7 +299,7 @@ public class InputTraceNoFragment extends DataBindingFragment {
if(sharedViewModel.hostType.getValue() == HostType.MPU) {
sharedViewModel.isEmv.setValue(false);
transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
transProcessViewModel.transType.postValue(sharedViewModel.transactionsType.getValue());
transProcessViewModel.setOldTransPayDetail(payDetail);
transProcessViewModel.setPayDetail(payDetail);
} else {

View File

@ -17,6 +17,7 @@ import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.print.PaperRollStatusCallback;
import com.utsmyanmar.paylibs.print.PrintHelper;
import com.utsmyanmar.paylibs.print.PrintReceipt;
import com.utsmyanmar.paylibs.utils.PrintStatus;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
@ -27,8 +28,7 @@ import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
public class PrintReceiptFragment extends DataBindingFragment implements DataBindingFragment.BackPressCallback {
private SharedViewModel sharedViewModel;
private static final String TAG = PrintReceiptFragment.class.getSimpleName();
private boolean printerEnabled = true;
private static final String TAG = PrintReceipt.class.getSimpleName();
@Override
protected int currentId() {
@ -49,6 +49,7 @@ public class PrintReceiptFragment extends DataBindingFragment implements DataBin
@Override
protected void initViewModel() {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
}
@Override
@ -60,7 +61,6 @@ public class PrintReceiptFragment extends DataBindingFragment implements DataBin
@Override
public void onResume() {
super.onResume();
printerEnabled = SystemParamsOperation.getInstance().getPrinterEnabled();
/*
* check TMS parameter here
@ -76,8 +76,7 @@ public class PrintReceiptFragment extends DataBindingFragment implements DataBin
setToolBarTitleWithoutBackIcon(getResourceString(R.string.title_print_receipt));
sharedViewModel.printReceiptButtons.setValue(printerEnabled ? 0 : 8);
sharedViewModel.printerDisabled.setValue(!printerEnabled);
sharedViewModel.printReceiptButtons.setValue(0);
PayDetail payDetail = sharedViewModel.payDetail.getValue();
@ -122,16 +121,10 @@ public class PrintReceiptFragment extends DataBindingFragment implements DataBin
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
printerEnabled = SystemParamsOperation.getInstance().getPrinterEnabled();
if (!printerEnabled) {
sharedViewModel.setPrintStatus(PrintStatus.NOT_PRINT);
sharedViewModel.setVisibilityPrintReceiptButtons(8);
sharedViewModel.postPrintReceiptMsg("Receipt is saved as E-receipt!");
} else {
sharedViewModel.setPrintStatus(PrintStatus.FIRST_PRINT);
observePrintProcess();
}
sharedViewModel.setPrintStatus(PrintStatus.FIRST_PRINT);
observePrintProcess();
setBackPressCallback(this);
}
@ -146,11 +139,8 @@ public class PrintReceiptFragment extends DataBindingFragment implements DataBin
case FIRST_PRINT:
sharedViewModel.postPrintReceiptMsg("Printing Receipt for Merchant");
startPrintProcess(true);
// sharedViewModel.postPrintReceiptMsg("Print Receipt for Customer?");
// sharedViewModel.setVisibilityPrintReceiptButtons(0);
break;
case FIRST_PRINT_DONE:
// sharedViewModel.postPrintReceiptMsg("Print Receipt for Customer?");
sharedViewModel.postPrintReceiptMsg("Confirm Print Receipt for Customer");
if(sharedViewModel.isEcr.getValue() != null &&
sharedViewModel.isEcr.getValue() &&
@ -182,9 +172,6 @@ public class PrintReceiptFragment extends DataBindingFragment implements DataBin
private void startPrintProcess(boolean isFirstPrint) {
if (!SystemParamsOperation.getInstance().getPrinterEnabled()) {
return;
}
PrintHelper.getInstance().checkPaperRollStatus(new PaperRollStatusCallback() {
@ -228,6 +215,7 @@ public class PrintReceiptFragment extends DataBindingFragment implements DataBin
@Override
public void onClickCancel() {
dismissPrinterAlertDialog();
}
@Override
public void onClickRetry() {
@ -260,39 +248,16 @@ public class PrintReceiptFragment extends DataBindingFragment implements DataBin
public class ClickEvent {
public void onConfirm() {
// PrintStatus printStatus = sharedViewModel.getPrintStatus().getValue();
//
// if(printStatus == PrintStatus.NOT_PRINT){
// sharedViewModel.setVisibilityPrintReceiptButtons(8);
// sharedViewModel.setPrintStatus(PrintStatus.FIRST_PRINT);
// }else if(printStatus == PrintStatus.FIRST_PRINT || printStatus == PrintStatus.FIRST_PRINT_DONE){
// sharedViewModel.setVisibilityPrintReceiptButtons(8);
// sharedViewModel.setPrintStatus(PrintStatus.SECOND_PRINT);
// }
sharedViewModel.setVisibilityPrintReceiptButtons(8);
//
sharedViewModel.setPrintStatus(PrintStatus.SECOND_PRINT);
}
public void onCancel() {
sharedViewModel.setVisibilityPrintReceiptButtons(8);
isCardInside();
// PrintStatus printStatus = sharedViewModel.getPrintStatus().getValue();
//
// if(printStatus == PrintStatus.NOT_PRINT){
// sharedViewModel.setPrintStatus(PrintStatus.FIRST_PRINT_DONE);
// }else{
// sharedViewModel.setVisibilityPrintReceiptButtons(8);
// isCardInside();
// }
}
public void onContinue(){
isCardInside();
}
}

View File

@ -1,27 +1,18 @@
package com.utsmm.kbz.ui.core_ui;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum;
import com.utsmm.kbz.config.data.model.CardTransactionType;
import com.utsmm.kbz.util.MockData;
import com.utsmm.kbz.util.ecr.CoreUtils;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TerminalUtil;
import com.utsmyanmar.checkxread.checkcard.CheckCardResultX;
import com.utsmyanmar.checkxread.model.CardDataX;
import com.utsmyanmar.checkxread.readcard.MAGXReadCard;
import com.utsmyanmar.checkxread.readcard.MPUXReadCard;
import com.utsmyanmar.checkxread.readcard.ReadCardResultX;
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.checkxread.util.CardTypeX;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
@ -43,8 +34,6 @@ import com.utsmm.kbz.util.TransactionUtil;
import com.utsmyanmar.paylibs.utils.LogUtil;
import java.util.HashSet;
public class ProcessingCardFragment extends DataBindingFragment {
private static final String TAG = ProcessingCardFragment.class.getSimpleName();
private CardReadViewModel cardReadViewModel;
@ -52,8 +41,6 @@ public class ProcessingCardFragment extends DataBindingFragment {
private TransProcessViewModel transProcessViewModel;
private PinPadViewModel pinPadViewModel;
private EmvTransactionProcessViewModel emvTransactionViewModel;
private int routeId;
@Override
@ -107,8 +94,7 @@ public class ProcessingCardFragment extends DataBindingFragment {
private void checkCardTransactionType() {
switch (cardReadViewModel.getCardTransactionType()) {
case MPU:
readMPUCard();
case MPU: readMPUCard();
break;
case EMV: handlePreEmvProcess();
break;
@ -116,64 +102,28 @@ public class ProcessingCardFragment extends DataBindingFragment {
break;
case MAG: readMAGStripe(false,true);
break;
case MOCK: mockMPUCard();
break;
}
}
private void processMPU(){
if(sharedViewModel.getAmountExist().getValue() != null && !sharedViewModel.getAmountExist().getValue()) {
routeId = R.id.action_processingCardFragment_to_inputAmountFragment;
}
routeId = R.id.action_processingCardFragment_to_pinPadFragment;
safeNavigateToRouteId();
}
private void mockMPUCard() {
LogUtil.d(TAG,"initialize mock card data...");
routeId = R.id.action_processingCardFragment_to_pinPadFragment;
transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
pinPadViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
CardDataX cardDataX = MockData.getInstance().generateMPUCard();
TradeData tradeData = TransactionUtil.getInstance().initMPUTransaction(cardDataX, CardTypeX.IC);
transProcessViewModel.setTradeData(tradeData);
pinPadViewModel.setTradeData(tradeData);
sharedViewModel.setCardDataExist(true);
safeNavigateToRouteId();
}
private void readMPUCard() {
cardReadViewModel.startReadXProcess(MPUXReadCard.getInstance(), new ReadCardResultX() {
@Override
public void onSuccess(CardDataX cardDataX) {
if(!TerminalUtil.getInstance().getBinList().isEmpty()) {
if(TerminalUtil.getInstance().getBinList().contains(cardDataX.getBin())) {
LogUtil.d(TAG," <= BIN found in list, switching to EMV process");
cardReadViewModel.cancelCheckCard();
initCheckCard();
return;
}
}
routeId = R.id.action_processingCardFragment_to_pinPadFragment;
transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
pinPadViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
transProcessViewModel.transType.postValue(sharedViewModel.transactionsType.getValue());
pinPadViewModel.transType.postValue(sharedViewModel.transactionsType.getValue());
TradeData tradeData = TransactionUtil.getInstance().initMPUTransaction(cardDataX, CardTypeX.IC);
transProcessViewModel.setTradeData(tradeData);
pinPadViewModel.setTradeData(tradeData);
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_VOID ) {
if(sharedViewModel.getTransMenu().getValue() == TransMenu.PRE_AUTH_PARTIAL_VOID ) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_function_not_supported));
routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId();
return;
}
// else if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND) {
// sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_card_not_supported));
@ -214,7 +164,7 @@ public class ProcessingCardFragment extends DataBindingFragment {
// pin required scenario
routeId = R.id.action_processingCardFragment_to_pinPadFragment;
transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
transProcessViewModel.transType.postValue(sharedViewModel.transactionsType.getValue());
pinPadViewModel.transType.postValue(sharedViewModel.transactionsType.getValue());
/* need to check card scheme according to card number --!^--- check below function*/
@ -239,11 +189,10 @@ public class ProcessingCardFragment extends DataBindingFragment {
}
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_VOID ) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
if(sharedViewModel.getTransMenu().getValue() == TransMenu.PRE_AUTH_PARTIAL_VOID ) {
// sharedViewModel.transMenu.postValue(null);
sharedViewModel.setTransMenu(null);
routeId = R.id.action_processingCardFragment_to_errorFragment;
}
// else if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND) {
// routeId = R.id.action_processingCardFragment_to_errorFragment;
@ -296,45 +245,6 @@ public class ProcessingCardFragment extends DataBindingFragment {
}
private void initCheckCard() {
HashSet<CardSlotTypeEnum> allType = new HashSet<>();
allType.add(CardSlotTypeEnum.ICC1);
cardReadViewModel.startCheckXProcessNex(allType, 60, new CheckCardResultX() {
@Override
public void onSuccess(CardTypeX cardType, boolean isMPU) {
LogUtil.d(TAG,"**** on success *****");
LogUtil.d(TAG,"card type:"+cardType);
LogUtil.d(TAG,"is MPU:"+isMPU);
// delayFunctionCall(()->{
//
// });
handlePreEmvProcess();
}
@Override
public void onError(int code, String message) {
LogUtil.d(TAG,"on error:"+code+" - message :"+message);
showDeclineDialog(message);
routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId();
}
@Override
public void onCommError() {
LogUtil.d(TAG,"on Comm Error...");
ecrActionCancel(getResourceString(R.string.txt_cancel_trans));
showDeclineDialog("Chip not detected!");
routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId();
}
});
}
private void prepareEmvTransaction() {
sharedViewModel.isEmv.postValue(true);
cardReadViewModel.cardTypeData.observe(getViewLifecycleOwner(), cardType -> {
@ -344,22 +254,5 @@ public class ProcessingCardFragment extends DataBindingFragment {
payDetail.setCardType(cardType);
emvTransactionViewModel.setTradeData(tradeData);
});
// TradeData tradeData = Params.newTrade(false);
// PayDetail payDetail = tradeData.getPayDetail();
//
// payDetail.setCardType(cardReadViewModel.cardTypeData.getValue());
// emvTransactionViewModel.setTradeData(tradeData);
}
private void ecrActionCancel(String msg) {
if (sharedViewModel.isEcr.getValue() != null) {
if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.isEcrFinished.postValue(true);
}
}
}
}

View File

@ -9,12 +9,7 @@ import androidx.annotation.Nullable;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptCardRequest;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TimeoutCallback;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
@ -30,8 +25,6 @@ import com.utsmm.kbz.util.ecr.CoreUtils;
import com.utsmyanmar.paylibs.utils.LogUtil;
import java.text.DecimalFormat;
public class ProcessingFragment extends DataBindingFragment {
private static final String TAG = ProcessingFragment.class.getSimpleName();
@ -175,19 +168,14 @@ public class ProcessingFragment extends DataBindingFragment {
} else {
LogUtil.d(TAG,"Updated sharedViewmodel payDetail for non emv");
sharedViewModel.payDetail.setValue(transProcessViewModel.payDetailResult.getValue());
}
// if(sharedViewModel.payDetail.getValue() != null) {
// EReceiptRequest request = EReceiptUtil.getInstance().generateMPUReceipt(sharedViewModel.payDetail.getValue());
// sharedViewModel.pushReceipt(request);
// }
// transProcessViewModel.payDetailResult.observe(getViewLifecycleOwner(), payDetail -> sharedViewModel.payDetail.postValue(payDetail));
}
private void callNextScreen(){
// updateData();
updateData();
if (requiresSignature()) {
routeId = R.id.action_processingFragment_to_signatureFragment;
} else {
@ -215,7 +203,7 @@ public class ProcessingFragment extends DataBindingFragment {
LogUtil.d(TAG,"tradeAnswerCode: "+payDetail.getTradeAnswerCode());
// For now, let's check if it's a card transaction and successful
boolean isSuccessful = "00".equals(payDetail.getTradeAnswerCode()) || "000".equals(payDetail.getTradeAnswerCode());
boolean isSuccessful = "00".equals(payDetail.getTradeAnswerCode());
// You can customize this logic based on your business requirements
return isSuccessful && !isEmvTrans(); // Require signature for successful non-EMV transactions
@ -262,17 +250,11 @@ public class ProcessingFragment extends DataBindingFragment {
processingTransaction.getTransStatus().observe(getViewLifecycleOwner(), transResultStatus -> {
LogUtil.d(TAG,"Transaction RESULT :"+transResultStatus);
PayDetail payDetail = isEmvTrans()
? emvTransactionProcessViewModel.payDetailResult.getValue()
: transProcessViewModel.payDetailResult.getValue();
LogUtil.d(TAG, "PayDetail from VM: " + payDetail);
switch (transResultStatus) {
case FAIL:
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, false, "FAILED"));
case SUCCESS:
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, "SUCCESS"));
case OFFLINE_SUCCESS:
LogUtil.d(TAG,"This was called!");
if(SystemParamsOperation.getInstance().getDemoStatus()) {
delayFunctionCall(()->{
// updateData();
@ -281,14 +263,12 @@ public class ProcessingFragment extends DataBindingFragment {
},1500);
} else {
// updateData();
sharedViewModel.dismissLoadingMsg();
callNextScreen();
}
break;
case OFFLINE_FAILURE:
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, false, "FAILED"));
sharedViewModel.dismissLoadingMsg();
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_offline_failure));
navigateToError();
@ -386,108 +366,4 @@ public class ProcessingFragment extends DataBindingFragment {
});
}
private String mapDE3ToShortCode(String de3) {
if (de3 == null) return "UNK";
switch (de3) {
case "000000": return "S"; // Sale
case "020000": return "V"; // Void
case "200000": return "R"; // Refund
case "030000": return "P"; // Preauth
case "310000": return "PC"; // Preauth Complete
}
return "UNK"; // Unknown
}
public static String mapTransactionType(int type) {
switch (type) {
case 1: // SALE
return "S";
case 2: // VOID SALE
return "V";
case 4: // REFUND
return "R";
case 5: // PRE-AUTH
return "P";
case 6: // PRE-AUTH VOID
return "PV";
case 7: // PRE-AUTH COMPLETE
return "PC";
case 8: // PRE-AUTH COMPLETE VOID
return "PCV";
case 9: // CASH OUT
return "CAV";
case 18: // TIP ADJUST
return "TA";
case 20: // QR PAYMENT
return "QR";
case 34: // QR REFUND
return "QRV";
default:
return "UNK";
}
}
private String mapCurrency(String currency) {
if (currency == null) return "MMK";
switch (currency) {
case "104": return "MMK";
case "840": return "USD";
case "764": return "THB";
case "702": return "SGD";
case "978": return "EUR";
default: return currency; // Already alphabetic? return as-is
}
}
private EReceiptCardRequest buildEReceiptCardReceipt(PayDetail payDetail, boolean isSuccess, String reason){
//current timestamp
String currentTimestamp = new java.text.SimpleDateFormat(
"MMddHHmmss", java.util.Locale.getDefault()
).format(new java.util.Date());
//DeviceInfo
String serial = TMSUtil.getInstance().getSerialNumber();
String appId = requireActivity().getPackageName();
//TerminalInfo
String terminalId = SystemParamsOperation.getInstance().getTerminalId();
String merchantId = SystemParamsOperation.getInstance().getMerchantId();
double realAmount = payDetail.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
String amount = df.format(realAmount);
EReceiptCardRequest request = new EReceiptCardRequest();
request.setDE2(payDetail.getCardNo());
request.setDE3(mapDE3ToShortCode(payDetail.getProcessCode()));
request.setDE4(amount);
request.setDE7(currentTimestamp);
request.setDE11(payDetail.getVoucherNo());
request.setDE22(mapTransactionType(payDetail.getTransactionType()));
request.setDE37(payDetail.getReferNo());
request.setDE38(payDetail.getAuthNo());
request.setDE39(isSuccess ? "A" : "E");
request.setDE41(terminalId);
request.setDE42(merchantId);
request.setDE49(mapCurrency(payDetail.getCurrencyCode()));
request.setSerial(serial);
request.setInvoiceNumber(payDetail.getInvoiceNo());
request.setAppId(appId);
request.setDescription(reason);
return request;
}
}

View File

@ -16,11 +16,7 @@ import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.print.printx.PrintX;
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.print_utils.BitmapUtils;
public class SignatureFragment extends DataBindingFragment {
@ -84,12 +80,14 @@ public class SignatureFragment extends DataBindingFragment {
@Override
public void onSigned() {
LogUtil.d(TAG,"ON Signed !");
isSigned = true;
}
@Override
public void onClear() {
isSigned = false;
LogUtil.d(TAG,"ON Clear !");
}
});
}
@ -132,12 +130,6 @@ public class SignatureFragment extends DataBindingFragment {
safeNavigateToRouteId();
}
private void updateData() {
PayDetail payDetail = sharedViewModel.payDetail.getValue();
payDetail.setESignHexData(BitmapUtils.bitmapToHexString(mSignaturePad.getSignatureBitmap()));
sharedViewModel.payDetail.setValue(payDetail);
}
public class ClickEvent {
@ -146,8 +138,6 @@ public class SignatureFragment extends DataBindingFragment {
// Handle digital signature
if (isSigned) {
sharedViewModel.signBitmap = mSignaturePad.getSignatureBitmap();
updateData();
LogUtil.d(TAG, "Digital signature confirmed and stored");
callNextScreen();
} else {
@ -157,6 +147,7 @@ public class SignatureFragment extends DataBindingFragment {
// Handle manual signature on paper
sharedViewModel.signBitmap = null; // No digital signature
LogUtil.d(TAG, "Manual signature on paper selected - no digital signature stored");
showSingleInfoDialog("Please sign on the printed receipt manually and proceed.");
callNextScreen();
}
}

View File

@ -21,7 +21,7 @@ public class TimeoutFragment extends DataBindingFragment {
private SharedViewModel sharedViewModel;
private int resultTimeOut = 5;
private int resultTimeOut = 3;
private CountDownTimer countDownTimer;
private int routeId;

View File

@ -8,7 +8,6 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.MalformedJsonException;
import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
@ -27,7 +26,6 @@ import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.print.PaperRollStatusCallback;
import com.utsmyanmar.paylibs.print.PrintHelper;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
import com.utsmyanmar.paylibs.utils.PrintStatus;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
@ -44,19 +42,18 @@ import java.io.IOException;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.HttpException;
import com.utsmyanmar.paylibs.utils.LogUtil;
// Temporarily disabled Hilt
@AndroidEntryPoint
// @AndroidEntryPoint
public class TransactionResultFragment extends DataBindingFragment implements DataBindingFragment.BackPressCallback {
private static final String TAG = TransactionResultFragment.class.getSimpleName();
private TransProcessViewModel transProcessViewModel;
private SharedViewModel sharedViewModel;
private static final int resultTimeOut = 3;
private static final int resultTimeOut = 1;
private int routeId;
private final RxUtil<SiriusResponse> siriusRxUtil = new RxUtil<>();
@ -94,6 +91,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
@Override
public void onStart() {
super.onStart();
}
@Override
@ -113,8 +111,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
}
if (resultStr.equals(Constant.ANSWER_CODE_ACCEPT) || resultStr.equals(Constant.ANSWER_CODE_APPROVED)) {
/* ISO 8583 RESPONSE */
if(sharedViewModel.payDetail.getValue().getTransactionType() != TransactionsType.SETTLEMENT.value
&& sharedViewModel.payDetail.getValue().getTransactionType() != TransactionsType.MMQR_SETTLEMENT.value) {
if(sharedViewModel.payDetail.getValue().getTransactionType() != TransactionsType.SETTLEMENT.value) {
if(SystemParamsOperation.getInstance().isAlertSound()) {
startSound(getResourceString(R.string.txt_audio_thank_you));
@ -122,7 +119,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
}
setToolBarTitleWithoutBackIcon(getResourceString(R.string.txt_title_trans_result));
} else if(qrStatus == 1 || qrStatus == -1 || qrStatus == 2 || qrStatus == 3 ) {
/* QR STATUS */
/* WAVE QR STATUS */
setToolBarTitleWithoutBackIcon(getResourceString(R.string.txt_title_qr_pay));
} else {
setToolBarTitleWithoutBackIcon(getResourceString(R.string.txt_title_error));
@ -149,8 +146,6 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
PayDetail payDetail = sharedViewModel.payDetail.getValue();
if (payDetail == null) {
navigateToMainScreen();
return;
@ -164,23 +159,16 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
TransactionsType transactionType = sharedViewModel.transactionsType.getValue();
if (isNonApprovedTrade(payDetail) && isNonQRPayTransaction(transactionType)) {
if (SystemParamsOperation.getInstance().getPrinterEnabled()) {
startPrintProcess(false);
}
if (isNonApprovedTrade(payDetail) && isNonWavepayTransaction(transactionType)) {
startPrintProcess(false);
isCardInside();
} else if (transactionType == TransactionsType.SETTLEMENT || transactionType == TransactionsType.MMQR_SETTLEMENT) {
} else if (transactionType == TransactionsType.SETTLEMENT) {
handleSettlementTransaction(siriusReq);
} else if (isQRPayNonSuccessTransaction(transactionType, payDetail)) {
// startPrintProcess(false);
if(transactionType == TransactionsType.MMQR_REFUND){
showDeclineDialog("QR Refund Failed! \n" + payDetail.getTradeResultDes());
}else{
showDeclineDialog("QR Payment Failed! \n" + payDetail.getTradeResultDes());
}
} else if (isWavePayNonSuccessTransaction(transactionType, payDetail)) {
startPrintProcess(false);
navigateToMainScreen();
} else if (isQRPaySuccessTransaction(transactionType, payDetail)) {
handleQRPaySuccessTransaction(payDetail, siriusReq);
} else if (isWavePaySuccessTransaction(transactionType, payDetail)) {
handleWavePaySuccessTransaction(payDetail, siriusReq);
} else {
handleDefaultTransaction(payDetail, siriusReq);
}
@ -194,37 +182,32 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
!payDetail.getTradeAnswerCode().equals(Constant.ANSWER_CODE_ACCEPT);
}
private boolean isNonQRPayTransaction(TransactionsType transactionType) {
private boolean isNonWavepayTransaction(TransactionsType transactionType) {
return transactionType != TransactionsType.MMQR &&
transactionType != TransactionsType.MMQR_INQUIRY_STATUS &&
transactionType != TransactionsType.MMQR_REFUND;
}
private boolean isQRPayNonSuccessTransaction(TransactionsType transactionType, PayDetail payDetail) {
private boolean isWavePayNonSuccessTransaction(TransactionsType transactionType, PayDetail payDetail) {
return (transactionType == TransactionsType.MMQR && payDetail.getQrTransStatus() != 1) ||
(transactionType == TransactionsType.MMQR_INQUIRY_STATUS && payDetail.getQrTransStatus() != 1) ||
(transactionType == TransactionsType.MMQR_REFUND && payDetail.getQrTransStatus() != 1);
}
private boolean isQRPaySuccessTransaction(TransactionsType transactionType, PayDetail payDetail) {
private boolean isWavePaySuccessTransaction(TransactionsType transactionType, PayDetail payDetail) {
return (transactionType == TransactionsType.MMQR || transactionType == TransactionsType.MMQR_REFUND) &&
payDetail.getQrTransStatus() == 1;
}
private void handleSettlementTransaction(SiriusRequest siriusReq) {
if (!SystemParamsOperation.getInstance().getPrinterEnabled()) {
downloadParameters(siriusReq, TMSUpdate.UPDATE);
isCardInside();
return;
}
startPrintProcess(true);
downloadParameters(siriusReq, TMSUpdate.UPDATE);
// showSuccessDialog(getResourceString(R.string.txt_configs_are_updated));
// navigateToMainScreen();
showSuccessDialog(getResourceString(R.string.txt_configs_are_updated));
navigateToMainScreen();
}
private void handleQRPaySuccessTransaction(PayDetail payDetail, SiriusRequest siriusReq) {
private void handleWavePaySuccessTransaction(PayDetail payDetail, SiriusRequest siriusReq) {
SystemParamsOperation.getInstance().setLastSuccessTrnx(payDetail.getVoucherNo());
downloadParameters(siriusReq, TMSUpdate.CHECK);
navigateToPrintScreen();
@ -255,12 +238,15 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
try {
SiriusError siriusError = new Gson().fromJson(error.response().errorBody().string(), SiriusError.class);
LogUtil.d(TAG,siriusError.getMessage());
} catch (IOException | JsonSyntaxException ex) {
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
LogUtil.d(TAG,getResourceString(R.string.txt_failure)+throwable.getMessage());
}
throwable.printStackTrace();
}
@ -328,18 +314,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
@Override
public void printerReady() {
if(isSettlement) {
sharedViewModel.startPrintSettlement(new PrintXStatus() {
@Override
public void onSuccess() {
sharedViewModel.onSettlementResultDone.postValue(true);
isCardInside();
}
@Override
public void onFailure() {
handleForEmptyPaperRoll(isSettlement);
}
});
sharedViewModel.startPrintProcessSettlement();
return;
}
sharedViewModel.startPrintProcess();
@ -347,7 +322,26 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
@Override
public void paperRollIsEmpty() {
handleForEmptyPaperRoll(isSettlement);
cancelTimeout();
showPrinterAlertDialog(getResourceString(R.string.txt_paper_roll_not_ready), new DialogCallback() {
@Override
public void onClickCancel() {
dismissPrinterAlertDialog();
isCardInside();
}
@Override
public void onClickRetry() {
dismissPrinterAlertDialog();
startPrintProcess(isSettlement);
}
});
if(SystemParamsOperation.getInstance().isAlertSound()) {
startSound(getResourceString(R.string.txt_audio_printer_alert));
}
}
@Override
@ -374,30 +368,6 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
});
}
private void handleForEmptyPaperRoll(boolean isSettle) {
cancelTimeout();
showPrinterAlertDialog(getResourceString(R.string.txt_paper_roll_not_ready), new DialogCallback() {
@Override
public void onClickCancel() {
dismissPrinterAlertDialog();
isCardInside();
}
@Override
public void onClickRetry() {
dismissPrinterAlertDialog();
startPrintProcess(isSettle);
}
});
if(SystemParamsOperation.getInstance().isAlertSound()) {
startSound(getResourceString(R.string.txt_audio_printer_alert));
}
}
private void alertPaperRoll(String title, String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
builder.setTitle(title)

View File

@ -25,8 +25,6 @@ import java.util.HashSet;
import javax.inject.Inject;
import io.reactivex.rxjava3.core.Single;
public class CardReadViewModel extends ViewModel {
@ -48,6 +46,7 @@ public class CardReadViewModel extends ViewModel {
public SingleLiveEvent<Integer> cardTypeData = new SingleLiveEvent<>();
public SingleLiveEvent<PayDetail> payDetail = new SingleLiveEvent<>();
public SingleLiveEvent<CardReadStatus> readStatus = new SingleLiveEvent<>();
public SingleLiveEvent<String> checkCardAlertMsg = new SingleLiveEvent<>();
@ -96,6 +95,96 @@ public class CardReadViewModel extends ViewModel {
checkCardAlertMsg.setValue(null);
}
// public void initCardReadProcess(int allType, int timeOutInSec, ReadCardResult readCardResult) {
// ReadCardProcess.getInstance().startReadCard(allType,"",timeOutInSec,false).onStartReadCardProcess(new CheckCardListener() {
// @Override
// public void onCheckCardSuccess(int cardType, MPUCardData mpuCardData, CardScheme cardScheme) {
//
// cardData.postValue(mpuCardData);
// cardSchemeData.postValue(cardScheme);
// cardTypeData.postValue(cardType);
// PayDetail payDetailData = new PayDetail();
// payDetailData.setCardNo(mpuCardData.getPan());
// payDetailData.setEXPDate(mpuCardData.getExp());
// payDetailData.setAccountType(cardScheme.name());
// payDetailData.setCardType(cardType);
// payDetailData.setCardHolderName(mpuCardData.getCardHolderName());
// CardInfo cardInfo = new CardInfo();
// MAGCardInfo magCardInfo = new MAGCardInfo();
// LogUtil.d(TAG,"track 2 : "+mpuCardData.getTrack2());
// magCardInfo.setTrack2Cipher(mpuCardData.getTrack2());
// cardInfo.setMAGCardInfo(magCardInfo);
// payDetailData.setCardInfo(cardInfo);
//
// payDetail.postValue(payDetailData);
//
// mainThreadHandler.post(readCardResult::onSuccess);
//// readCardResult.onSuccess();
//
// }
//
// @Override
// public void onCheckCardFail(int code, String message) {
//
// if(code == -2801) {
// mainThreadHandler.post(readCardResult::onCommunicationError);
//// readCardResult.onCommunicationError();
// } else {
// mainThreadHandler.post(() -> readCardResult.onError(code,message));
//// readCardResult.onError(code,message);
// }
//
// }
// });
// }
//
// public SingleLiveEvent<CardReadStatus> startReadProcess(int allType,int timeOutInSec){
//
// ReadCardProcess.getInstance().startReadCard(allType,"",timeOutInSec,false).onStartReadCardProcess(new CheckCardListener() {
// @Override
// public void onCheckCardSuccess(int cardType, MPUCardData mpuCardData, CardScheme cardScheme) {
// flag.postValue(true);
// cardData.postValue(mpuCardData);
// cardSchemeData.postValue(cardScheme);
// cardTypeData.postValue(cardType);
// PayDetail payDetailData = new PayDetail();
// payDetailData.setCardNo(mpuCardData.getPan());
// payDetailData.setEXPDate(mpuCardData.getExp());
// payDetailData.setAccountType(cardScheme.name());
// payDetailData.setCardType(cardType);
// payDetailData.setCardHolderName(mpuCardData.getCardHolderName());
// CardInfo cardInfo = new CardInfo();
// MAGCardInfo magCardInfo = new MAGCardInfo();
// LogUtil.d(TAG,"track 2 : "+mpuCardData.getTrack2());
// magCardInfo.setTrack2Cipher(mpuCardData.getTrack2());
// cardInfo.setMAGCardInfo(magCardInfo);
// payDetailData.setCardInfo(cardInfo);
//
// payDetail.postValue(payDetailData);
//
// readStatus.postValue(CardReadStatus.SUCCESS);
//
//
// }
//
// @Override
// public void onCheckCardFail(int code, String message) {
//
// readStatus.postValue(CardReadStatus.FAIL);
// // this action just need to do once because there's too many reason to get fail
// if(!oneTimeFlag){
// errorCode.postValue(code+":"+message);
// flag.postValue(false);
// cardSchemeData.postValue(CardScheme.UNK);
// oneTimeFlag = true;
// }
//
// }
// });
//
// return readStatus;
// }
public void resetOneTimeFlag(){
oneTimeFlag = false;
}
@ -103,44 +192,20 @@ public class CardReadViewModel extends ViewModel {
public void cancelCheckCard(){
NexGoSDK.getInstance().cancelCheckCard();
}
/**
* Properly cleanup card reading operations with sequential steps
*/
public void performCompleteCleanup(Runnable onCleanupComplete) {
// Step 1: Cancel check card operations
NexGoSDK.getInstance().cancelCheckCard();
// Step 2: Cancel X process operations
cancelCheckXProcess();
// Step 3: Reset internal flags and state
resetOneTimeFlag();
resetUI();
// Step 4: Wait for SDK to be ready before proceeding
if (onCleanupComplete != null) {
waitForSDKReady(onCleanupComplete, 0);
}
}
/**
* Wait for SDK to be ready with timeout
*/
private void waitForSDKReady(Runnable callback, int retryCount) {
final int MAX_RETRIES = 10; // Max 2 seconds (10 * 200ms)
if (NexGoSDK.getInstance().isSDKReady() || retryCount >= MAX_RETRIES) {
// SDK is ready or we've reached max retries
if (retryCount >= MAX_RETRIES) {
// Log warning if we reached max retries
android.util.Log.w(TAG, "SDK readiness check timed out after " + (MAX_RETRIES * 200) + "ms");
}
callback.run();
} else {
// Wait a bit more and check again
mainThreadHandler.postDelayed(() -> waitForSDKReady(callback, retryCount + 1), 200);
}
}
// public void checkCard(){
// int allType = AidlConstants.CardType.NFC.getValue() | AidlConstants.CardType.IC.getValue() | AidlConstants.CardType.MAGNETIC.getValue();
// ReadCardProcess.getInstance().startReadCard(allType,"",60,false).onStartReadCardProcess(new CheckCardListener() {
// @Override
// public void onCheckCardSuccess(int cardType, MPUCardData mpuCardData, CardScheme cardScheme) {
// System.out.println("Success");
// }
//
// @Override
// public void onCheckCardFail(int code, String message) {
//
// System.out.println("Failed");
// }
// });
// }
}

View File

@ -0,0 +1,460 @@
package com.utsmm.kbz.ui.core_viewmodel;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import androidx.lifecycle.ViewModel;
import com.sunmi.pay.hardware.aidl.bean.CardInfo;
import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.sunmi.pay.hardware.aidlv2.bean.EMVCandidateV2;
import com.sunmi.pay.hardware.aidlv2.bean.EMVTransDataV2;
import com.sunmi.pay.hardware.aidlv2.emv.EMVListenerV2;
import com.sunmi.pay.hardware.aidlv2.emv.EMVOptV2;
import com.sunmi.pay.hardware.aidlv2.pinpad.PinPadOptV2;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.system.SingleLiveEvent;
import com.utsmyanmar.paylibs.utils.core_utils.KernelDataProcessUtil;
import com.utsmm.kbz.MyApplication;
import com.utsmm.kbz.util.enums.EmvReadStatus;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
/*
* Currently this class is not used
* */
@HiltViewModel
public class EmvReadCardViewModel extends ViewModel {
private static final String TAG = EmvReadCardViewModel.class.getSimpleName();
private final Repository repository;
public SingleLiveEvent<String> cardNum = new SingleLiveEvent<>();
public SingleLiveEvent<String> expDate = new SingleLiveEvent<>();
public SingleLiveEvent<EmvReadStatus> resultStatus = new SingleLiveEvent<>();
public SingleLiveEvent<List<EMVCandidateV2>> emvList = new SingleLiveEvent<>();
public SingleLiveEvent<Boolean> isButtonVisible = new SingleLiveEvent<>();
public SingleLiveEvent<String> emvCardType = new SingleLiveEvent<>();
public SingleLiveEvent<String> errorCode = new SingleLiveEvent<>();
private String mTag9F06Value;
public TradeData mTradeData;
public PayDetail mPayDetail;
private EMVOptV2 mEMVOptV2;
private PinPadOptV2 mPinPadOptV2;
private static final int CHECK_CARD_FAIL = 1;
private static final int CHECK_CARD_SUCCESS = 2;
private static final int CHECK_CARD_MAG = 3;
private static final int CHECK_CARD_NFC = 4;
private static final int CHECK_CARD_IC = 5;
private static final int EMV_APP_SELECT = 6;
private static final int EMV_CONFIRM_CARD_NO = 7;
private Looper mLooper = Looper.getMainLooper();
private final Handler mHandler = new Handler(mLooper) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CHECK_CARD_FAIL:
String hint = (String) msg.obj;
resultStatus.postValue(EmvReadStatus.FAIL);
// checkCardFail(msg.arg1, hint);
break;
case EMV_APP_SELECT:
List<EMVCandidateV2> list = ( List<EMVCandidateV2> ) msg.obj;
emvList.postValue(list);
resultStatus.postValue(EmvReadStatus.SELECT_APP);
case CHECK_CARD_SUCCESS:
getCardInfo();
getF055Data();
terminateTrans();
resultStatus.postValue(EmvReadStatus.SUCCESS);
break;
case EMV_CONFIRM_CARD_NO:
getCardInfo();
getF055Data();
terminateTrans();
resultStatus.postValue(EmvReadStatus.SUCCESS);
try {
mEMVOptV2.importCardNoStatus(0);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case CHECK_CARD_MAG:
Bundle bundle = (Bundle) msg.obj;
// handleMagCard(bundle);
break;
case CHECK_CARD_NFC:
// handleNFCCard();
break;
case CHECK_CARD_IC:
// handleICCard();
break;
}
}
};
public void terminateTrans(){
try {
mEMVOptV2.abortTransactProcess();
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void setEmvAppSelect(int position){
try {
mEMVOptV2.importAppSelect(position);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Inject
public EmvReadCardViewModel(Repository repository){
this.repository = repository;
}
public void setTradeData(TradeData tradeData){
this.mTradeData = tradeData;
mPayDetail = mTradeData.getPayDetail();
}
public TradeData getTradeData(){
return mTradeData;
}
public void startProcess(){
initView();
initEmvTlvData();
transactProcess();
}
private void initView(){
mEMVOptV2 = MyApplication.getInstance().mEMVOptV2;
mPinPadOptV2 = MyApplication.getInstance().mPinPadOptV2;
}
private void initEmvTlvData() {
try {
// set PayWave(Visa) tlv data
String[] tagsPayWave = {"DF8124", "DF8125", "DF8126"};
String[] valuesPayWave = {"999999999999", "999999999999", "000000000000"};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYWAVE, tagsPayWave, valuesPayWave);
// set JCB Wave tlv data
String[] tagsJCB = {"9F53", "DF8161"};
String[] valuesJCB = {"708000", "7F00"};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_JCB, tagsJCB, valuesJCB);
// set PayPass(MasterCard) tlv data
String[] tagsPayPass = {"DF8117", "DF8118", "DF8119", "DF811F", "DF811E", "DF812C",
"DF8123", "DF8124", "DF8125", "DF8126",
"DF811B", "DF811D", "DF8122", "DF8120", "DF8121"};
String[] valuesPayPass = {"E0", "F8", "F8", "E8", "00", "00",
"000000000000", "000000100000", "999999999999", "000000100000",
"30", "02", "0000000000", "000000000000", "000000000000"};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYPASS, tagsPayPass, valuesPayPass);
// set AMEX(AmericanExpress) tlv data
String[] tagsAE = {"9F6D", "9F6E", "9F33", "9F35", "DF8168", "DF8167", "DF8169", "DF8170"};
String[] valuesAE = {"C0", "D8E00000", "E0E888", "22", "00", "00", "00", "60"};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_AE, tagsAE, valuesAE);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private void transactProcess() {
// LogUtil.e(TAG, "***************************************************************");
// LogUtil.e(TAG, "****************************Start Process**********************");
// LogUtil.e(TAG, "***************************************************************");
//
// LogUtil.e(TAG, "transactProcess");
try {
mEMVOptV2.initEmvProcess();
EMVTransDataV2 emvTransData = new EMVTransDataV2();
emvTransData.amount = "1000";
// if(mPayDetail.cardType == AidlConstantsV2.CardType.NFC.getValue()){
// emvTransData.flowType = AidlConstantsV2.EMV.FlowType.TYPE_NFC_SPEEDUP;
// }else{
// emvTransData.flowType = AidlConstantsV2.EMV.FlowType.TYPE_EMV_STANDARD;
// }
emvTransData.flowType = 2;
emvTransData.cardType = mPayDetail.cardType;
mEMVOptV2.transactProcess(emvTransData, mEMVListener);
} catch (Exception e) {
resultStatus.postValue(EmvReadStatus.FAIL);
e.printStackTrace();
}
}
private void initEmvProcess() {
try {
// Set normal TLV data
String[] tags = {"5F2A", "5F36"};
String[] values = {"0104", "00"};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tags, values);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private EMVListenerV2 mEMVListener = new EMVListenerV2.Stub() {
@Override
public void onWaitAppSelect(List<EMVCandidateV2> appNameList, boolean isFirstSelect) throws RemoteException {
// LogUtil.e(TAG, "onWaitAppSelect isFirstSelect:" + isFirstSelect);
mHandler.obtainMessage(EMV_APP_SELECT, appNameList).sendToTarget();
}
@Override
public void onAppFinalSelect(String tag9F06Value) throws RemoteException {
// LogUtil.d(TAG, "tag9F06Value:" + tag9F06Value);
mTag9F06Value = tag9F06Value;
initEmvProcess();
/* if (tag9F06Value != null && tag9F06Value.length() > 0) {
boolean visa = tag9F06Value.startsWith("A000000003");
boolean master = tag9F06Value.startsWith("A000000004");
boolean unionPay = tag9F06Value.startsWith("A000000333");
boolean jcb = tag9F06Value.startsWith("A000000065");
if (visa) {
emvCardType.postValue("VISA");
// VISA - PayWave
mPayDetail.setAccountType("Visa");
LogUtil.d(TAG, "detect VISA card");
String[] tagsPayWave = {
// "DF8124", "DF8125", "DF8126"
"9F33"
};
String[] valuesPayWave = {
// "999999999999", "999999999999", "000000000000"
"002888"
};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tagsPayWave, valuesPayWave);
} else if (master) {
emvCardType.postValue("MASTER");
// MasterCard - PayPass
mPayDetail.setAccountType("Master");
LogUtil.d(TAG, "detect MasterCard card");
// String[] tagsPayPass = {
// "DF8118", "DF8119", "DF811F", "DF811E",
// "DF8123", "DF8124", "DF8125", "DF8126",
// "DF811B", "DF811D", "DF8122", "DF8120", "DF8121"
// };
// String[] valuesPayPass = {
// "28", "08", "08", "10",
// "000000010000", "000000030000", "000000050000", "000000001000",
// "00", "00", "0000000000", "0000000000", "0000000000"
// };
String[] tagsPayPass = {
"DF8117", "DF8118", "DF8119", "DF811F", "DF811E", "DF812C",
"DF8123", "DF8124", "DF8125", "DF8126",
"DF811B", "DF811D", "DF8122", "DF8120", "DF8121"
};
String[] valuesPayPass = {
"E0", "F8", "F8", "E8", "00", "00",
"999999999999", "000000001000", "000000001000", "000000001000",
"30", "02", "0000000000", "000000000000", "000000000000"
};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYPASS, tagsPayPass, valuesPayPass);
} else if (unionPay) {
emvCardType.postValue("UnionPay");
mPayDetail.setAccountType("UPI");
// UnionPay
LogUtil.d(TAG, "detect UnionPay card");
String[] tagsPayPass = {
"DF8120", "DF8121", "DF8122"
};
String[] valuesPayPass = {
"D84000A800", "DC4004F800", "0100000000"
};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tagsPayPass, valuesPayPass);
} else if(jcb) {
emvCardType.postValue("JCB");
mPayDetail.setAccountType("JCB");
// UnionPay
LogUtil.d(TAG, "detect JCB card");
}
}
if (AidlConstants.CardType.IC.getValue() == mPayDetail.cardType) {
String[] tags = {
"9F33", "9F09", "DF81FF"
};
String[] values = {
"6060C8", "0111", "01"
// "0008C8", "0111", "01"
};
mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tags, values);
}*/
mEMVOptV2.importAppFinalSelectStatus(0);
}
@Override
public void onConfirmCardNo(String cardNo) {
// LogUtil.e(TAG, "onConfirmCardNo cardNo:" + cardNo);
mHandler.sendEmptyMessage(EMV_CONFIRM_CARD_NO);
}
@Override
public void onRequestShowPinPad(int type, int remainTime) throws RemoteException {
// LogUtil.e(TAG, "requestShowPinPad type:" + type + " remainTime:" + remainTime);
mHandler.sendEmptyMessage(CHECK_CARD_SUCCESS);
}
@Override
public void onRequestSignature() throws RemoteException {
// LogUtil.e(TAG, "signatureStatus");
mEMVOptV2.importSignatureStatus(0);
}
@Override
public void onCertVerify(int certType, String certInfo) throws RemoteException {
// LogUtil.e(TAG, "onCertVerify certType:" + certType + " certInfo:" + certInfo);
mEMVOptV2.importCertStatus(0);
}
@Override
public void onOnlineProc() throws RemoteException {
// LogUtil.e(TAG, "onProcessEnd");
mHandler.sendEmptyMessage(CHECK_CARD_SUCCESS);
}
@Override
public void onCardDataExchangeComplete() throws RemoteException {
// LogUtil.e(TAG, "onCardDataExchangeComplete");
}
@Override
public void onConfirmationCodeVerified() throws RemoteException {
// LogUtil.e(TAG, "onConfirmationCodeVerified");
}
@Override
public void onRequestDataExchange(String s) throws RemoteException {
}
@Override
public void onTermRiskManagement() throws RemoteException {
}
@Override
public void onPreFirstGenAC() throws RemoteException {
}
@Override
public void onTransResult(int code, String desc) throws RemoteException {
/*
* Temporary Error Message
* */
String errorMsg = "Card read failed!";
errorCode.postValue(code+":"+errorMsg);
if (code != 0) {
if( code == -50011) {
mHandler.sendEmptyMessage(CHECK_CARD_SUCCESS);
} else {
mHandler.obtainMessage(CHECK_CARD_FAIL, code, code, desc).sendToTarget();
}
} else {
mHandler.sendEmptyMessage(CHECK_CARD_SUCCESS);
}
// LogUtil.e(TAG, "onTransResult code:" + code + " desc:" + desc);
// LogUtil.e(TAG, "***************************************************************");
// LogUtil.e(TAG, "****************************End Process************************");
// LogUtil.e(TAG, "***************************************************************");
}
};
private void getCardInfo() {
String[] tagList = {"5A", "5F24", "57", "5F34", "9F6B"};
byte[] outData = new byte[1024];
try {
int len = mEMVOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tagList, outData);
if (len > 0) {
byte[] data = new byte[len];
System.arraycopy(outData, 0, data, 0, len);
CardInfo cardInfo = KernelDataProcessUtil.getCardInfo(mPayDetail.cardType, data);
mTradeData = KernelDataProcessUtil.fillTradeDataInfo(cardInfo, mTradeData);
//display card data in layout
cardNum.postValue(mPayDetail.getCardNo());
expDate.postValue(mPayDetail.getEXPDate());
} else {
// LogUtil.e(Constant.TAG, "The data length of the card information is negative = " + len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void getF055Data() {
/* For Yoma */
/*Jun 6 Added 9F2A*/
String[] tagList={
"9F2A","9F26","9F27","9F10","9F37","9F36","95","9A","9C","9F02","5F2A","5F34","82","9F1A", //field 55 tag
"9F03","9F33","4F","9F08","9F34","9F35","9F1E","9F53","84","9F09","9F41", //field55 tag
"9F5B","8A","9B","9F6E","9F7C","9F4C","50","9F12","DF01","9F63","5F20","9F0B","9F42"
};
byte[] outData = new byte[2048];
try {
int len = mEMVOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_NORMAL, tagList, outData);
if (len > 0) {
byte[] data = new byte[len];
System.arraycopy(outData, 0, data, 0, len);
mTradeData = KernelDataProcessUtil.readKernelData(data, mTradeData);
} else {
// LogUtil.e(Constant.TAG, "Get the data length of the 55 field as a negative number = " + len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -16,7 +16,6 @@ import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.baselib.util.enums.EmvResultStatus;
import com.utsmyanmar.baselib.viewModel.EmvBaseViewModel;
import com.utsmyanmar.checkxread.util.CardTypeX;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.model.enums.TransCVM;
@ -83,7 +82,7 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
} else if (isOfflinePinEntered) {
emvHandler.onSetPinInputResponse(true, false);
} else {
emvHandler.onSetPinInputResponse(true, false);
emvHandler.onSetPinInputResponse(false, true);
}
if (transType.getValue() == TransactionsType.PRE_AUTH_COMPLETE || transType.getValue() == TransactionsType.PRE_AUTH_VOID || transType.getValue() == TransactionsType.REFUND) {
emvResultStatus.postValue(EmvResultStatus.ON_NEXT_SCREEN);
@ -162,10 +161,7 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
handleTransactionFail(msg.arg1, msg.obj.toString());
break;
case EMV_TRY_AGAIN:
emvResultStatus.postValue(EmvResultStatus.READ_CARD_RETRY);
break;
case EMV_CARD_APP_BLOCK:
emvResultStatus.postValue(EmvResultStatus.CARD_APP_BLOCKED);
emvResultStatus.postValue(EmvResultStatus.TRY_AGAIN);
break;
case EMV_CONFIRM_CODE_VERIFY:
emvResultStatus.postValue(EmvResultStatus.CONFIRM_CODE_VERIFY);
@ -179,16 +175,9 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
case EMV_SUCCESS_OFFLINE:
transResult.postValue(TransResultStatus.OFFLINE_SUCCESS);
break;
case EMV_FAILURE_OFFLINE:
transResult.postValue(TransResultStatus.OFFLINE_FAILURE);
break;
case EMV_SEE_PHONE:
emvResultStatus.postValue(EmvResultStatus.SEE_PHONE);
break;
case EMV_OTHER_INTERFACE:
emvResultStatus.postValue(EmvResultStatus.OTHER_INTERFACE);
break;
}
}
@ -214,13 +203,12 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
} else if (mProcessStep == EMV_CONFIRM_CARD_NO) {
emvHandler.onSetConfirmCardNoResponse(false);
} else if (mProcessStep == EMV_CERT_VERIFY) {
// importCertStatus(1);
// importCertStatus(1);
} else if (mProcessStep == PIN_ERROR) {
emvHandler.onSetPinInputResponse(false, false);
} else if (mProcessStep == EMV_ONLINE_PROCESS) {
importOnlineProcess(SdkResult.Success, new EmvOnlineResultEntity());
} else if (mProcessStep == EMV_SIGNATURE) {
// emvHandler.
// importSignatureStatus(1);
} else if (mProcessStep == EMV_SHOW_PIN_PAD) {
emvHandler.onSetPinInputResponse(false, false);
@ -300,8 +288,6 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
if(isCardLessTrans()) {
transResult.setValue(TransResultStatus.SUCCESS);
} else if(payDetailRes.getCardType() == CardTypeX.MANUAL.value) {
transResult.setValue(TransResultStatus.SUCCESS);
}
} else {
@ -309,8 +295,6 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
if(isCardLessTrans()) {
transResult.setValue(TransResultStatus.FAIL);
} else if(payDetailRes.getCardType() == CardTypeX.MANUAL.value) {
transResult.setValue(TransResultStatus.FAIL);
}
/*
* @Note
@ -508,9 +492,9 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
private void handleTransactionProcess() {
String cardNo = mPayDetail.getCardNo();
// if (cardNo == null || TextUtils.equals(cardNo, "")) {
if (cardNo == null || TextUtils.equals(cardNo, "")) {
getCardInfo();
// }
}
getPayWaveData();
getF055Data();
if(transType.getValue() == TransactionsType.PRE_AUTH_COMPLETE || transType.getValue() == TransactionsType.PRE_AUTH_VOID || transType.getValue() == TransactionsType.REFUND ) {

View File

@ -13,109 +13,126 @@ import java.util.Objects;
public class InputAmountViewModel extends ViewModel {
private static final String TAG = InputAmountViewModel.class.getSimpleName();
public MutableLiveData<String> inputAmountView = new MutableLiveData<>();
public SingleLiveEvent<String> invalidAmountMsg = new SingleLiveEvent<>();
public SingleLiveEvent<String> availableAmount = new SingleLiveEvent<>();
private static final int MAX_INT_DIGITS = 10;
private static final int MAX_DECIMAL_DIGITS = 2;
public InputAmountViewModel() {
inputAmountView.setValue("0");
}
private String formatInteger(String value) {
if (TextUtils.isEmpty(value)) return "0";
double amt = Double.parseDouble(value);
DecimalFormat formatter = new DecimalFormat("#,###");
return formatter.format(amt);
private int countDecimalDigits(double number) {
String numberStr = Double.toString(number);
int decimalIndex = numberStr.indexOf('.');
return decimalIndex >= 0 ? numberStr.length() - decimalIndex - 1 : 0;
}
public NumberKeyboard.KeyClickCallback onKeyClick() {
return new NumberKeyboard.KeyClickCallback() {
@Override
public void onNumClick(int keyNum) {
String current = inputAmountView.getValue();
if (current == null) return;
String raw = current.replace(",", "");
if (raw.contains(".")) {
String[] parts = raw.split("\\.");
String intPart = parts[0];
String decimalPart = parts.length > 1 ? parts[1] : "";
if (decimalPart.length() >= MAX_DECIMAL_DIGITS) {
return;
}
raw = raw + keyNum;
} else {
if (raw.length() >= MAX_INT_DIGITS) {
return;
}
if (TextUtils.equals(raw, "0")) {
raw = String.valueOf(keyNum);
} else {
raw = raw + keyNum;
}
if (inputAmountView.getValue().length() == 15) {
return;
}
if (raw.contains(".")) {
String[] parts = raw.split("\\.");
String formattedInt = formatInteger(parts[0]);
String decimal = parts.length > 1 ? parts[1] : "";
inputAmountView.setValue(formattedInt + "." + decimal);
if (TextUtils.equals(inputAmountView.getValue(), "0")) {
inputAmountView.setValue(keyNum + "");
} else if (inputAmountView.getValue().contains(".")) {
StringBuilder inputAmount = new StringBuilder();
inputAmount.append(inputAmountView.getValue());
int dotIndex = inputAmount.indexOf(".");
if(inputAmount.substring(dotIndex).length() > 0 && inputAmount.substring(dotIndex+1).length() == 2) {
return;
}
if (inputAmountView.getValue().contains(",")) {
inputAmountView.setValue(inputAmountView.getValue().replace(",", ""));
}
double amt = Double.parseDouble(inputAmountView.getValue());
if (countDecimalDigits(amt) < 2) {
inputAmountView.setValue(inputAmountView.getValue() + keyNum);
}
} else {
inputAmountView.setValue(formatInteger(raw));
if (inputAmountView.getValue().contains(",")) {
inputAmountView.setValue(inputAmountView.getValue().replace(",", ""));
}
inputAmountView.setValue(inputAmountView.getValue() + keyNum);
double amt = Double.parseDouble(inputAmountView.getValue());
DecimalFormat formatter = new DecimalFormat("#,###");
inputAmountView.setValue(formatter.format(amt));
}
}
@Override
public void onDelClick() {
String current = inputAmountView.getValue();
if (current == null) return;
if (current.contains(".")) return;
if (TextUtils.equals(current, "0")) {
if (Objects.requireNonNull(inputAmountView.getValue()).contains(".")) {
return;
}
if (inputAmountView.getValue().length() == 15) {
return;
}
if (TextUtils.equals(inputAmountView.getValue(), "0")) {
inputAmountView.setValue("0.");
} else {
inputAmountView.setValue(current + ".");
inputAmountView.setValue(inputAmountView.getValue() + ".");
}
}
@Override
public void onCleanClick() {
if (inputAmountView.getValue() != null) {
if (inputAmountView.getValue().contains(".")) {
StringBuilder inputAmount = new StringBuilder();
inputAmount.append(inputAmountView.getValue());
inputAmount.deleteCharAt(inputAmount.length() - 1);
inputAmountView.setValue(inputAmount.toString());
} else if (!inputAmountView.getValue().equals("0")) {
StringBuilder inputAmount = new StringBuilder();
inputAmount.append(inputAmountView.getValue());
if (inputAmount.length() > 4) {
String current = inputAmountView.getValue();
if (current == null) return;
if(inputAmount.toString().contains(",")) {
int commaIndex = inputAmount.indexOf(",");
inputAmount.deleteCharAt(commaIndex);
} else {
inputAmount.deleteCharAt(inputAmount.length() - 1);
}
inputAmountView.setValue(inputAmount.toString());
String raw = current.replace(",", "");
if (raw.length() <= 1) {
inputAmountView.setValue("0");
return;
}
// inputAmount.deleteCharAt(inputAmount.toString().length() - 4);
// if (inputAmount.charAt(inputAmount.toString().length() - 4) == ',') {
// inputAmount.deleteCharAt(inputAmount.toString().length() - 4);
// }
// inputAmountView.setValue(inputAmount.toString());
} else if(inputAmount.length() == 1) {
inputAmountView.setValue("0");
} else {
StringBuilder currentAmount = new StringBuilder();
currentAmount.append(inputAmountView.getValue());
currentAmount.deleteCharAt(currentAmount.length() - 1);
inputAmountView.setValue(currentAmount.toString());
}
raw = raw.substring(0, raw.length() - 1);
if (raw.contains(".")) {
String[] parts = raw.split("\\.");
String formattedInt = formatInteger(parts[0]);
String decimal = parts.length > 1 ? parts[1] : "";
inputAmountView.setValue(formattedInt + "." + decimal);
} else {
inputAmountView.setValue(formatInteger(raw));
}
}
}
};
}
}
}

View File

@ -1,23 +1,18 @@
package com.utsmm.kbz.ui.core_viewmodel;
import android.graphics.Bitmap;
import android.util.Log;
import dagger.hilt.android.lifecycle.HiltViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.google.gson.Gson;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptResponse;
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest;
import com.utsmyanmar.baselib.network.model.sirius.SiriusResponse;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.baselib.util.TerminalUtil;
import com.utsmyanmar.ecr.data.TransType;
import com.utsmyanmar.ecr.data.model.Transactions;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.QRSettleData;
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
import com.utsmyanmar.paylibs.system.SingleLiveEvent;
@ -31,15 +26,9 @@ import com.utsmyanmar.paylibs.utils.enums.HostType;
import java.util.List;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import retrofit2.HttpException;
import com.utsmyanmar.paylibs.utils.LogUtil;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject;
@HiltViewModel
@ -65,16 +54,15 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent<String> processCode = new SingleLiveEvent<>();
public SingleLiveEvent<PayDetail> payDetail = new SingleLiveEvent<>();
public SingleLiveEvent<List<PayDetail>> payDetails = new SingleLiveEvent<>();
public SingleLiveEvent<PrintStatus> printStatus = new SingleLiveEvent<>();
public SingleLiveEvent<String> merchantName = new SingleLiveEvent<>();
public SingleLiveEvent<String> transactionName = new SingleLiveEvent<>();
// In SharedViewModel
public MutableLiveData<Boolean> onSettlementResultDone = new MutableLiveData<>(false);
/*Apr 28 2022*/
public SingleLiveEvent<List<PayDetail>> payDetailList = new SingleLiveEvent<>();
/*May 16 2022*/
public SingleLiveEvent<Boolean> isEcr = new SingleLiveEvent<>();
@ -116,8 +104,6 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent<HostType> hostType = new SingleLiveEvent<>();
public MutableLiveData<Integer> printReceiptButtons = new MutableLiveData<>(0);
public SingleLiveEvent<Boolean> printerDisabled = new SingleLiveEvent<>();
public SingleLiveEvent<Boolean> suppressReprintButtons = new SingleLiveEvent<>();
public SingleLiveEvent<String> printReceiptMsg = new SingleLiveEvent<>();
@ -164,8 +150,6 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent<String> loadingMsg = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isFallback = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isSeePhone = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isCardAppBlock = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> _isCardDataExist = new SingleLiveEvent<>();
@ -173,23 +157,16 @@ public class SharedViewModel extends ViewModel {
private PayDetail mPayDetail = new PayDetail();
public MutableLiveData<String> serialNumber = new MutableLiveData<>();
// Updated constructor for Hilt ViewModel
@Inject
public SharedViewModel(Repository repository) {
this.repository = repository;
setPrintStatus(PrintStatus.FIRST_PRINT);
isReprint.setValue(false);
suppressReprintButtons.setValue(false);
cardNo.setValue("");
String sn = TerminalUtil.getInstance().getSerialNo();
serialNumber.setValue(sn);
}
public void setEmvTrans(boolean status) {
isEmv.setValue(status);
}
@ -208,23 +185,6 @@ public class SharedViewModel extends ViewModel {
printReceiptButtons.postValue(value);
}
public void setTransactionsType(TransactionsType transactionsType) {
this.transactionsType.setValue(transactionsType);
}
public SingleLiveEvent<TransactionsType> getTransactionsType() {
return transactionsType;
}
public void setAmount(String amount) {
this.amount.setValue(amount);
}
public SingleLiveEvent<String> getAmount() {
return amount;
}
public void setPrintReceiptMsg(String msg) { this.printReceiptMsg.setValue(msg);}
public void postPrintReceiptMsg(String msg) { this.printReceiptMsg.postValue(msg);}
public void setPrintStatus(PrintStatus printStatus) { this.printStatus.setValue(printStatus); }
public void postPrintStatus(PrintStatus printStatus) { this.printStatus.postValue(printStatus); }
@ -235,14 +195,6 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent<Boolean> getIsFallback() { return isFallback;}
public void setIsCardAppBlock(boolean status) { isCardAppBlock.setValue(status);}
public SingleLiveEvent<Boolean> getIsCardAppBlock() {return isCardAppBlock;}
public void setIsSeePhone(boolean status) { isSeePhone.setValue(status);}
public SingleLiveEvent<Boolean> getIsSeePhone() { return isSeePhone;}
public void setCardDataExist(boolean exist) { _isCardDataExist.setValue(exist);}
public SingleLiveEvent<Boolean> getCardDataExist() { return _isCardDataExist; }
@ -298,7 +250,6 @@ public class SharedViewModel extends ViewModel {
return repository.getParams(siriusRequest);
}
private void printReceipt(boolean isMerchantCopy) {
PrintXReceipt.getInstance().printSmileReceipt(payDetail.getValue(), isMerchantCopy, new PrintXStatus() {
@Override
@ -330,7 +281,6 @@ public class SharedViewModel extends ViewModel {
public void startPrintReceipt(boolean isFirstPrint) {
/*
* First Print is Merchant Copy..
@ -411,29 +361,23 @@ public class SharedViewModel extends ViewModel {
}
public void startPrintSettlement(PrintXStatus printXStatus) {
if(payDetail.getValue() == null) return;
if(payDetail.getValue().getTransactionType() == TransactionsType.SETTLEMENT.value) {
startPrintProcessSettlement(printXStatus);
} else {
startPrintProcessQRSettlement(printXStatus);
}
}
public void startPrintProcessSettlement(PrintXStatus printXStatus) {
public void startPrintProcessSettlement() {
if(payDetail.getValue() == null) return;
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(),printXStatus);
}
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(), new PrintXStatus() {
@Override
public void onSuccess() {
private void startPrintProcessQRSettlement(PrintXStatus printXStatus) {
}
@Override
public void onFailure() {
if(payDetail.getValue() == null && payDetails.getValue() == null) return;
PrintXReceipt.getInstance().printQRSettlementReport(payDetail.getValue(), QRSettleData.convertFromPayDetail(payDetails.getValue()), printXStatus);
}
});
/*POS */
// PrintReceipt.getInstance().printSettlementReceiptPOS(settleData.getSaleCount(), settleData.getSaleAmount(), settleData.getRefundCount(), settleData.getRefundAmount(), settleData.getPreAuthCount(), settleData.getPreAuthAmount(), true);
}
@ -462,47 +406,4 @@ public class SharedViewModel extends ViewModel {
}
public void pushReceipt(Object body){
Log.d("push receipt", new Gson().toJson(body));
repository.sendReceipt(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> Log.d("E-Receipt", "Success =>"+ response.getMessage()),
error -> {
if (error instanceof HttpException) {
HttpException httpEx = (HttpException) error;
try {
String errorJson = httpEx.response().errorBody().string();
Log.e("E-Receipt", "Raw error JSON => " + errorJson);
// Parse JSON to model
EReceiptResponse res = new Gson().fromJson(errorJson, EReceiptResponse.class);
Log.e("E-Receipt", "Parsed Error => " + res.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
} else {
Log.e("E-Receipt", "Unexpected error => " + error.getMessage());
}
}
);
}
public void printTerminalHostConfigs(){
PrintXReceipt.getInstance().printTerminalHostConfig(new PrintXStatus() {
@Override
public void onSuccess() {
Log.d("PrintConfig", "Print Terminal Config Success.");
}
@Override
public void onFailure() {
Log.e("PrintConfig", "Print Terminal Config Success.");
}
});
}
}

View File

@ -71,7 +71,7 @@ public class TMSProcessViewModel extends ViewModel {
}
public void loadEmvParameters() {
// emvParamOperation.loadAidRids();
emvParamOperation.loadAidRids();
emvParamOperation.loadEmvTerminalParam();
}

View File

@ -1,118 +0,0 @@
package com.utsmm.kbz.ui.dashboard;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.utils.enums.HostType;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.databinding.FragmentDashboardHistoryScreenBinding;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.management.CardViewAdapter;
import com.utsmm.kbz.ui.management.ManagementViewModel;
import java.util.ArrayList;
public class DashboardHistoryFragment extends DataBindingFragment {
private ManagementViewModel managementViewModel;
private SharedViewModel sharedViewModel;
private CardViewAdapter cardViewAdapter;
private int routeId;
private final ArrayList<PayDetail> lists = new ArrayList<>();
@Override
protected void initViewModel() {
managementViewModel = getFragmentScopeViewModel(ManagementViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_dashboard_history_screen, BR.manageViewModel, managementViewModel)
.addBindingParam(BR.sharedViewModel, sharedViewModel);
}
@Override
protected int currentId() {
return R.id.dashboardHistoryFragment;
}
@Override
protected int hostId() {
return Constants.NAV_HOST_ID;
}
@Override
protected int routeId() {
return routeId;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
observeHistory();
}
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon(getString(R.string.title_history));
}
private void observeHistory() {
managementViewModel.getTransactionHistory().observe(getViewLifecycleOwner(), payDetailList -> {
if (payDetailList == null) {
return;
}
lists.clear();
if (payDetailList.isEmpty()) {
managementViewModel.detailReportLayoutVisibility.setValue(0);
managementViewModel.detailReportBottomLayoutVisibility.setValue(8);
} else {
managementViewModel.detailReportLayoutVisibility.setValue(8);
managementViewModel.detailReportBottomLayoutVisibility.setValue(0);
}
for (PayDetail payDetail : payDetailList) {
if (payDetail.getTransactionType() == TransactionsType.MMQR.value
|| payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value
|| payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value
|| payDetail.getTransactionType() == TransactionsType.MMQR_SETTLEMENT.value
|| payDetail.getTransactionType() == TransactionsType.REVERSAL.value) {
continue;
}
lists.add(payDetail);
}
if (lists.isEmpty()) {
managementViewModel.detailReportBottomLayoutVisibility.setValue(8);
managementViewModel.detailReportLayoutVisibility.setValue(0);
}
cardViewAdapter = new CardViewAdapter(lists, payDetail -> {
sharedViewModel.setTransMenu(TransMenu.REPRINT);
sharedViewModel.suppressReprintButtons.setValue(true);
sharedViewModel.payDetail.postValue(payDetail);
routeId = R.id.action_dashboardHistoryFragment_to_confirmTransactionFragment;
safeRouteTo(currentId(), routeId, hostId());
});
((FragmentDashboardHistoryScreenBinding) mBinding).setMyAdapter(cardViewAdapter);
});
}
}

View File

@ -10,8 +10,6 @@ import androidx.annotation.Nullable;
import com.utsmm.kbz.util.enums.SettlementType;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
@ -68,60 +66,8 @@ public class DashboardTransFragment extends DataBindingFragment {
initData();
}
// private void initData() {
// TMSUtil.getInstance().checkFeaturesList(requireActivity(),featuresList);
// mainAdapter.notifyDataSetChanged();
// }
Boolean isRefundEnabled = SystemParamsOperation.getInstance().getRefundStatus();
Boolean isVoidEnabled = SystemParamsOperation.getInstance().getVoidStatus();
Boolean isPreAuthEnabled = SystemParamsOperation.getInstance().getPreAuthStatus();
Boolean isCashAdvanceEnabled = SystemParamsOperation.getInstance().getCashAdvanceStatus();
private void initData() {
featuresList.clear();
ArrayList<Features> allFeatures = new ArrayList<>();
TMSUtil.getInstance().checkFeaturesList(requireActivity(), allFeatures);
for (Features feature : allFeatures) {
switch (feature.getFeaturesType()) {
case REFUND:
if (isRefundEnabled) {
featuresList.add(feature);
}
break;
case VOID:
if (isVoidEnabled) {
featuresList.add(feature);
}
break;
case PRE_AUTH_SALE:
case PRE_AUTH_COMPLETE_VOID:
case PRE_AUTH_VOID:
case PRE_AUTH_COMPLETE:
if (isPreAuthEnabled) {
featuresList.add(feature);
}
break;
case CASH_ADVANCE:
if(isCashAdvanceEnabled){
featuresList.add(feature);
}
break;
default:
featuresList.add(feature);
break;
}
}
TMSUtil.getInstance().checkFeaturesList(requireActivity(),featuresList);
mainAdapter.notifyDataSetChanged();
}
@ -157,8 +103,8 @@ public class DashboardTransFragment extends DataBindingFragment {
case CASH_ADVANCE:
new DashboardTransFragment.ClickEvent().onClickCashAdvance();
break;
case DEVICE_CONFIG:
new DashboardTransFragment.ClickEvent().onClickDeviceConfig();
case HISTORY:
new DashboardTransFragment.ClickEvent().onClickHistory();
break;
}
@ -179,7 +125,7 @@ public class DashboardTransFragment extends DataBindingFragment {
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Boolean demoStatus = SystemParamsOperation.getInstance().getDemoStatus();
}
public class ClickEvent {
@ -189,7 +135,7 @@ public class DashboardTransFragment extends DataBindingFragment {
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
sharedViewModel.setTransactionsType(TransactionsType.VOID);
sharedViewModel.transactionsType.setValue(TransactionsType.VOID);
// sharedViewModel.transMenu.postValue(TransMenu.TRANSACTIONS);
sharedViewModel.setTransMenu(TransMenu.TRANSACTIONS);
@ -201,15 +147,16 @@ public class DashboardTransFragment extends DataBindingFragment {
public void onClickSettlement() {
sharedViewModel.settlementType.setValue(SettlementType.NORMAL);
sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT);
sharedViewModel.setTransMenu(TransMenu.SETTLEMENT);
sharedViewModel.setTransactionsType(TransactionsType.SETTLEMENT);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickRefund() {
sharedViewModel.setTransactionsType(TransactionsType.REFUND);
sharedViewModel.transactionsType.setValue(TransactionsType.REFUND);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
@ -220,7 +167,8 @@ public class DashboardTransFragment extends DataBindingFragment {
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_SALE);
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_SALE);
routeId = R.id.action_dashboardTransFragment_to_inputAmountFragment;
safeRouteTo(currentId,routeId,hostId);
}
@ -228,24 +176,23 @@ public class DashboardTransFragment extends DataBindingFragment {
}
public void onClickPreAuthCancel () {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_FULL_VOID);
sharedViewModel.amount.postValue("0"); // null to 0
// sharedViewModel.amount.postValue(null);
sharedViewModel.amount.postValue(null);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickPreAuthComp () {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_COMPLETE);
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_COMPLETE);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickPreAuthCompCancel () {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_COMPLETE_VOID);
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_COMPLETE_VOID);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
@ -253,16 +200,18 @@ public class DashboardTransFragment extends DataBindingFragment {
public void onClickCashAdvance() {
sharedViewModel.setTransactionsType(TransactionsType.CASH_OUT);
sharedViewModel.setTransMenu(TransMenu.CASH_OUT);
sharedViewModel.transactionsType.setValue(TransactionsType.CASH_OUT);
routeId = R.id.action_dashboardTransFragment_to_inputAmountFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickDeviceConfig(){
routeId = R.id.action_dashboardTransFragment_to_deviceConfig;
safeRouteTo(currentId, routeId, hostId);
public void onClickHistory() {
routeId = R.id.action_dashboardTransFragment_to_manageFunctionFragment;
safeRouteTo(currentId,routeId,hostId);
}
}
}

View File

@ -13,7 +13,6 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.kizzy.xpay.util.Sign;
import com.utsmm.kbz.ui.qr_pay.QRRefund;
import com.utsmyanmar.baselib.network.model.DemoQRRequest;
import com.utsmyanmar.baselib.network.model.DemoQRResponse;
import com.utsmyanmar.baselib.network.model.DemoQRReturnRequest;
@ -37,16 +36,12 @@ import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.system.SingleLiveEvent;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsSettings;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
@ -57,11 +52,7 @@ public class KPayViewModel extends ViewModel {
private final Repository repository;
private final String appKey = SystemParamsOperation.getInstance().getAppKey();
// private final String appKey = "UTSMMuat@2025";
private final String appId = SystemParamsOperation.getInstance().getAppId();
// private final String appId = "kp9b0794b349ae85b00c51e0677484c7";
private final String appKey = "UTSMMuat@2025";
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final Handler mainHandler = new Handler(Looper.getMainLooper());
@ -70,7 +61,10 @@ public class KPayViewModel extends ViewModel {
private static final String NONCE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final int NONCE_LENGTH = 32;
private final SecureRandom secureRandom = new SecureRandom();
public MutableLiveData<Boolean> partialRefundEnabled = new MutableLiveData<>();
private String generateRandomTwoChars() {
// You can reuse the existing character set and SecureRandom instance
@ -120,7 +114,7 @@ public class KPayViewModel extends ViewModel {
bizContent.put("refund_request_no", refundOrderId);
bizContent.put("merch_order_id", origOrderId);
bizContent.put("merch_code", mid);
bizContent.put("appid", appId);
bizContent.put("appid", "kp9b0794b349ae85b00c51e0677484c7");
if(!refundAmount.equals("0")) {
bizContent.put("refund_amount", refundAmount);
}
@ -144,7 +138,7 @@ public class KPayViewModel extends ViewModel {
KPayRefund.RefundRequest.RequestBody.BizContent biz =
new KPayRefund.RefundRequest.RequestBody.BizContent(
appId,
"kp9b0794b349ae85b00c51e0677484c7",
mid,
origOrderId,
refundAmount, // This can be null for original refunds
@ -166,7 +160,7 @@ public class KPayViewModel extends ViewModel {
} else {
KPayRefund.RefundRequest.RequestBody.BizContent biz =
new KPayRefund.RefundRequest.RequestBody.BizContent(
appId,
"kp9b0794b349ae85b00c51e0677484c7",
mid,
origOrderId,
refundOrderId,
@ -193,47 +187,20 @@ public class KPayViewModel extends ViewModel {
return createQR(amount, String.valueOf(System.currentTimeMillis()),mid);
}
private int expireTime = 1;
private void calculateTimeoutMinutes() {
String data = SystemParamsOperation.getInstance().getWaveIntervalTime();
if (data == null || !data.contains("-")) {
data = "15-60"; // fallback
}
try {
String[] parts = data.split("-");
int waitingTimeSec = Integer.parseInt(parts[1]); // only take second part
// convert seconds minutes
expireTime = waitingTimeSec / 60;
// enforce limits 1120
if (expireTime < 1) expireTime = 1;
if (expireTime > 120) expireTime = 120;
} catch (Exception e) {
expireTime = 1; // safety fallback
LogUtil.d(TAG, "Invalid format for timeout config: " + data);
}
}
public KPayQRRequest.QrRequest createQR(String amount, String time,String mid) {
String merchOrderId = "NEX"+SystemParamsOperation.getInstance().getCurrentSerialNum()+generateRandomTwoChars();
String serialNum = TerminalUtil.getInstance().getSerialNo();
String nonceStr = generateNonceStr(); // Generate random nonce_str
calculateTimeoutMinutes();
String timeoutExpress = expireTime + "m";
Map<String, Object> bizContent = new HashMap<>();
bizContent.put("merch_order_id", merchOrderId);
bizContent.put("merch_code", mid);
bizContent.put("appid", appId);
bizContent.put("appid", "kp9b0794b349ae85b00c51e0677484c7");
bizContent.put("trade_type", "PAY_BY_QRCODE");
bizContent.put("total_amount", amount);
bizContent.put("title", "testing");
bizContent.put("operator_id", serialNum);
bizContent.put("timeout_express", timeoutExpress);
// bizContent.put("operator_id", serialNum);
bizContent.put("timeout_express", "100m");
bizContent.put("trans_currency", "MMK");
bizContent.put("callback_info", "callback");
@ -249,16 +216,15 @@ public class KPayViewModel extends ViewModel {
String sign = Sign.INSTANCE.generateSign(requestMap, appKey);
KPayQRRequest.QrRequest.RequestBody.BizContent biz = new KPayQRRequest.QrRequest.RequestBody.BizContent(
appId,
"kp9b0794b349ae85b00c51e0677484c7",
mid,
merchOrderId,
"PAY_BY_QRCODE",
"testing",
amount,
"MMK",
timeoutExpress,
"callback",
serialNum
"100m",
"callback"
);
KPayQRRequest.QrRequest.RequestBody body = new KPayQRRequest.QrRequest.RequestBody(
@ -277,44 +243,6 @@ public class KPayViewModel extends ViewModel {
return qrRequest;
}
public KPayQRRequest.CloseOrderRequest closeQrOrder(String merchOrderId, String mid){
String currentTime = String.valueOf(System.currentTimeMillis());
String nonceStr = generateNonceStr(); // Generate random nonce_str
Map<String, Object> bizContentMap = new HashMap<>();
bizContentMap.put("merch_order_id", merchOrderId);
bizContentMap.put("merch_code", mid);
bizContentMap.put("appid", appId);
Map<String, Object> requestMap = new HashMap<>();
requestMap.put("timestamp", currentTime);
requestMap.put("nonce_str", nonceStr);
requestMap.put("method", "kbz.payment.closeorder");
requestMap.put("version", "3.0");
requestMap.put("biz_content", bizContentMap);
String sign = Sign.INSTANCE.generateSign(requestMap, appKey);
KPayQRRequest.CloseOrderRequest.Request.BizContent bizContent = new KPayQRRequest.CloseOrderRequest.Request.BizContent(
merchOrderId,
mid,
appId
);
KPayQRRequest.CloseOrderRequest.Request requestBody = new KPayQRRequest.CloseOrderRequest.Request(
currentTime,
"kbz.payment.closeorder",
nonceStr,
"SHA256",
sign,
"3.0",
bizContent
);
KPayQRRequest.CloseOrderRequest request = new KPayQRRequest.CloseOrderRequest(requestBody);
return request;
}
public KPayQRQueryRequest.QRQueryRequest getQrStatus(String merchOrderId, String mid) {
@ -324,7 +252,7 @@ public class KPayViewModel extends ViewModel {
Map<String, Object> bizContentMap = new HashMap<>();
bizContentMap.put("merch_order_id", merchOrderId);
bizContentMap.put("merch_code", mid);
bizContentMap.put("appid", appId);
bizContentMap.put("appid", "kp9b0794b349ae85b00c51e0677484c7");
Map<String, Object> requestMap = new HashMap<>();
requestMap.put("timestamp", currentTime);
@ -336,7 +264,7 @@ public class KPayViewModel extends ViewModel {
String sign = Sign.INSTANCE.generateSign(requestMap, appKey);
KPayQRQueryRequest.QRQueryRequest.Request.BizContent bizContent = new KPayQRQueryRequest.QRQueryRequest.Request.BizContent(
appId,
"kp9b0794b349ae85b00c51e0677484c7",
mid,
merchOrderId
);
@ -356,19 +284,13 @@ public class KPayViewModel extends ViewModel {
return request;
}
@Inject
public KPayViewModel(Repository repository) {
this.repository = repository;
boolean enabled = SystemParamsOperation.getInstance().isQrPartialRefundEnable();
partialRefundEnabled.setValue(enabled);
}
private TradeData tradeData;
private PayDetail payDetail;
private QRRefund qrRefund;
public void setTradeData(TradeData tradeData){
this.tradeData = tradeData;
@ -382,12 +304,6 @@ public class KPayViewModel extends ViewModel {
public void setPayDetail(PayDetail payDetail) {
this.payDetail = payDetail;
}
public void setQrRefund(QRRefund qrRefund) {
this.qrRefund = qrRefund;
}
public QRRefund getQrRefund() {
return qrRefund;
}
public PayDetail getPayDetail() { return payDetail; }
@ -439,11 +355,4 @@ public class KPayViewModel extends ViewModel {
public Observable<KPayRefund.RefundResponse> kPayRefund(KPayRefund.RefundRequest refundRequest) {
return repository.kPayRefund(refundRequest);
}
public Observable<KPayQRRequest.CloseOrderResponse> closeQrOrderApi(
KPayQRRequest.CloseOrderRequest request
) {
return repository.qrCloseOrder(request);
}
}

View File

@ -25,7 +25,6 @@ import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.TransactionUtil;
import com.utsmm.kbz.util.ecr.CoreUtils;
import java.text.DecimalFormat;
import java.util.Locale;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
@ -136,14 +135,10 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
}
private void generateQR() {
long originalAmount = payDetail.getAmount();
// String amount = String.format(Locale.getDefault(), "%.2f", payDetail.getAmount()/100.0);
// String amount = String.format(Locale.getDefault(), "%d", (int)(payDetail.getAmount()/100.0)); //this method have problem for 10055 to 100.00 auto convert (should convert to 100.55)
double realAmount = payDetail.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
String amount = df.format(realAmount);
String amount = String.format(Locale.getDefault(), "%d", (int)(payDetail.getAmount()/100.0));
KPayQRRequest.QrRequest kPayQRRequest = KPayViewModel.createQR(amount, merchantId);
@ -168,6 +163,7 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
LogUtil.d(TAG,"Ref Label :"+refLabel);
payDetail.setPayQRCode(response.getResponse().getQrCode());
payDetail.setQrReferNo(refLabel);
payDetail.setQrTransStatus(2);
payDetail.setReferNo(refLabel);

View File

@ -11,10 +11,8 @@ import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.KPayRefund;
//import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptQRRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
@ -36,8 +34,6 @@ import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import com.utsmyanmar.paylibs.utils.LogUtil;
import java.text.DecimalFormat;
public class QRRefundFragment extends DataBindingFragment {
private SharedViewModel sharedViewModel;
@ -196,16 +192,16 @@ public class QRRefundFragment extends DataBindingFragment {
payDetail.setAmount(refundAmount == null ? 0 : POSUtil.getInstance().convertAmount(refundAmount));
payDetail.setOriginalTransDate(dateTime);
payDetail.setQrTransStatus(1);
payDetail.setQrReferNo(referenceNo);
payDetail.setReferNo(referenceNo);
payDetail.setIsCanceled(true);
// sharedViewModel.pushReceipt(buildEReceiptQRReceipt(payDetail, true, "Refund success"));
retrievedUpdatePayDetail(referenceNo);
} else {
LogUtil.d(TAG, "Refund failed!");
payDetail.setQrTransStatus(-1);
payDetail.setQrReferNo(referenceNo);
payDetail.setReferNo(referenceNo);
String errorMsg = "Refund failed";
@ -214,8 +210,6 @@ public class QRRefundFragment extends DataBindingFragment {
}
payDetail.setTradeResultDes(errorMsg);
// sharedViewModel.pushReceipt(buildEReceiptQRReceipt(payDetail, true, "RESP CODE [68]\n Refund Failed"));
sharedViewModel.payDetail.setValue(payDetail);
navigateToNext();
}
@ -334,6 +328,4 @@ public class QRRefundFragment extends DataBindingFragment {
}
}
}
}

View File

@ -2,6 +2,7 @@ package com.utsmm.kbz.ui.kpay;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@ -9,12 +10,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmm.kbz.util.enums.TransResultStatus;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.DemoQRStatusRequest;
import com.utsmyanmar.baselib.network.model.KPayQRQueryRequest;
import com.utsmyanmar.baselib.network.model.KPayQRRequest;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TimeoutCallback;
import com.utsmyanmar.ecr.ECRHelper;
@ -125,7 +123,6 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
terminalId = TransactionUtil.getInstance().getQRTerminalId();
merchantId = TransactionUtil.getInstance().getQRMerchantId();
refLabel = sharedViewModel.qrRefNum.getValue();
// tradeData = waveViewModel.getTradeData();
@ -135,7 +132,6 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
sharedViewModel.insertPayDetail(payDetail);
}
@ -184,25 +180,14 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
initSetup();
calculateIntervalAndCount();
LogUtil.d(TAG,"intervalInSec: "+intervalInSec+" totalCount: "+totalCount);
setUpTimeout();
setUpCountDown();
requireActivity().getOnBackPressedDispatcher().addCallback(
getViewLifecycleOwner(),
new androidx.activity.OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
showExitConfirmation();
}
}
);
}
private void setUpCountDown() {
int totalTime = intervalInSec * totalCount;
setupTimeout(totalTime, new TimeoutCallback() {
setupTimeout(10, new TimeoutCallback() {
@Override
public void onTrick(long trickTime) {
sharedViewModel.countDownTxt.setValue((trickTime / 1000)+"");
@ -287,6 +272,9 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
Disposable setUpDi = Observable.interval(intervalInSec, TimeUnit.SECONDS) // Emit an item every 10 seconds
.take(totalCount) // Take only 3 emissions
.flatMap(tick -> {
// Make the API call here using Retrofit
// WaveStatusRequest request = new WaveStatusRequest(refLabel, merchantId);
// DemoQRStatusRequest request = new DemoQRStatusRequest(refLabel, merchantId);
KPayQRQueryRequest.QRQueryRequest request = kPayViewModel.getQrStatus(refLabel,merchantId);
return kPayViewModel.checkStatus(request)
@ -309,29 +297,17 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
* trans is success !*/
// String transStatus = response.getTransactionStatus();
// String transTime = response.getResponse().;
if(response.getResponse().getWalletIdentifier() != null) {
payDetail.setCustomerMobile(response.getResponse().getWalletIdentifier());
} else {
payDetail.setCustomerMobile("KBZPay");
}
if(response.getResponse().getMmqrRef() != null) {
payDetail.setQrReferNo(response.getResponse().getMmqrRef());
}
payDetail.setTC(response.getResponse().getTradeStatus());
payDetail.setCustomerMobile("KBZ PAY");
payDetail.setQrReferNo(refLabel);
payDetail.setQrTransId(response.getResponse().getMmOrderId());
payDetail.setReferNo(refLabel);
payDetail.setApprovalCode(response.getResponse().getMmOrderId());
payDetail.setQrTransStatus(1);
payDetail.setTradeDateAndTime(response.getResponse().getPaySuccessTime());
payDetail.setOriginalTransDate(response.getResponse().getPaySuccessTime());
retrievedUpdatePayDetail(refLabel, payDetail,false);
EReceiptRequest request = EReceiptUtil.getInstance().generateQRReceipt(payDetail, TransResultStatus.SUCCESS);
sharedViewModel.pushReceipt(request);
return;
}
@ -341,11 +317,6 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
payDetail.setQrTransStatus(2);
}
EReceiptRequest request = EReceiptUtil.getInstance().generateQRReceipt(payDetail, TransResultStatus.FAIL);
sharedViewModel.pushReceipt(request);
sharedViewModel.insertPayDetail(payDetail);
sharedViewModel.payDetail.postValue(payDetail);
safeNavigateToRouteId();
@ -353,24 +324,16 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
} catch (Exception e) {
LogUtil.d(TAG, "On Exception::");
// sharedViewModel.pushReceipt(buildEReceiptQRReceipt(payDetail, false, "QR Failed! :" + e.getMessage()));
e.printStackTrace();
if (count == totalCount) {
if(payDetail.getQrTransStatus() != -1) {
payDetail.setQrTransStatus(2);
}
EReceiptRequest request = EReceiptUtil.getInstance().generateQRReceipt(payDetail, TransResultStatus.TIME_OUT);
sharedViewModel.pushReceipt(request);
sharedViewModel.insertPayDetail(payDetail);
sharedViewModel.payDetail.postValue(payDetail);
safeNavigateToRouteId();
}
}
@ -434,48 +397,6 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
popBackStack();
}
private void showExitConfirmation() {
new androidx.appcompat.app.AlertDialog.Builder(requireContext())
.setTitle("Exit QR Transaction?")
.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", (dialog, which) -> {
dialog.dismiss();
if (sharedViewModel.isEcr.getValue() != null) {
if (sharedViewModel.isEcr.getValue()) {
finishECR();
}
}
closeOrder();
popBackStack();
})
.setNegativeButton("No", (dialog, which) -> dialog.dismiss())
.show();
}
private void closeOrder(){
String refNo = sharedViewModel.qrRefNum.getValue();
String mid = TransactionUtil.getInstance().getQRMerchantId();
if (refNo == null || mid == null) {
LogUtil.e("QR", "Missing ref or merchant ID. Cannot close order.");
return;
}
KPayQRRequest.CloseOrderRequest request = kPayViewModel.closeQrOrder(refNo, mid);
kPayViewModel.closeQrOrderApi(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
resp -> {
LogUtil.d("CloseOrder", "Result = " + resp.getResponse().getResult());
LogUtil.d("CloseOrder", "Msg = " + resp.getResponse().getMsg());
},
err -> {
LogUtil.e("CloseOrder", "Error = " + err.getMessage());
}
);
}
private String getECRResponseMessage() {
sharedViewModel.payDetail.setValue(payDetail);

View File

@ -7,6 +7,7 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.sunmi.pay.hardware.aidlv2.bean.EMVCandidateV2;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.ui.ListDialog;
import com.utsmyanmar.baselib.util.DataBindingConfig;
@ -67,6 +68,20 @@ public class TestFragment extends DataBindingFragment {
return 0;
}
private String[] getCandidateNames(List<EMVCandidateV2> candiList) {
if (candiList == null || candiList.size() == 0) return new String[0];
String[] result = new String[candiList.size()];
for (int i = 0; i < candiList.size(); i++) {
EMVCandidateV2 candi = candiList.get(i);
String name = candi.appPreName;
name = TextUtils.isEmpty(name) ? candi.appLabel : name;
name = TextUtils.isEmpty(name) ? candi.appName : name;
name = TextUtils.isEmpty(name) ? "" : name;
result[i] = name;
LogUtil.e(Constant.TAG, "EMVCandidateV2: " + name);
}
return result;
}
private void showCandiListDialog(String[] list) {
if (mListDialog == null) {

View File

@ -72,7 +72,6 @@ public class DetailReportFragment extends DataBindingFragment {
super.onResume();
setToolBarTitleWithBackIcon(getResourceString(R.string.txt_subtitle_print_detail_report));
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
showLoadingView();
}
@ -94,8 +93,12 @@ public class DetailReportFragment extends DataBindingFragment {
managementViewModel.hostTypeDR.setValue("PAYMENT");
managementViewModel.cardTypeDR.setValue("QR PAY");
} else if(sharedViewModel.hostType.getValue() == HostType.MPU) {
managementViewModel.hostTypeDR.setValue("CARD");
managementViewModel.cardTypeDR.setValue("CARD");
managementViewModel.hostTypeDR.setValue("MPU");
managementViewModel.cardTypeDR.setValue("MPU");
} else if(sharedViewModel.hostType.getValue() == HostType.VISA_MASTER) {
managementViewModel.hostTypeDR.setValue("VISA/MASTER");
managementViewModel.cardTypeDR.setValue("VISA/MASTER");
}
}
@ -149,12 +152,7 @@ public class DetailReportFragment extends DataBindingFragment {
if(sharedViewModel.hostType.getValue() == HostType.MPU) {
if(payDetail.getTransactionType() != TransactionsType.MMQR_REFUND.value
&& payDetail.getTransactionType() != TransactionsType.MMQR.value
&& payDetail.getTransactionType() != TransactionsType.MMQR_SETTLEMENT.value
&& payDetail.getTransactionType() != TransactionsType.REVERSAL.value
&& payDetail.getTransactionType() != TransactionsType.SETTLEMENT.value
&& POSUtil.getInstance().getYesterdayDate().compareTo(POSUtil.getInstance().getDateByString(payDetail.transDate)) < 1) {
if(payDetail.getAccountType().equals("MPU") && payDetail.getTransactionType() != TransactionsType.MMQR_REFUND.value && payDetail.getTransactionType() != TransactionsType.MMQR.value && payDetail.getTransactionType() != TransactionsType.REVERSAL.value && payDetail.getTransactionType() != TransactionsType.SETTLEMENT.value && POSUtil.getInstance().getYesterdayDate().compareTo(POSUtil.getInstance().getDateByString(payDetail.transDate)) < 1) {
boolean isNeedMinusSign = payDetail.getTransactionType() == TransactionsType.VOID.value || payDetail.getTransactionType() == TransactionsType.REFUND.value;
lists.add(payDetail);
count++;
@ -176,6 +174,19 @@ public class DetailReportFragment extends DataBindingFragment {
totalAmount += payDetail.getAmount();
}
}
} if(sharedViewModel.hostType.getValue() == HostType.VISA_MASTER) {
if(!payDetail.getAccountType().equals("MPU") && payDetail.getTransactionType() != TransactionsType.MMQR_REFUND.value && payDetail.getTransactionType() != TransactionsType.MMQR.value && payDetail.getTransactionType() != TransactionsType.REVERSAL.value && payDetail.getTransactionType() != TransactionsType.SETTLEMENT.value && POSUtil.getInstance().getYesterdayDate().compareTo(POSUtil.getInstance().getDateByString(payDetail.transDate)) < 1) {
boolean isNeedMinusSign = payDetail.getTransactionType() == TransactionsType.VOID.value || payDetail.getTransactionType() == TransactionsType.REFUND.value;
lists.add(payDetail);
count++;
if(isNeedMinusSign) {
totalAmount -= payDetail.getAmount();
} else {
totalAmount += payDetail.getAmount();
}
}
}
}
@ -211,10 +222,6 @@ public class DetailReportFragment extends DataBindingFragment {
}
public void onPrint() {
if (!SystemParamsOperation.getInstance().getPrinterEnabled()) {
showDeclineDialog("Printer is disabled!");
return;
}
TradeData tradeData = Params.newTrade(false);
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setTransType(TransactionsType.DETAIL_REPORT.name);

View File

@ -10,7 +10,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.ItemViewHistoryBinding;
import com.utsmm.kbz.databinding.ItemViewDetailReportBinding;
import java.util.List;
@ -35,7 +35,7 @@ public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHold
@NonNull
@Override
public HistoryAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemViewHistoryBinding binding = DataBindingUtil.inflate(
ItemViewDetailReportBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_view_history, parent, false);
@ -58,9 +58,9 @@ public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHold
public class ViewHolder extends RecyclerView.ViewHolder{
public ItemViewHistoryBinding itemBinding;
public ItemViewDetailReportBinding itemBinding;
public ViewHolder(ItemViewHistoryBinding itemRowBinding){
public ViewHolder(ItemViewDetailReportBinding itemRowBinding){
super(itemRowBinding.getRoot());
this.itemBinding = itemRowBinding;
}

View File

@ -122,7 +122,6 @@ public class ManagementFunctionFragment extends DataBindingFragment {
public void onClickReprintLastTrans() {
sharedViewModel.setTransMenu(TransMenu.REPRINT);
sharedViewModel.suppressReprintButtons.setValue(false);
observeLastTransaction();
}

View File

@ -27,7 +27,6 @@ public class ManagementViewModel extends ViewModel {
public SingleLiveEvent<String> processCodeText = new SingleLiveEvent<>();
public SingleLiveEvent<PayDetail> payDetail = new SingleLiveEvent<>();
public SingleLiveEvent<List<PayDetail>> payDetails = new SingleLiveEvent<>();
public SingleLiveEvent<String> panErrorMsg = new SingleLiveEvent<>();
@ -76,10 +75,6 @@ public class ManagementViewModel extends ViewModel {
return repository.getLastSettlement(voucherNo);
}
public LiveData<List<PayDetail>> getLastSettlementQR(String voucherNo){
return repository.getLastSettlementQR(voucherNo);
}
public LiveData<List<PayDetail>> getLastTransaction(String voucherNo){
return repository.getLastTransaction(voucherNo);
}

View File

@ -10,7 +10,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmm.kbz.ui.kpay.KPayViewModel;
import com.utsmm.kbz.util.helper.KeyboardHelper;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.KPayQRQueryRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
@ -129,7 +128,7 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
private void searchByTrace(String trace) {
for (PayDetail s : lists) {
if(s.getVoucherNo().contains(trace)) {
if(s.getVoucherNo().equals(trace)) {
searchedLists.add(s);
}
}
@ -152,13 +151,19 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
String input = managementViewModel.txtRRNTrace.getValue();
if(input != null && !input.isEmpty()) {
searchByTrace(input);
if(input.length() == 6) {
searchByTrace(input);
} else if(input.length() == 12) {
searchByRRN(input);
}
} else {
searchedLists.addAll(lists);
}
cardViewAdapter.updateList(searchedLists);
KeyboardHelper.hide(requireActivity());
}
}
@ -291,27 +296,24 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
// LogUtil.d(TAG,"Transaction settlement config : "+pay.isSettlementEnabled());
// LogUtil.d(TAG,"Transaction batch : "+pay.getBatchNo());
// LogUtil.d(TAG,"Current batch : "+SystemParamsOperation.getInstance().getCurrentBatchNum());
//
// LogUtil.d(TAG,"----------------------------------------------------------");
LogUtil.d(TAG,"----------------------------------------------------------");
if(sharedViewModel.transactionsType.getValue() != null && sharedViewModel.transactionsType.getValue() == TransactionsType.MMQR_HISTORY) {
if(sharedViewModel.transactionsType.getValue() != null && sharedViewModel.transactionsType.getValue() == TransactionsType.MMQR_INQUIRY_STATUS) {
// Wave Inquiry Status::
// April 2, 2024 QR Inquiry status check is for unsuccessful transactions.
if(yesterday.compareTo(transDate) <= 0 && (pay.getTransactionType() == TransactionsType.MMQR.value || pay.getTransactionType() == TransactionsType.MMQR_REFUND.value) ) {
if(yesterday.compareTo(transDate) <= 0 && pay.getTransactionType() == TransactionsType.MMQR.value && pay.getQrTransStatus() != 1) {
filteredLists.add(pay);
}
} else {
// Reprint Any Transaction::
if(yesterday.compareTo(transDate) <= 0
&& pay.getTransactionType() != TransactionsType.SETTLEMENT.value
&& pay.getTransactionType() != TransactionsType.MMQR_SETTLEMENT.value
&& pay.getTransactionType() != TransactionsType.REVERSAL.value) {
if(yesterday.compareTo(transDate) <= 0 && pay.getTransactionType() != TransactionsType.SETTLEMENT.value && pay.getTransactionType() != TransactionsType.REVERSAL.value) {
// April 2, 2024 client requested to add QR host at host selection type
if(sharedViewModel.hostType.getValue() == HostType.MPU) {
if(pay.getTransactionType() != TransactionsType.MMQR.value && pay.getTransactionType() != TransactionsType.MMQR_REFUND.value) {
if(pay.getAccountType().equals("MPU") && pay.getTransactionType() != TransactionsType.MMQR.value && pay.getTransactionType() != TransactionsType.MMQR_REFUND.value) {
filteredLists.add(pay);
}
@ -321,6 +323,10 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
filteredLists.add(pay);
}
}
} else if(sharedViewModel.hostType.getValue() == HostType.VISA_MASTER) {
if(!pay.getAccountType().equals("MPU") && pay.getTransactionType() != TransactionsType.MMQR.value && pay.getTransactionType() != TransactionsType.MMQR_REFUND.value) {
filteredLists.add(pay);
}
}
}
@ -361,12 +367,7 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
* */
// sharedViewModel.transMenu.postValue(TransMenu.REPRINT);
sharedViewModel.setTransMenu(TransMenu.REPRINT);
sharedViewModel.suppressReprintButtons.setValue(false);
// payDetail.setTransType(payDetail.getTransType()+"(REPRINT)");
//tempo guarding the Reprint duplicate by kmk
if (!payDetail.getTransType().contains("REPRINT")) {
payDetail.setTransType(payDetail.getTransType() + "(REPRINT)");
}
payDetail.setTransType(payDetail.getTransType()+"(REPRINT)");
sharedViewModel.payDetail.postValue(payDetail);
routeId = R.id.action_reprintAnyTransactionFragment_to_confirmTransactionFragment;

View File

@ -13,8 +13,8 @@ import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.DialogCallback;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.QRSettleData;
import com.utsmyanmar.paylibs.print.PrintHelper;
import com.utsmyanmar.paylibs.print.PrintReceipt;
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
@ -26,9 +26,6 @@ import com.utsmm.kbz.ui.core_viewmodel.TransProcessViewModel;
import java.util.List;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.enums.HostType;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.POSUtil;
public class ReprintReceiptFragment extends DataBindingFragment {
@ -37,7 +34,7 @@ public class ReprintReceiptFragment extends DataBindingFragment {
private ManagementViewModel managementViewModel;
private SharedViewModel sharedViewModel;
private static final String TAG = ReprintReceiptFragment.class.getSimpleName();
private static final String TAG = PrintReceipt.class.getSimpleName();
private PayDetail payDetail;
@ -111,7 +108,7 @@ public class ReprintReceiptFragment extends DataBindingFragment {
private void updateUIPrintReceiptFailure(PayDetail payDetail) {
sharedViewModel.printReceiptMsg.postValue(getString(R.string.txt_printing_settlement_report_failure));
sharedViewModel.reprintBtnLayout.postValue(0);
// ReprintReceiptFragment.this.payDetail = payDetail;
ReprintReceiptFragment.this.payDetail = payDetail;
}
private void checkPaperExists(PayDetail payDetail) {
@ -145,67 +142,42 @@ public class ReprintReceiptFragment extends DataBindingFragment {
}
private void observeLastSettlement() {
managementViewModel.getLastSettlement(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetails) {
if (payDetails != null) {
if (payDetails.size() != 0) {
PayDetail payDetail = payDetails.get(payDetails.size() - 1);
payDetail.setTransType( payDetail.getTransType()+"(REPRINT)");
checkPaperExists(payDetail);
payDetail = sharedViewModel.payDetail.getValue();
if (payDetail == null) {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
navigateMainScreen();
return;
}
sharedViewModel.totalAmount.postValue(payDetail.getAmount());
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount()));
String transType = payDetail.getTransType();
if (transType == null) {
transType = "";
}
payDetail.setTransType(transType + "(REPRINT)");
checkPaperExists(payDetail);
// managementViewModel.payDetail.observe(getViewLifecycleOwner(), new Observer<PayDetail>() {
// @Override
// public void onChanged(PayDetail pay) {
// if (pay != null) {
//
// payDetail = pay;
//
//
//
//
//
// } else {
// showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
// navigateMainScreen();
// }
// }
// });
} else {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
navigateMainScreen();
}
}
}
});
}
private void printReceipt(PayDetail payDetail) {
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail, new PrintXStatus() {
@Override
public void onSuccess() {
delayFunctionCall(ReprintReceiptFragment.this::navigateMainScreen);
}
if (payDetail.getTransactionType() == TransactionsType.MMQR_SETTLEMENT.value) {
PrintXReceipt.getInstance().printQRSettlementReport(payDetail, payDetail.getQrSettleData(), printXStatus);
} else {
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail, printXStatus);
}
@Override
public void onFailure() {
updateUIPrintReceiptFailure(payDetail);
checkPaperExists(payDetail);
}
});
}
private PrintXStatus printXStatus = new PrintXStatus() {
@Override
public void onSuccess() {
delayFunctionCall(ReprintReceiptFragment.this::navigateMainScreen);
}
@Override
public void onFailure() {
updateUIPrintReceiptFailure(payDetail);
// checkPaperExists(payDetail);
}
};
@SuppressWarnings("ConstantConditions")
private void navigateMainScreen() {

View File

@ -72,7 +72,6 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
}
}
checkQRButtonVisibility();
// try {
// int result = MyApplication.getInstance().basicOptBinder.setScreenMode(1);
// } catch (RemoteException e) {
@ -169,16 +168,14 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
observerData();
isReturnTransactions();
}
private void checkQRButtonVisibility() {
if(sharedViewModel.getTransMenu().getValue() == TransMenu.VOID || sharedViewModel.getTransMenu().getValue() == TransMenu.PRE_AUTH_COMPLETE_VOID || sharedViewModel.getTransMenu().getValue() == TransMenu.REVERSAL || sharedViewModel.getTransMenu().getValue() == TransMenu.PRE_AUTH_FULL_VOID ) {
private void isReturnTransactions() {
if(sharedViewModel.getTransMenu().getValue() == TransMenu.VOID || sharedViewModel.getTransMenu().getValue() == TransMenu.PRE_AUTH_COMPLETE_VOID || sharedViewModel.getTransMenu().getValue() == TransMenu.REVERSAL || sharedViewModel.getTransMenu().getValue() == TransMenu.PRE_AUTH_FULL_VOID) {
sharedViewModel.qrPayVisibility.setValue(8);
} else {
sharedViewModel.qrPayVisibility.setValue(0);
}
}
@ -265,62 +262,27 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
});
}
private PayDetail findLastByType(List<PayDetail> payDetails, int transactionType) {
if (payDetails == null) {
return null;
}
for (int i = payDetails.size() - 1; i >= 0; i--) {
PayDetail payDetail = payDetails.get(i);
if (payDetail != null && payDetail.getTransactionType() == transactionType) {
return payDetail;
}
}
return null;
}
private void observeLastSettlement() {
HostType hostType = sharedViewModel.hostType.getValue();
if (hostType == HostType.QR) {
managementViewModel.getLastSettlementQR(SystemParamsOperation.getInstance().getCurrentSerialNum())
.observe(getViewLifecycleOwner(), payDetails -> handleLastSettlement(payDetails, HostType.QR));
} else {
managementViewModel.getLastSettlement(SystemParamsOperation.getInstance().getCurrentSerialNum())
.observe(getViewLifecycleOwner(), payDetails -> handleLastSettlement(payDetails, hostType));
}
}
private void handleLastSettlement(List<PayDetail> payDetails, HostType hostType) {
if (payDetails == null || payDetails.isEmpty()) {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
routeId = R.id.action_selectHostFragment_to_nav_main;
safeNavigateToRouteId();
return;
}
PayDetail payDetail;
if (hostType == HostType.QR) {
payDetail = findLastByType(payDetails, TransactionsType.MMQR_SETTLEMENT.value);
if (payDetail != null) {
managementViewModel.payDetails.setValue(java.util.Collections.singletonList(payDetail));
routeId = R.id.action_selectHostFragment_to_QRSettlementTransactionFragment;
} else {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
routeId = R.id.action_selectHostFragment_to_nav_main;
managementViewModel.getLastSettlement(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetails) {
if (payDetails != null) {
if (!payDetails.isEmpty()) {
routeId = R.id.action_selectHostFragment_to_settlementTransactionFragment;
} else {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
routeId = R.id.action_selectHostFragment_to_nav_main;
}
safeNavigateToRouteId();
} else {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
routeId = R.id.action_selectHostFragment_to_nav_main;
safeNavigateToRouteId();
}
}
} else {
payDetail = findLastByType(payDetails, TransactionsType.SETTLEMENT.value);
if (payDetail != null) {
routeId = R.id.action_selectHostFragment_to_settlementTransactionFragment;
} else {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
routeId = R.id.action_selectHostFragment_to_nav_main;
}
}
safeNavigateToRouteId();
});
}
private void observeRoute() {
switch (Objects.requireNonNull(sharedViewModel.getTransMenu().getValue())) {
case REVERSAL:
@ -334,14 +296,13 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
clearBatch();
break;
case LAST_SETTLEMENT:
observeLastSettlement();
// if(sharedViewModel.hostType.getValue() != HostType.QR) {
// observeLastSettlement();
// } else {
// showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
// routeId = R.id.action_selectHostFragment_to_nav_main;
// safeNavigateToRouteId();
// }
if(sharedViewModel.hostType.getValue() == HostType.MPU)
observeLastSettlement();
else {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
routeId = R.id.action_selectHostFragment_to_nav_main;
safeNavigateToRouteId();
}
break;
case CLEAR_REVERSAL:
clearReversal();
@ -375,11 +336,13 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
}
break;
case TIP_ADJUSTMENT:
if(sharedViewModel.hostType.getValue() != HostType.QR) {
if(sharedViewModel.hostType.getValue() == HostType.VISA_MASTER) {
routeId = R.id.action_selectHostFragment_to_inputTraceFragment;
} else {
routeId = R.id.action_selectHostFragment_to_errorFragment;
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_tip_adjust_not_allowed));
}
safeNavigateToRouteId();
break;
@ -430,9 +393,23 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
public class ClickEvent {
public void onClickCards() {
public void onClickVisaMaster() {
sharedViewModel.hostType.setValue(HostType.VISA_MASTER);
if(SystemParamsOperation.getInstance().isEmvEnabled()) {
observeRoute();
} else {
showSingleInfoDialog("Currently this menu is unavailable!");
}
}
public void onClickMPU() {
sharedViewModel.hostType.setValue(HostType.MPU);
observeRoute();
}
public void onClickQR() {

View File

@ -5,8 +5,6 @@ import android.app.TimePickerDialog;
import androidx.lifecycle.Observer;
import com.google.android.material.timepicker.MaterialTimePicker;
import com.google.android.material.timepicker.TimeFormat;
import com.nexgo.oaf.apiv3.SdkResult;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
@ -62,7 +60,6 @@ public class TransactionSummaryFragment extends DataBindingFragment {
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_transaction_summary_screen, BR.manageViewModel,managementViewModel)
.addBindingParam(BR.summaryViewModel,summaryViewModel)
.addBindingParam(BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.click,new ClickEvent());
}
@ -87,8 +84,6 @@ public class TransactionSummaryFragment extends DataBindingFragment {
setToolBarTitleWithBackIcon(getString(R.string.title_trans_summary));
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
summaryViewModel.resetField();
}
@ -158,19 +153,11 @@ public class TransactionSummaryFragment extends DataBindingFragment {
if (isStart) {
String selectedDate = dateFormat.format(myCalendar.getTime());
summaryViewModel.startDate.postValue(selectedDate);
// LogUtil.d(TAG, "Start date updated: " + selectedDate);
// STATIC START TIME
// summaryViewModel.startHr.setValue("00");
// summaryViewModel.startMin.setValue("00");
summaryViewModel.startDayOrNight.setValue(getString(R.string.txt_am));
LogUtil.d(TAG, "Start date updated: " + selectedDate);
} else {
String selectedDate = dateFormat.format(myCalendar2.getTime());
summaryViewModel.endDate.postValue(selectedDate);
// STATIC END TIME
// summaryViewModel.endHr.setValue("23");
// summaryViewModel.endMin.setValue("59");
summaryViewModel.endDayOrNight.setValue(getString(R.string.txt_pm));
// LogUtil.d(TAG, "End date updated: " + selectedDate);
LogUtil.d(TAG, "End date updated: " + selectedDate);
}
} catch (Exception e) {
LogUtil.e(TAG, "Error updating date label: " + e.getMessage());
@ -282,22 +269,44 @@ public class TransactionSummaryFragment extends DataBindingFragment {
waveRefund.inc(pay.amount);
}
} else if (sharedViewModel.hostType.getValue() == HostType.MPU) {
if (pay.getTransactionType() == TransactionsType.VOID.value) {
voidTran.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.SALE.value) {
sale.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.CASH_OUT.value) {
ca.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_SALE.value) {
preAuth.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_VOID.value) {
preAuthVoid.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_COMPLETE.value) {
preAuthComp.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_COMPLETE_VOID.value) {
preAuthCompVoid.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.REFUND.value) {
refund.inc(pay.amount);
if ("MPU".equals(pay.getAccountType())) {
if (pay.getTransactionType() == TransactionsType.VOID.value) {
voidTran.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.SALE.value) {
sale.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.CASH_OUT.value) {
ca.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_SALE.value) {
preAuth.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_VOID.value) {
preAuthVoid.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_COMPLETE.value) {
preAuthComp.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_COMPLETE_VOID.value) {
preAuthCompVoid.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.REFUND.value) {
refund.inc(pay.amount);
}
}
} else if (sharedViewModel.hostType.getValue() == HostType.VISA_MASTER) {
if (!"MPU".equals(pay.getAccountType())) {
if (pay.getTransactionType() == TransactionsType.VOID.value) {
voidTran.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.SALE.value) {
sale.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.CASH_OUT.value) {
ca.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_SALE.value) {
preAuth.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_VOID.value) {
preAuthVoid.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_COMPLETE.value) {
preAuthComp.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.PRE_AUTH_COMPLETE_VOID.value) {
preAuthCompVoid.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.REFUND.value) {
refund.inc(pay.amount);
}
}
}
}
@ -328,7 +337,9 @@ public class TransactionSummaryFragment extends DataBindingFragment {
if (sharedViewModel.hostType.getValue() == HostType.QR) {
return "WALLET";
} else if (sharedViewModel.hostType.getValue() == HostType.MPU) {
return "CARD";
return "MPU";
} else if (sharedViewModel.hostType.getValue() == HostType.VISA_MASTER) {
return "Visa/Master";
}
return "";
}
@ -366,7 +377,7 @@ public class TransactionSummaryFragment extends DataBindingFragment {
private void printReceipt(PayDetail payDetail) {
try {
LogUtil.d(TAG, "Starting receipt print");
PrintXReceipt.getInstance().printSmileSummaryReport(payDetail, sharedViewModel.hostType.getValue(), new PrintXStatus() {
PrintXReceipt.getInstance().printSmileSummaryReport(payDetail, new PrintXStatus() {
@Override
public void onSuccess() {
LogUtil.d(TAG, "Receipt printed successfully");
@ -452,104 +463,47 @@ public class TransactionSummaryFragment extends DataBindingFragment {
}
public void onClickStartHr() {
// showTimePicker(startTime, myCalendar);
showMaterialTimePicker(myCalendar, true);
showTimePicker(startTime, myCalendar);
}
public void onClickEndHr() {
// showTimePicker(endTime, myCalendar2);
showMaterialTimePicker(myCalendar2, false);
showTimePicker(endTime, myCalendar2);
}
public void onClickStartMin() {
// showTimePicker(startTime, myCalendar);
showMaterialTimePicker(myCalendar, true);
showTimePicker(startTime, myCalendar);
}
public void onClickEndMin() {
// showTimePicker(endTime, myCalendar2);
showMaterialTimePicker(myCalendar2, false);
showTimePicker(endTime, myCalendar2);
}
public void onClickStartDayOrNight() {
// showTimePicker(startTime, myCalendar);
showMaterialTimePicker(myCalendar, true);
showTimePicker(startTime, myCalendar);
}
public void onClickEndDayOrNight() {
// showTimePicker(endTime, myCalendar2);
showMaterialTimePicker(myCalendar2, false);
showTimePicker(endTime, myCalendar2);
}
private void showTimePicker(TimePickerDialog.OnTimeSetListener listener, Calendar calendar) {
try {
TimePickerDialog timePickerDialog =
new TimePickerDialog(
requireContext(),
listener,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
false);
TimePickerDialog timePickerDialog = new TimePickerDialog(requireContext(),
listener, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), false);
timePickerDialog.show();
} catch (Exception e) {
LogUtil.e(TAG, "Error showing time picker: " + e.getMessage());
}
}
private void showMaterialTimePicker(
Calendar calendar,
boolean isStart
) {
MaterialTimePicker timePicker = new MaterialTimePicker.Builder()
.setTimeFormat(TimeFormat.CLOCK_24H)
.setHour(calendar.get(Calendar.HOUR_OF_DAY))
.setMinute(calendar.get(Calendar.MINUTE))
.setInputMode(MaterialTimePicker.INPUT_MODE_KEYBOARD)
.setTitleText("Select Time")
.build();
timePicker.addOnPositiveButtonClickListener(v -> {
int hour = timePicker.getHour();
int minute = timePicker.getMinute();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
String amPm = hour >= 12
? getString(R.string.txt_pm)
: getString(R.string.txt_am);
if (isStart) {
summaryViewModel.startHr.setValue(String.format(Locale.getDefault(), "%02d", hour));
summaryViewModel.startMin.setValue(String.format(Locale.getDefault(), "%02d", minute));
summaryViewModel.startDayOrNight.setValue(amPm);
} else {
summaryViewModel.endHr.setValue(String.format(Locale.getDefault(), "%02d", hour));
summaryViewModel.endMin.setValue(String.format(Locale.getDefault(), "%02d", minute));
summaryViewModel.endDayOrNight.setValue(amPm);
}
LogUtil.d(TAG, (isStart ? "Start" : "End") +
" time selected: " + hour + ":" + minute);
});
timePicker.show(getParentFragmentManager(), "material_time_picker");
}
public void onPrint() {
try {
if (!SystemParamsOperation.getInstance().getPrinterEnabled()) {
showDeclineDialog("Printer is disabled!");
return;
}
if (summaryViewModel.validateField()) {
LogUtil.d(TAG, "Print button clicked - validation passed");
startSearchProcess();
} else {
LogUtil.w(TAG, "Print button clicked - validation failed");
showSingleInfoDialog("Please select date and time!");
showSingleInfoDialog("Please select date!");
}
} catch (Exception e) {
LogUtil.e(TAG, "Error in print action: " + e.getMessage());

View File

@ -104,7 +104,7 @@ public class ManualEntryFragment extends DataBindingFragment {
payDetail.setAccountType(manualEntryViewModel.get_cardScheme().getValue().name);
}
payDetail.setICC55("");
// payDetail.setAuthNo(manualEntryViewModel.cvv.getValue());
payDetail.setAuthNo(manualEntryViewModel.cvv.getValue());
emvTransactionProcessViewModel.setTradeData(tradeData);
@ -166,7 +166,7 @@ public class ManualEntryFragment extends DataBindingFragment {
public void onConfirm() {
if(manualEntryViewModel.validateData()) {
if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND || sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_SALE || sharedViewModel.transactionsType.getValue() == TransactionsType.SALE || sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_VOID || sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_COMPLETE) {
if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND || sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_SALE || sharedViewModel.transactionsType.getValue() == TransactionsType.SALE || sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_VOID) {
if(manualEntryViewModel.get_cardScheme().getValue() != null && manualEntryViewModel.get_cardScheme().getValue() == CardScheme.MPU) {
processMPUCard();

View File

@ -90,9 +90,6 @@ public class ManualEntryViewModel extends ViewModel {
return expDate;
}
private boolean validateCard() {
return (cardFieldState.getValue() == EntryState.UNSELECTED && expFieldState.getValue() == EntryState.UNSELECTED && expDate.getValue() != null && !expDate.getValue().isEmpty()) ;
}
private boolean validateDataMPU() {
return (cardFieldState.getValue() == EntryState.UNSELECTED && expFieldState.getValue() == EntryState.UNSELECTED && expDate.getValue() != null && !expDate.getValue().isEmpty()) ;
}
@ -109,9 +106,8 @@ public class ManualEntryViewModel extends ViewModel {
}
public boolean validateData() {
return validateCard();
// if(_cardScheme.getValue() == CardScheme.MPU) return validateDataMPU();
// else return validateDataEmv();
if(_cardScheme.getValue() == CardScheme.MPU) return validateDataMPU();
else return validateDataEmv();
}
public void resetUI() {
@ -310,23 +306,23 @@ public class ManualEntryViewModel extends ViewModel {
if (pan.startsWith("4"))
{
_cardScheme.setValue(CardScheme.VISA);
// cvvVisibility.setValue(0);
cvvVisibility.setValue(0);
}
else if (pan.startsWith("51") || pan.startsWith("52") || pan.startsWith("53") || pan.startsWith("54") || pan.startsWith("55")) {
_cardScheme.setValue(CardScheme.MASTERCARD);
// cvvVisibility.setValue(0);
cvvVisibility.setValue(0);
}
else if (pan.startsWith("3528")) {
if(pan.length() > 4 && (Integer.parseInt(pan.substring(0, 4)) >= 3528 && Integer.parseInt(pan.substring(0, 4)) <= 3589)) {
_cardScheme.setValue(CardScheme.JCB);
// cvvVisibility.setValue(0);
cvvVisibility.setValue(0);
}
}
else if (pan.startsWith("60") || pan.startsWith("62") || pan.startsWith("65") || pan.startsWith("81"))
{
_cardScheme.setValue(CardScheme.UPI);
// cvvVisibility.setValue(0);
cvvVisibility.setValue(0);
}
else
{

View File

@ -2,20 +2,8 @@ package com.utsmm.kbz.ui.navigation;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import com.nexgo.oaf.apiv3.APIProxy;
import com.nexgo.oaf.apiv3.DeviceEngine;
import com.nexgo.oaf.apiv3.DeviceInfo;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.printer.AlignEnum;
import com.nexgo.oaf.apiv3.device.printer.GrayLevelEnum;
import com.nexgo.oaf.apiv3.device.printer.LineOptionEntity;
import com.nexgo.oaf.apiv3.device.printer.Printer;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusHost;
import com.utsmyanmar.baselib.network.model.sirius.SiriusMerchant;
import com.utsmyanmar.baselib.network.model.sirius.SiriusResponse;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.sign_on.EchoTestProcess;
@ -25,8 +13,6 @@ import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import java.util.List;
public class NaviMainFragment extends DataBindingFragment {
private OnFragmentInteractionListener mListener;
@ -151,7 +137,6 @@ public class NaviMainFragment extends DataBindingFragment {
});
}
public void onClickLogOff() {
showLoadingDialog("Sending LogOff!");
@ -191,34 +176,6 @@ public class NaviMainFragment extends DataBindingFragment {
mListener.onClickFunction();
}
private GrayLevelEnum getGrayLevel() {
int gray = 2;
GrayLevelEnum grayLevelEnum = GrayLevelEnum.LEVEL_1;
switch (gray) {
case 0:
grayLevelEnum = GrayLevelEnum.LEVEL_0;
break;
case 1:
grayLevelEnum = GrayLevelEnum.LEVEL_1;
break;
case 2:
grayLevelEnum = GrayLevelEnum.LEVEL_2;
break;
case 3:
grayLevelEnum = GrayLevelEnum.LEVEL_3;
break;
case 4:
grayLevelEnum = GrayLevelEnum.LEVEL_4;
break;
default:
grayLevelEnum = GrayLevelEnum.LEVEL_1;
break;
}
return grayLevelEnum;
}
public void onClickVersion(){
mListener.onClickVersion();
}
@ -227,6 +184,7 @@ public class NaviMainFragment extends DataBindingFragment {
mListener.onClickExit();
}
}
public interface OnFragmentInteractionListener {
@ -237,6 +195,5 @@ public class NaviMainFragment extends DataBindingFragment {
void onClickVersion();
void onClickExit();
}
}

View File

@ -6,8 +6,6 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.nexgo.oaf.apiv3.DeviceEngine;
import com.nexgo.oaf.apiv3.DeviceInfo;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmm.kbz.BR;
@ -34,7 +32,6 @@ public class VersionFragment extends DataBindingFragment {
setToolBarTitleWithBackIcon(getString(R.string.title_version));
fetchVersions();
versionViewModel.loadDeviceInfo(requireContext());
}
@Override
@ -78,4 +75,5 @@ public class VersionFragment extends DataBindingFragment {
}

View File

@ -1,13 +1,13 @@
package com.utsmm.kbz.ui.navigation;
import android.content.Context;
import android.os.RemoteException;
import androidx.lifecycle.ViewModel;
import com.nexgo.oaf.apiv3.APIProxy;
import com.nexgo.oaf.apiv3.DeviceEngine;
import com.nexgo.oaf.apiv3.DeviceInfo;
import com.sunmi.pay.hardware.aidl.AidlConstants;
import com.utsmyanmar.paylibs.system.SingleLiveEvent;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.MyApplication;
public class VersionViewModel extends ViewModel {
@ -28,25 +28,31 @@ public class VersionViewModel extends ViewModel {
public VersionViewModel() {
// initData();
// loadDeviceInfo();
initData();
}
private void initData() {
String txtHardwareVersion = getParams(AidlConstants.SysParam.HARDWARE_VERSION);
hardwareVersion.setValue(txtHardwareVersion);
String txtFirmwareVersion = getParams(AidlConstants.SysParam.FIRMWARE_VERSION);
firmwareVersion.setValue(txtFirmwareVersion);
String txtSerialNo = getParams(AidlConstants.SysParam.SN);
serialNumber.setValue(txtSerialNo);
String txtDeviceModel = getParams(AidlConstants.SysParam.DEVICE_MODEL);
deviceModel.setValue(txtDeviceModel);
public void loadDeviceInfo(Context context){
try{
DeviceEngine deviceEngine = APIProxy.getDeviceEngine(context);
DeviceInfo deviceInfo = deviceEngine.getDeviceInfo();
serialNumber.setValue(deviceInfo.getSn());
deviceModel.setValue(deviceInfo.getModel());
hardwareVersion.setValue(deviceInfo.getKernelVer());
firmwareVersion.setValue(deviceInfo.getFirmWareVer());
swFinalVersion.setValue(deviceInfo.getFirmWareFullVersion());
payHardwareVersion.setValue(deviceInfo.getSpCoreVersion());
romVersion.setValue(deviceInfo.getOsVer());
} catch (Exception e) {
throw new RuntimeException(e);
swFinalVersion.setValue(SystemParamsOperation.getInstance().getFinalVersion());
}
private String getParams(String name) {
String value = "";
try {
value = MyApplication.getInstance().basicOptBinder.getSysParam(name);
} catch (RemoteException e) {
e.printStackTrace();
}
return value;
}

View File

@ -13,11 +13,11 @@ import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.pinpad.AlgorithmModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.OnPinPadInputListener;
import com.nexgo.oaf.apiv3.device.pinpad.PinAlgorithmModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.PinKeyboardModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.PinKeyboardViewModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.PinPad;
import com.nexgo.oaf.apiv3.device.pinpad.PinPadKeyCode;
import com.nexgo.oaf.apiv3.device.pinpad.PinpadLayoutEntity;
import com.sunmi.pay.hardware.aidlv2.pinpad.PinPadOptV2;
import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.ui.CustomPinPadKeyboard;
@ -37,6 +37,7 @@ public class PinPadViewModel extends ViewModel {
private static final String TAG = PinPadViewModel.class.getSimpleName();
private PinPadOptV2 mPinPadOptV2;
public SingleLiveEvent<String> pinText = new SingleLiveEvent<>();
public SingleLiveEvent<String> alertMsg = new SingleLiveEvent<>();
@ -118,12 +119,7 @@ public class PinPadViewModel extends ViewModel {
case ON_CONFIRM_CLICK:
LogUtil.d(TAG, "ON CLICK CONFIRM");
// increasedKSN();
if(transType.getValue() == TransactionsType.PRE_AUTH_COMPLETE || transType.getValue() == TransactionsType.PRE_AUTH_VOID || transType.getValue() == TransactionsType.REFUND ) {
pinStatus.postValue(PinPadStatus.ON_NEXT_SCREEN);
} else {
pinStatus.postValue(PinPadStatus.ON_CONFIRM);
}
pinStatus.postValue(PinPadStatus.ON_CONFIRM);
break;
case ON_CANCEL_CLICK:
LogUtil.d(TAG, "ON CLICK CANCEL");
@ -172,13 +168,13 @@ public class PinPadViewModel extends ViewModel {
}
// public void cancelPinPad() {
// try {
// mPinPadOptV2.cancelInputPin();
// } catch (RemoteException e) {
// throw new RuntimeException(e);
// }
// }
public void cancelPinPad() {
try {
mPinPadOptV2.cancelInputPin();
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
private void increasedKSN() {
pinPad.dukptKsnIncrease(pinIndex); //3
@ -321,8 +317,6 @@ public class PinPadViewModel extends ViewModel {
r.bottom = customPinPadKeyboard.getKey_ok().getHeight() + r.top;
pinpadLayout.setKeyConfirm(r);
pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED);
byte[] number = pinPad.setPinpadLayout(pinpadLayout);
if(number != null) {
@ -337,8 +331,6 @@ public class PinPadViewModel extends ViewModel {
byte[] panBytes = pan.substring(length - 13).getBytes(StandardCharsets.US_ASCII);
// byte[] panBytes = pan.substring(length - 13, length - 1).getBytes(StandardCharsets.US_ASCII);
pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT);
pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED);
// pinPad.setAlgorithmMode(AlgorithmModeEnum.DES);

View File

@ -8,9 +8,6 @@ import com.utsmyanmar.paylibs.model.PayDetail;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@HiltViewModel
public class PreAuthVoidViewModel extends ViewModel {
private Repository repository;

View File

@ -1,61 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.ItemQrHistoryBinding;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.ArrayList;
import java.util.List;
public class QRHistoryAdapter extends RecyclerView.Adapter<QRHistoryAdapter.ViewHolder> {
private List<PayDetail> items = new ArrayList<>();
public void setItems(List<PayDetail> data){
items = data;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemQrHistoryBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_qr_history,
parent,
false
);
return new ViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.bind(items.get(position));
}
@Override
public int getItemCount() {
return items.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private final ItemQrHistoryBinding binding;
public ViewHolder(@NonNull ItemQrHistoryBinding binding){
super(binding.getRoot());
this.binding = binding;
}
public void bind(PayDetail item){
binding.setPayDetail(item);
binding.executePendingBindings();
}
}
}

View File

@ -1,78 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
public class QRHistoryFragment extends DataBindingFragment {
private QRHistoryAdapter adapter;
private QRHistoryViewModel viewModel;
@Override
protected void initViewModel() {
viewModel = new ViewModelProvider(this).get(QRHistoryViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
DataBindingConfig bindingConfig = new DataBindingConfig(R.layout.fragment_qr_history, BR.viewModel, viewModel);
bindingConfig.addBindingParam(BR.adapter, adapter);
return bindingConfig;
}
@Override
protected int currentId() {
return 0;
}
@Override
protected int hostId() {
return 0;
}
@Override
protected int routeId() {
return 0;
}
@Override
public void onResume(){
super.onResume();
setToolBarTitleWithBackIcon("History");
observeData();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstance){
super.onViewCreated(view, savedInstance);
RecyclerView rvHistory = view.findViewById(R.id.qrRvHistory);
rvHistory.setLayoutManager(new LinearLayoutManager(getContext()));
adapter = new QRHistoryAdapter();
rvHistory.setAdapter(adapter);
observeData();
}
private void observeData(){
viewModel.getAllQrHistory().observe(getViewLifecycleOwner(), list -> {
adapter.setItems(list);
});
}
}

View File

@ -1,35 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@HiltViewModel
public class QRHistoryViewModel extends ViewModel {
private final Repository repository;
private final LiveData<List<PayDetail>> history;
private final LiveData<List<PayDetail>> refundList;
@Inject
public QRHistoryViewModel(Repository repository){
this.repository = repository;
this.history = repository.getAllQRHistory();
this.refundList = repository.getRefundableQRHistory();
}
public LiveData<List<PayDetail>> getAllQrHistory(){
return history;
}
public LiveData<List<PayDetail>> getRefundableQrHistory(){
return refundList;
}
}

View File

@ -1,407 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.MainViewModel;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.adapters.QRPayAdapter;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.management.ManagementViewModel;
import com.utsmm.kbz.ui.settlement.SettlementViewModel;
import com.utsmm.kbz.util.Connectivity;
import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
import com.utsmyanmar.paylibs.utils.enums.HostType;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class QRPayFragment extends DataBindingFragment {
private MainViewModel mainViewModel;
private SharedViewModel sharedViewModel;
private static final int hostId = Constants.NAV_HOST_ID;
private int routeId;
private static final int currentId = R.id.qrFragment;
private Observer<PayDetail> observeLastTrans;
private PayDetail lastPay;
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon("MMQR PAY");
}
@Override
protected void initViewModel() {
mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
// sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
boolean isQrRefundEnable = SystemParamsOperation.getInstance().getQrRefundEnable();
List<QRPayItem> features = new ArrayList<>();
features.add(new QRPayItem("Sale", R.drawable.ic_qr_pay, true));
if(isQrRefundEnable){
features.add(new QRPayItem("Refund", R.drawable.ic_refund, true));
}
features.add(new QRPayItem("History", R.drawable.ic_history, true));
// List<QRPayItem> features = List.of(
// new QRPayItem("Sale", R.drawable.ic_qr_pay, true),
// new QRPayItem("Refund", R.drawable.ic_refund, false),
// new QRPayItem("History", R.drawable.ic_history, true)
// );
QRPayAdapter adapter = new QRPayAdapter(features, position -> {
QRPayItem selectedBtn = features.get(position);
switch (selectedBtn.title){
case "Sale":
onClickQRPay();
break;
case "Refund":
onClickRefund();
break;
case "History":
onClickHistory();
break;
}
});
DataBindingConfig config = new DataBindingConfig(R.layout.fragment_qr_pay, BR.mainViewModel, mainViewModel);
config.addBindingParam(BR.sharedViewModel,sharedViewModel);
config.addBindingParam(BR.adapter, adapter);
return config;
}
@Override
protected int currentId() {
return currentId;
}
@Override
protected int hostId() {
return hostId;
}
@Override
protected int routeId() {
return routeId;
}
public void onClickQRPay() {
String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress();
if (mainViewModel.payDetailSingle.getValue() != null) {
mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue());
}
// else if (TMSUtil.getInstance().checkSecHostParams().isStatus() == ValidityStatus.FAILURE) {
// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkSecHostParams().getMessage());
// }
else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
}
// else if (!isValidDomain(mmqrIp)) {
// showDeclineDialog(getResourceString(R.string.txt_please_check_mmqr_ip));
// }
else {
CurrencyType currencyType = TMSUtil.getInstance().currencyTextToCurrencyType(SystemParamsOperation.getInstance().getSecHostCurrency());
sharedViewModel.set_currencyText(currencyType.name);
processBatch();
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR);
navigateToAmount();
}
}
private void onClickHistory(){
sharedViewModel.hostType.setValue(HostType.QR);
sharedViewModel.setTransactionsType(TransactionsType.MMQR_HISTORY);
routeId = R.id.action_qrFragment_to_qrHistory;
safeNavigateToRouteId();
}
private void onClickRefund(){
// sharedViewModel.setTransactionsType(TransactionsType.MMQR_REFUND);
routeId = R.id.action_qrFragment_to_qr_refund_list;
// routeId = R.id.action_qrFragment_to_inputPasswordFragment;
safeNavigateToRouteId();
}
private void navigateToAmount() {
routeId = R.id.action_qrFragment_to_inputAmountFragment;
safeNavigateToRouteId();
}
private void processBatch() {
calculateLastTransaction();
mainViewModel.observeSettlementPOS();
observeLastTrans = payDetail -> {
if(payDetail == null) {
return;
}
// SystemParamsOperation.getInstance().saveSerialNumber(payDetail.getVoucherNo());
// SystemParamsOperation.getInstance().saveInvoiceNumber(payDetail.getInvoiceNo());
if(lastPay != null) {
Date lastPayDate = POSUtil.getInstance().getDateByString(lastPay.getTransDate());
Date observePayDate = POSUtil.getInstance().getDateByString(payDetail.getTransDate());
if(lastPayDate.compareTo(observePayDate) < 0) {
payDetail = lastPay;
}
}
// LogUtil.d(TAG,"TransDetail :"+payDetail.getTransType() + "- Trans Time :"+payDetail.getTransDate());
if(payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value){
return;
}
/*
* saving for api post request, to send in next time.
* */
SystemParamsOperation.getInstance().setLastTransTime(String.valueOf(payDetail.getTransNum()));
SystemParamsOperation.getInstance().setLastTransName(payDetail.getTransType());
String lastTransDate = payDetail.getTransDate();
String lastTransTime = payDetail.getTransTime();
Date today = POSUtil.getInstance().getCurrentDate();
Date transDate;
Date current = new Date(System.currentTimeMillis());
String configTimer = SystemParamsOperation.getInstance().getClearBatchTime();
// LogUtil.d(TAG,"Config Time :" + configTimer);
String configTime = "23:00";
int configDay = 10;
String configRawDay = SystemParamsOperation.getInstance().getClearBatchDay();
if(configRawDay != null && !configRawDay.trim().isEmpty()) {
try {
configDay = Integer.parseInt(configRawDay);
} catch (Exception e) {
e.printStackTrace();
}
}
if(configTimer != null && !configTimer.trim().isEmpty() && checkValidTime(configTimer.trim())) {
configTime = configTimer.trim();
}
Date configDateTime = POSUtil.getInstance().getDateTime(configTime);
Date yesterdayConfigDateTime = POSUtil.getInstance().getYesterdayConfigDateTime(configTime);
transDate = POSUtil.getInstance().getDateByString(lastTransDate);
Date yesterdayDate = POSUtil.getInstance().getYesterdayDate();
if(today.compareTo(transDate) == 0) {
// LogUtil.d(TAG,"Last Trans is Today!");
// LogUtil.d(TAG,"date current :!"+current);
// LogUtil.d(TAG,"date config :!"+configDateTime);
// Today
if(current.compareTo(configDateTime) > 0) {
// clear batch and force update param
// LogUtil.d(TAG,"Last Trans is Today! Config time is passed!");
// if (!SystemParamsOperation.getInstance().isClearBatch()) {
if (checkSyncTrans() || !SystemParamsOperation.getInstance().isClearBatch() ) {
// LogUtil.d(TAG,"Clearing....");
if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
clearBatchAndDownload(configDay,payDetail);
}
}
} else {
// LogUtil.d(TAG,"Last Trans is Today! Config time is not passed yet.....");
SystemParamsOperation.getInstance().setClearBatch(false);
}
} else {
// LogUtil.d(TAG,"Last Trans is Before Today!");
Date yest;
if(configTime.equals("00:00")) {
yest = configDateTime;
} else {
yest = yesterdayConfigDateTime;
}
Date lastTransDateTime = POSUtil.getInstance().getDateByTransDateTime(lastTransDate,lastTransTime);
// LogUtil.d(TAG,"Compare Result : "+lastTransDateTime.compareTo(yest));
if(yest.compareTo(lastTransDateTime) < 0) {
// LogUtil.d(TAG,"Trans is yesterday, but after config time, no action!");
} else {
// LogUtil.d(TAG,"Trans is yesterday, before config time,");
// if(!checkSyncTrans()) {
// LogUtil.d(TAG,"Clearing....");
if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
clearBatchAndDownload(configDay,payDetail);
}
// }
}
}
};
if(mainViewModel.lastTrans.hasActiveObservers()) {
mainViewModel.lastTrans.removeObserver(observeLastTrans);
}
mainViewModel.lastTrans.observe(getViewLifecycleOwner(),observeLastTrans);
}
private void calculateLastTransaction() {
mainViewModel.allTrans.observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetails) {
if(payDetails == null || payDetails.isEmpty()) {
return;
}
PayDetail tempPay = payDetails.get(0);
for (int i = 0; i < payDetails.size() ; i++) {
Date tempDate = POSUtil.getInstance().getDateByString(tempPay.getTransDate());
Date indexDate = POSUtil.getInstance().getDateByString(payDetails.get(i).getTransDate());
if(tempDate.compareTo(indexDate) > 0) {
// if before
tempPay = payDetails.get(i);
}
}
lastPay = tempPay;
// LogUtil.d(TAG,"Transaction Name : "+tempPay.getTransType());
// LogUtil.d(TAG,"Transaction Type : "+tempPay.getTransactionType());
// LogUtil.d(TAG,"Transaction Amount : "+tempPay.getAmount());
// LogUtil.d(TAG,"Transaction Date/Time : "+tempPay.getTransDate()+"/"+tempPay.getTransTime());
// LogUtil.d(TAG,"RRN/Trace : "+tempPay.getReferNo()+"/"+tempPay.getVoucherNo());
// LogUtil.d(TAG,"Transaction is canceled : "+tempPay.isCanceled());
// LogUtil.d(TAG,"Transaction settlement config : "+tempPay.isSettlementEnabled());
// LogUtil.d(TAG,"----------------------------------------------------------");
}
});
}
private boolean checkSyncTrans() {
String transDateString = SystemParamsOperation.getInstance().getSyncTransDate();
Date today = POSUtil.getInstance().getCurrentDate();
if(transDateString == null || transDateString.isEmpty()) {
return true;
}
Date transDate = POSUtil.getInstance().getDateByString(transDateString);
return today.compareTo(transDate) == 0;
}
private void clearBatchAndDownload(int configDay,PayDetail payDetail) {
Date yesterday = POSUtil.getInstance().getYesterdayDate();
Date lastInputDay = POSUtil.getInstance().getLastInputDay(configDay);
mainViewModel.settlementPOS.observe(getViewLifecycleOwner(), list -> {
Date transDate;
if(list == null || list.size() == 0) {
return;
}
for (PayDetail pay:list) {
/*
* To Hold One day transaction!
* */
transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
if (pay.getTransactionType() == TransactionsType.SALE.value) {
if(lastInputDay.compareTo(transDate) > 0) {
mainViewModel.deletePayDetail(pay);
}
} else {
if(yesterday.compareTo(transDate) > 0 ) {
mainViewModel.deletePayDetail(pay);
}
}
}
});
mainViewModel.deleteTrans.observe(getViewLifecycleOwner(), lists -> {
Date transDate;
if(lists == null || lists.size() == 0) {
return;
}
for (PayDetail pay:lists) {
/*
* To Hold One day transaction!
* */
transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
// LogUtil.d(TAG,"Trans Type : "+pay.getTransType()+"<=====> Trans Date :"+pay.getTransDate());
// LogUtil.d(TAG,"Yesterday Date: "+yesterday.toString());
// LogUtil.d(TAG,"Compare result :"+yesterday.compareTo(transDate));
if(yesterday.compareTo(transDate) > 0) {
mainViewModel.deletePayDetail(pay);
}
}
});
mainViewModel.preAuthTrans.observe(getViewLifecycleOwner(), lists -> {
Date transDate;
if(lists == null || lists.size() == 0) {
return;
}
for (PayDetail pay:lists) {
transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
if (lastInputDay.compareTo(transDate) > 0) {
mainViewModel.deletePayDetail(pay);
}
}
});
/*
*
* Need to think about his problem .... Nov 7, 2024
* */
if(!SystemParamsOperation.getInstance().isClearBatch()) {
// downloadParams(payDetail.getTransType(),String.valueOf(payDetail.getTransNum()),TMSUpdate.UPDATE,false);
}
}
}

View File

@ -1,14 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
public class QRPayItem {
public String title;
public int icon;
public boolean isActive;
public QRPayItem(String title, int icon, boolean isActive) {
this.title = title;
this.icon = icon;
this.isActive = isActive;
}
}

View File

@ -1,51 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@HiltViewModel
public class QRPayViewModel extends ViewModel {
private final Repository repository;
private final LiveData<List<PayDetail>> refundableHistory;
private final RefundCertificateManager refundCertificateManager;
private final MutableLiveData<PayDetail> _payDetail = new MutableLiveData<>();
public LiveData<PayDetail> payDetail = _payDetail;
@Inject
public QRPayViewModel(
Repository repository,
RefundCertificateManager refundCertificateManager
){
this.repository = repository;
this.refundableHistory = repository.getRefundableQRHistory();
this.refundCertificateManager = refundCertificateManager;
}
public LiveData<List<PayDetail>> getRefundableQrHistory(){
return refundableHistory;
}
public void setPayDetail(PayDetail payDetail){
_payDetail.setValue(payDetail);
}
public void checkCertificateFiles(){
refundCertificateManager.updateCertificateFiles();
}
public Runnable onCancel;
public Runnable onConfirm;
}

View File

@ -1,49 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
public class QRRefund {
private String referenceNo;
private String refundAmount;
private String originalAmount;
private String reason;
public QRRefund(String referenceNo, String refundAmount, String originalAmount, String reason) {
this.referenceNo = referenceNo;
this.refundAmount = refundAmount;
this.originalAmount = originalAmount;
this.reason = reason;
}
public String getReferenceNo() {
return referenceNo;
}
public void setReferenceNo(String referenceNo) {
this.referenceNo = referenceNo;
}
public String getRefundAmount() {
return refundAmount;
}
public void setRefundAmount(String refundAmount) {
this.refundAmount = refundAmount;
}
public String getOriginalAmount() {
return originalAmount;
}
public void setOriginalAmount(String originalAmount) {
this.originalAmount = originalAmount;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}

View File

@ -1,235 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.os.Bundle;
import android.text.InputFilter;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmm.kbz.ui.kpay.KPayViewModel;
import com.utsmm.kbz.util.helper.KeyboardHelper;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.DecimalDigitsInputFilter;
import com.utsmm.kbz.util.TransactionUtil;
import java.text.DecimalFormat;
public class QRRefundDetailFragment extends DataBindingFragment {
private SharedViewModel sharedViewModel;
private KPayViewModel kPayViewModel;
private int routeId;
private TradeData tradeData;
private PayDetail payDetail;
// UI Elements
private RadioGroup radioGroupRefundType;
private RadioButton radioOriginal, radioPartial;
private EditText etReferenceNo, etOriginalAmount, etRefundAmount, etRefundReason;
private LinearLayout originalAmountLayout, refundAmountLayout;
private String originalRefundAmount;
private boolean isPartialRefund = false;
private static final String TAG = com.utsmm.kbz.ui.kpay.QRRefundFragment.class.getSimpleName();
private static final int hostId = Constants.NAV_HOST_ID;
private static final int currentId = R.id.qrRefundDetail;
@Override
protected void initViewModel() {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
kPayViewModel = getFragmentScopeViewModel(KPayViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_qr_refund_detail, BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.kPayViewModel, kPayViewModel)
.addBindingParam(BR.click, new ClickEvent());
}
@Override
protected int currentId() {
return currentId;
}
@Override
protected int hostId() {
return hostId;
}
@Override
protected int routeId() {
return routeId;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if(getArguments() != null){
payDetail = (PayDetail) getArguments().getSerializable("payDetail");
}
}
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon("QR Refund");
kPayViewModel.invalidAmountMsg.setValue("");
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initViews();
initData();
setupRadioGroupListener();
}
private void initViews() {
radioGroupRefundType = mBinding.getRoot().findViewById(R.id.radio_group_refund_type);
radioOriginal = mBinding.getRoot().findViewById(R.id.radio_original);
radioPartial = mBinding.getRoot().findViewById(R.id.radio_partial);
etReferenceNo = mBinding.getRoot().findViewById(R.id.et_reference_no);
etOriginalAmount = mBinding.getRoot().findViewById(R.id.et_original_amount);
etRefundAmount = mBinding.getRoot().findViewById(R.id.et_refund_amount);
etRefundReason = mBinding.getRoot().findViewById(R.id.et_refund_reason);
originalAmountLayout = mBinding.getRoot().findViewById(R.id.original_amount_layout);
refundAmountLayout = mBinding.getRoot().findViewById(R.id.refund_amount_layout);
// Set input filters for amount fields
etOriginalAmount.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(11, 2)});
etRefundAmount.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(11, 2)});
}
private void initData() {
double realAmount = payDetail.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
originalRefundAmount = df.format(realAmount);
payDetail = TransactionUtil.getInstance().initWalletTransaction(TransactionsType.MMQR_REFUND);
payDetail.setInvoiceNo(SystemParamsOperation.getInstance().getIncrementInvoiceNum());
if(getArguments() != null){
PayDetail passData = (PayDetail) getArguments().getSerializable("payDetail");
if(passData != null && passData.getReferNo() != null){
etReferenceNo.setText(passData.getReferNo());
etReferenceNo.setEnabled(false);
}
}
}
private void setupRadioGroupListener() {
radioGroupRefundType.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.radio_partial) {
// Show both amount fields for partial refund
isPartialRefund = true;
originalAmountLayout.setVisibility(View.VISIBLE);
refundAmountLayout.setVisibility(View.VISIBLE);
} else {
// Hide amount fields for original refund
isPartialRefund = false;
originalAmountLayout.setVisibility(View.GONE);
refundAmountLayout.setVisibility(View.GONE);
}
});
}
public class ClickEvent {
public void onCancel() {
safePopBackStack();
}
public void onConfirm() {
kPayViewModel.invalidAmountMsg.setValue("");
String referenceNo = etReferenceNo.getText().toString().trim();
String refundReason = etRefundReason.getText().toString().trim();
// Validate reference number
if (referenceNo.isEmpty()) {
kPayViewModel.invalidAmountMsg.setValue("Enter reference number");
return;
}
if (isPartialRefund) {
// Partial refund validation
String originalAmountStr = etOriginalAmount.getText().toString().trim();
String refundAmountStr = etRefundAmount.getText().toString().trim();
if (originalAmountStr.isEmpty()) {
kPayViewModel.invalidAmountMsg.setValue("Enter original amount");
return;
}
if (refundAmountStr.isEmpty()) {
kPayViewModel.invalidAmountMsg.setValue("Enter refund amount");
return;
}
double originalAmount = Double.parseDouble(originalAmountStr);
double refundAmount = Double.parseDouble(refundAmountStr);
if (originalAmount <= 0) {
kPayViewModel.invalidAmountMsg.setValue("Enter valid original amount");
return;
}
if (refundAmount <= 0) {
kPayViewModel.invalidAmountMsg.setValue("Enter valid refund amount");
return;
}
if (refundAmount > originalAmount) {
kPayViewModel.invalidAmountMsg.setValue("Refund amount cannot exceed original amount");
return;
}
QRRefund qrRefund = new QRRefund(referenceNo, refundAmountStr, originalAmountStr, refundReason);
kPayViewModel.setQrRefund(qrRefund);
} else {
// String originalAmountStr = etOriginalAmount.getText().toString().trim();
// String refundAmountStr = etRefundAmount.getText().toString().trim();
QRRefund qrRefund = new QRRefund(referenceNo, "0", originalRefundAmount, refundReason);
kPayViewModel.setQrRefund(qrRefund);
}
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR_REFUND);
kPayViewModel.setPayDetail(payDetail);
// sharedViewModel.amount.setValue(refundAmountStr);
KeyboardHelper.hide(requireActivity());
routeId = R.id.action_qrRefundDetail_inputPasswordFragment;
safeNavigateToRouteId();
}
}
}

View File

@ -1,147 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.kpay.KPayViewModel;
import com.utsmm.kbz.util.helper.KeyboardHelper;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.ArrayList;
import java.util.List;
public class QRRefundFragment extends DataBindingFragment {
private static final int hostId = Constants.NAV_HOST_ID;
private int routeId;
private static final int currentId = R.id.qrRefundList;
private QRPayViewModel qrPayViewModel;
private SharedViewModel sharedViewModel;
private QRRefundViewAdapter adapter;
private LinearLayout emptyStateView;
@Override
protected int currentId() {
return currentId;
}
@Override
protected int hostId() {return hostId;}
@Override
protected int routeId() {return routeId;}
@Override
protected void initViewModel() {
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
qrPayViewModel = new ViewModelProvider(requireActivity()).get(QRPayViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
adapter = new QRRefundViewAdapter(this::onRefundItemClicked);
return new DataBindingConfig(R.layout.fragment_qr_refund, BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.adapter, adapter)
.addBindingParam(BR.click, new ClickEvent());
}
@Override
public void onResume(){
super.onResume();
setToolBarTitleWithBackIcon("QR Refund");
}
@Override
public void onCreate(@Nullable Bundle savedInstance){
super.onCreate(savedInstance);
adapter = new QRRefundViewAdapter(this::onRefundItemClicked);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = view.findViewById(R.id.qrRefundHistory);
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
recyclerView.setAdapter(adapter);
emptyStateView = view.findViewById(R.id.emptyStateSectionRefund);
qrPayViewModel.checkCertificateFiles();
observeData();
}
private void observeData(){
qrPayViewModel.getRefundableQrHistory().observe(getViewLifecycleOwner(), this::updateList);
}
private void updateList(List<PayDetail> list){
if (adapter == null) {
return;
}
if(list == null || list.isEmpty()){
emptyStateView.setVisibility(View.VISIBLE);
getView().findViewById(R.id.qrRefundHistory).setVisibility(View.GONE);
}else{
emptyStateView.setVisibility(View.GONE);
getView().findViewById(R.id.qrRefundHistory).setVisibility(View.VISIBLE);
adapter.setData(list);
}
}
public class ClickEvent {
public void onCancel(){
safeNavigateToRouteId();
}
public void onSearch(){
searchByTrace();
KeyboardHelper.hide(requireActivity());
}
}
private void onRefundItemClicked(PayDetail payDetail) {
Bundle bundle = new Bundle();
bundle.putSerializable("payDetail", payDetail);
routeId = R.id.action_qrRefundList_to_qrRefundDetail;
NavHostFragment.findNavController(this).navigate(routeId, bundle);
}
private void searchByTrace(){
EditText editText = getView().findViewById(R.id.rnn_trace_id);
String keyword = editText.getText().toString().trim();
if(keyword.isEmpty()){
updateList(qrPayViewModel.getRefundableQrHistory().getValue());
return;
}
List<PayDetail> originalList = qrPayViewModel.getRefundableQrHistory().getValue();
if(originalList == null) return;
List<PayDetail> filteredList = new ArrayList<>();
for(PayDetail item: originalList){
boolean match = item.getVoucherNo() != null && item.getVoucherNo().contains(keyword);
if(match){
filteredList.add(item);
}
}
updateList(filteredList);
}
}

View File

@ -1,257 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.kpay.KPayViewModel;
import com.utsmm.kbz.ui.kpay.QRRefundFragment;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmm.kbz.util.TransactionUtil;
import com.utsmm.kbz.util.ecr.CoreUtils;
import com.utsmm.kbz.util.enums.TransResultStatus;
import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.KPayRefund;
//import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptQRRequest;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.POSUtil;
import java.text.DecimalFormat;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class QRRefundProcessFragment extends DataBindingFragment {
private static final String TAG = QRRefundProcessFragment.class.getSimpleName();
private SharedViewModel sharedViewModel;
private KPayViewModel kPayViewModel;
private PayDetail payDetail;
private QRRefund qrRefund;
private static final int hostId = Constants.NAV_HOST_ID;
private int routeId;
private static final int currentId = R.id.QRRefundProcessFragment;
CompositeDisposable retrieveUpdateDisposable = new CompositeDisposable();
CompositeDisposable refundDisposable = new CompositeDisposable();
@Override
protected void initViewModel() {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
kPayViewModel = getFragmentScopeViewModel(KPayViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_qr_refund_process, BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.kPayViewModel, kPayViewModel);
}
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithoutBackIcon("QR Refund Process");
}
@Override
public void onDestroyView() {
super.onDestroyView();
retrieveUpdateDisposable.dispose();
refundDisposable.dispose();
}
@Override
protected int currentId() {
return currentId;
}
@Override
protected int hostId() {
return hostId;
}
@Override
protected int routeId() {
return routeId;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initData();
processKPayRefund(qrRefund.getReferenceNo(), qrRefund.getRefundAmount(), qrRefund.getOriginalAmount(), qrRefund.getReason());
}
private void initData() {
payDetail = kPayViewModel.getPayDetail();
qrRefund = kPayViewModel.getQrRefund();
}
private void processKPayRefund(String referenceNo, String refundAmount, String originalAmount, String reason) {
String merchantId = TransactionUtil.getInstance().getQRMerchantId();
// Generate unique refund request ID
String refundRequestId = referenceNo + "R";
// Create KPay refund request
KPayRefund.RefundRequest refundRequest = kPayViewModel.createRefundRequest(
refundRequestId,
referenceNo,
merchantId,
refundAmount,
reason != null ? reason : "Refund request"
);
Disposable refundDi = kPayViewModel.kPayRefund(refundRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> {
handleRefundResponse(response, referenceNo, originalAmount);
},
throwable -> {
LogUtil.e(TAG, "Refund error: " + throwable.getMessage());
showDeclineDialog("Refund failed!\nCommunication Error!");
ecrActionCancel("Refund failed");
navigateToMain();
},
() -> LogUtil.d(TAG, "Refund request completed")
);
refundDisposable.add(refundDi);
}
private void handleRefundResponse(KPayRefund.RefundResponse response, String referenceNo, String orgAmount) {
if (response != null && response.getResponse() != null && "REFUND_SUCCESS".equalsIgnoreCase(response.getResponse().getRefundStatus())) {
LogUtil.d(TAG, "Refund successful!");
String refundAmount = response.getResponse().getRefundAmount();
long text = POSUtil.getInstance().convertAmount(refundAmount);
String dateTime = SystemDateTime.getTodayDateFormat() + " " + SystemDateTime.getTodayTimeFormat();
payDetail.setTC(response.getResponse().getRefundStatus());
payDetail.setAmount(refundAmount == null ? 0 : POSUtil.getInstance().convertAmount(refundAmount));
payDetail.setOriginalTransDate(dateTime);
payDetail.setQrTransStatus(1);
if(response.getResponse().getMmqrRef() != null) {
payDetail.setQrReferNo(response.getResponse().getMmqrRef());
}
payDetail.setReferNo(referenceNo);
payDetail.setIsCanceled(true);
payDetail.setCustomerMobile(response.getResponse().getWalletIdentifier());
payDetail.setTradeDateAndTime(response.getResponse().getRefundTime());
EReceiptRequest request = EReceiptUtil.getInstance().generateQRRefundReceipt(
refundAmount,
referenceNo,
payDetail != null ? payDetail.getInvoiceNo() : "",
payDetail != null ? payDetail.getVoucherNo() : "",
payDetail != null ? payDetail.getQrReferNo() != null ? payDetail.getQrReferNo() : "" : "" ,
payDetail != null ? payDetail.getCustomerMobile() : "",
TransResultStatus.SUCCESS
);
sharedViewModel.pushReceipt(request);
sharedViewModel.amount.setValue(refundAmount);
retrievedUpdatePayDetail(referenceNo);
} else {
LogUtil.d(TAG, "Refund failed!");
payDetail.setQrTransStatus(-1);
payDetail.setReferNo(referenceNo);
String errorMsg = "Refund failed";
if (response != null && response.getResponse() != null && response.getResponse().getMsg() != null) {
errorMsg = response.getResponse().getMsg();
}
payDetail.setTradeResultDes(errorMsg);
EReceiptRequest request = EReceiptUtil.getInstance().generateQRRefundReceipt(
"0",
referenceNo,
payDetail != null ? payDetail.getInvoiceNo() : "",
payDetail != null ? payDetail.getVoucherNo() : "",
payDetail != null ? payDetail.getQrReferNo() != null ? payDetail.getQrReferNo() : "" : "" ,
payDetail != null ? payDetail.getCustomerMobile() : "",
TransResultStatus.FAIL
);
sharedViewModel.pushReceipt(request);
sharedViewModel.amount.setValue(orgAmount);
sharedViewModel.payDetail.setValue(payDetail);
navigateToNext();
}
}
private void retrievedUpdatePayDetail(String refNum) {
LogUtil.d(TAG, "Trying to update Database!");
retrieveUpdateDisposable.add(kPayViewModel.searchPayByRefNum(refNum)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(oldPay -> {
LogUtil.d(TAG, "Inside the subscribe!");
if (oldPay != null) {
oldPay.setIsCanceled(true);
payDetail.setQrTransId(oldPay.getQrTransId());
payDetail.setCustomerMobile(oldPay.getCustomerMobile());
sharedViewModel.updatePayDetail(oldPay);
}
updateData();
navigateToNext();
},
onError -> {
LogUtil.d(TAG, "On error Unable to retrieve PayDetail");
updateData();
navigateToNext();
},
() -> {
LogUtil.d(TAG, "No data found! navigating to Result Page!");
updateData();
navigateToNext();
}
));
}
private void updateData() {
kPayViewModel.insertPayDetail(payDetail);
sharedViewModel.payDetail.postValue(payDetail);
}
private void navigateToNext() {
routeId = R.id.action_QRRefundProcessFragment_to_transactionResultFragment;
safeNavigateToRouteId();
}
private void navigateToMain() {
routeId = R.id.action_QRRefundProcessFragment_to_nav_main;
safeNavigateToRouteId();
}
private void ecrActionCancel(String msg) {
if (sharedViewModel.isEcr.getValue() != null) {
if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.isEcrFinished.postValue(true);
}
}
}
}

View File

@ -1,84 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.ItemQrRefundBinding;
import com.utsmm.kbz.ui.adapters.QRPayAdapter;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.ArrayList;
import java.util.List;
public class QRRefundViewAdapter extends RecyclerView.Adapter<QRRefundViewAdapter.ViewHolder> {
private List<PayDetail> payDetailList = new ArrayList<>();
private final OnRefundItemClick listener;
public interface OnRefundItemClick {
void onClick(PayDetail payDetail);
}
public QRRefundViewAdapter(OnRefundItemClick listener){
this.listener = listener;
}
// public QRRefundViewAdapter(List<PayDetail> payDetailList, OnRefundItemClick listener){
// this.payDetailList = payDetailList;
// this.listener = listener;
// }
public void setData(List<PayDetail> data){
this.payDetailList = data != null ? data : new ArrayList<>();
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemQrRefundBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_qr_refund,
parent,
false
);
return new ViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
PayDetail payDetail = payDetailList.get(position);
holder.bind(payDetail, listener);
}
@Override
public int getItemCount() {
return payDetailList == null ? 0 : payDetailList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private final ItemQrRefundBinding binding;
public ViewHolder(ItemQrRefundBinding binding){
super(binding.getRoot());
this.binding = binding;
}
public void bind(PayDetail payDetail, OnRefundItemClick listener){
binding.setVariable(BR.payDetail, payDetail);
binding.executePendingBindings();
binding.getRoot().setOnClickListener( v -> {
if(listener != null) listener.onClick(payDetail);
});
}
}
}

View File

@ -1,107 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import com.utsmm.kbz.util.DownloadUtil;
import com.utsmyanmar.baselib.util.EReceiptHelper;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class RefundCertificateManager {
private static final String TAG = RefundCertificateManager.class.getSimpleName();
private static final String E_RECEIPT_SECRET =
com.utsmyanmar.baselib.BuildConfig.ERECEIPT_SECRET;
// Prevent duplicate parallel downloads
private final AtomicBoolean isUpdating = new AtomicBoolean(false);
@Inject
public RefundCertificateManager() {
}
/**
* Download & refresh refund certificates.
* Safe to call multiple times.
*/
public void updateCertificateFiles() {
if (!isUpdating.compareAndSet(false, true)) {
LogUtil.d(TAG, "Certificate update already in progress");
return;
}
try {
String tmsAddress = SystemParamsOperation.getInstance().getTmsAddress();
if (tmsAddress == null || tmsAddress.trim().isEmpty()) {
LogUtil.e(TAG, "TMS address is empty");
return;
};
// String downloadBase = tmsAddress.trim() + "/api/v1/file/download?filePath="; //local
String downloadBase = tmsAddress.trim() + "/file/download?filePath="; // uat and prod
String certUrl = SystemParamsOperation.getInstance().getCertificateUrl();
String clientCertUrl = SystemParamsOperation.getInstance().getCertificateClientUrl();
if (certUrl == null || clientCertUrl == null) {
LogUtil.e(TAG, "Certificate URLs are missing");
return;
}
String timestamp = String.valueOf(System.currentTimeMillis());
String signature = generateSignature(timestamp);
// LogUtil.d(TAG, "Download base => " + downloadBase);
// LogUtil.d(TAG, "Cert URL => " + certUrl);
// LogUtil.d(TAG, "Client Cert URL => " + clientCertUrl);
// ---------- CA CERT ----------
DownloadUtil.downloadCertificateRx(
downloadBase + certUrl,
"refund_ca_" + "file", // IMPORTANT: unique filename
timestamp,
signature,
path -> {
if (path != null) {
SystemParamsOperation.getInstance()
.setCertFilePath(path);
LogUtil.d(TAG, "CA cert saved => " + path);
} else {
LogUtil.e(TAG, "Failed to download CA cert");
}
}
);
// ---------- CLIENT CERT ----------
DownloadUtil.downloadCertificateRx(
downloadBase + clientCertUrl,
"refund_client_" + "file", // IMPORTANT: unique filename
timestamp,
signature,
path -> {
if (path != null) {
SystemParamsOperation.getInstance()
.setCertClientFilePath(path);
LogUtil.d(TAG, "Client cert saved => " + path);
} else {
LogUtil.e(TAG, "Failed to download client cert");
}
}
);
} finally {
isUpdating.set(false);
}
}
private static String generateSignature(String timestamp) {
String bodyString = "{}";
String dataToHash = bodyString + E_RECEIPT_SECRET + timestamp;
return EReceiptHelper.sha256(dataToHash);
}
}

View File

@ -2,6 +2,8 @@ package com.utsmm.kbz.ui.settings;
import android.os.RemoteException;
import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.sunmi.pay.hardware.aidlv2.security.SecurityOptV2;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmm.kbz.BR;
@ -17,7 +19,7 @@ public class DeleteKeyFragment extends DataBindingFragment {
private InputKeyViewModel inputKeyViewModel;
// private final SecurityOptV2 securityOptV2 = MyApplication.getInstance().mSecurityOptV2;
private final SecurityOptV2 securityOptV2 = MyApplication.getInstance().mSecurityOptV2;
@Override
protected void initViewModel() {
@ -63,9 +65,9 @@ public class DeleteKeyFragment extends DataBindingFragment {
int keyIndex = Integer.parseInt(inputKeyViewModel.keyIndex.getValue());
// int result = securityOptV2.deleteKey(AidlConstantsV2.Security.SEC_MKSK,keyIndex);
try {
int result = securityOptV2.deleteKey(AidlConstantsV2.Security.SEC_MKSK,keyIndex);
int result = -1;
LogUtil.d(TAG,"Delete Key result :"+ result);
if( result == 0) {
showSuccessDialog(keyIndex + " was deleted successfully!");
@ -75,6 +77,9 @@ public class DeleteKeyFragment extends DataBindingFragment {
showDeclineDialog(keyIndex + " delete process failure \nError Code : "+result);
inputKeyViewModel.keyIndex.setValue("");
}
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
public void onCancel() {

View File

@ -1,87 +0,0 @@
package com.utsmm.kbz.ui.settings;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import android.view.View;
import com.nexgo.oaf.apiv3.device.printer.Printer;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.databinding.FragmentHostConfigBinding;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
public class HostConfigFragment extends DataBindingFragment {
private HostConfigViewModel viewModel;
private SharedViewModel sharedViewModel;
protected Printer printer;
int FONT_NORMAL = 20;
int FONT_HEADER = 24;
@Override
protected void initViewModel() {
viewModel = new ViewModelProvider(this).get(HostConfigViewModel.class);
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_host_config, BR.viewModel, viewModel)
.addBindingParam(BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.click, new ClickHandler());
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
FragmentHostConfigBinding binding = (FragmentHostConfigBinding) this.binding;
viewModel.loadConfig();
}
@Override
public void onResume(){
super.onResume();
setToolBarTitleWithBackIcon("Host Configs");
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
}
@Override
protected int currentId() {
return R.id.hostConfigFragment;
}
@Override
protected int hostId() {
return Constants.NAV_HOST_ID;
}
@Override
protected int routeId() {
return 0;
}
public class ClickHandler {
public void onCancel(){
safePopBack(R.id.hostConfigFragment, Constants.NAV_HOST_ID);
}
public void onPrint(){
if (!SystemParamsOperation.getInstance().getPrinterEnabled()) {
showDeclineDialog("Printer is disabled!");
return;
}
sharedViewModel.printTerminalHostConfigs();
}
}
}

View File

@ -1,33 +0,0 @@
package com.utsmm.kbz.ui.settings;
public class HostConfigItem {
public String name;
public String ip;
public String mid;
public String tid;
public String secHostName;
public String secHostIp;
public String secHostMid;
public String secHostTid;
public HostConfigItem(
String name,
String ip,
String mid,
String tid,
String secHostName,
String secHostIp,
String secHostMid,
String secHostTid
){
this.name = name;
this.ip = ip;
this.mid = mid;
this.tid = tid;
this.secHostName = secHostName;
this.secHostIp = secHostIp;
this.secHostMid = secHostMid;
this.secHostTid = secHostTid;
}
}

View File

@ -1,150 +0,0 @@
package com.utsmm.kbz.ui.settings;
import static com.utsmyanmar.paylibs.print.printx.BaseXPrint.wrapAddressText;
import android.text.TextUtils;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.utsmm.kbz.BuildConfig;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import java.util.ArrayList;
import java.util.List;
public class HostConfigViewModel extends ViewModel {
public String appVersion = BuildConfig.VERSION_NAME;
public MutableLiveData<String> merchantName = new MutableLiveData<>();
public MutableLiveData<String> merchantPhone = new MutableLiveData<>();
public MutableLiveData<String> merchantAddress1 = new MutableLiveData<>();
public MutableLiveData<String> merchantAddress2 = new MutableLiveData<>();
// Primary Host
public MutableLiveData<String> hostName = new MutableLiveData<>();
public MutableLiveData<String> tid = new MutableLiveData<>();
public MutableLiveData<String> mid = new MutableLiveData<>();
public MutableLiveData<String> primaryIp = new MutableLiveData<>();
public MutableLiveData<String> primaryPort = new MutableLiveData<>();
public MutableLiveData<String> secondaryIp = new MutableLiveData<>();
public MutableLiveData<String> secondaryPort = new MutableLiveData<>();
public MutableLiveData<String> currencyCode = new MutableLiveData<>();
// Secondary Host
public MutableLiveData<String> secHostName = new MutableLiveData<>();
// public MutableLiveData<String> secHostTid = new MutableLiveData<>();
// public MutableLiveData<String> secHostMid = new MutableLiveData<>();
public MutableLiveData<String> shortCode = new MutableLiveData<>();
public MutableLiveData<String> secHostPrimaryIp = new MutableLiveData<>();
public MutableLiveData<String> secHostPrimaryPort = new MutableLiveData<>();
public MutableLiveData<String> secHostSecondaryIp = new MutableLiveData<>();
public MutableLiveData<String> secHostSecondaryPort = new MutableLiveData<>();
public MutableLiveData<String> terminalName = new MutableLiveData<>();
public void loadConfig() {
SystemParamsOperation sp = SystemParamsOperation.getInstance();
// Merchant Info
merchantName.setValue(sp.getMerchantName());
merchantPhone.setValue(sp.getMerchantPhoneNo());
merchantAddress1.setValue(wrapMerchantAddress(sp.getMerchantAddress()));
terminalName.setValue(sp.getTerminalName());
// PRIMARY HOST
hostName.setValue(sp.getHostName());
tid.setValue(sp.getTerminalId());
mid.setValue(sp.getMerchantId());
String[] pri = split(sp.getIpAddress());
primaryIp.setValue(pri[0]);
primaryPort.setValue(pri[1]);
String[] sec = split(sp.getSecIpAddress());
secondaryIp.setValue(sec[0]);
secondaryPort.setValue(sec[1]);
currencyCode.setValue(sp.getCurrencyType() != null ? sp.getCurrencyType().toString() : "");
if (sp.getSecHostName() != null && !sp.getSecHostName().isEmpty()) {
secHostName.setValue(sp.getSecHostName());
// secHostTid.setValue(sp.getSecHostTerminalId());
// secHostMid.setValue(sp.getSecHostMerchantId());
shortCode.setValue(sp.getShortCode());
String[] shp = split(sp.getSecHostIpAddress());
secHostPrimaryIp.setValue(shp[0]);
secHostPrimaryPort.setValue(shp[1]);
String[] shs = split(sp.getSecHostSecIpAddress());
secHostSecondaryIp.setValue(shs[0]);
secHostSecondaryPort.setValue(shs[1]);
}
}
private String wrapMerchantAddress(String address) {
if (TextUtils.isEmpty(address)) return "";
String addr = address
.replace("\\r\\n", "\n")
.replace("\\n", "\n")
.replace("\r\n", "\n")
.trim();
//
List<String> lines = wrapAddressText(addr, 29);
//
return TextUtils.join("\n", lines);
}
private String[] split(String raw) {
if (raw == null || raw.trim().isEmpty()) {
return new String[]{"", ""};
}
raw = raw.trim();
// If starts with http/https
if (raw.startsWith("http://") || raw.startsWith("https://")) {
// Attempt to extract host + port via URL
try {
java.net.URL url = new java.net.URL(raw);
String host = url.getHost(); // hostname or IP
int port = url.getPort(); // -1 if no port
String path = url.getPath(); // /api or /
// If port exists split normally
if (port != -1) {
return new String[]{
host, // e.g. 10.10.10.10
String.valueOf(port) // e.g. 5000
};
}
// No port do NOT split
return new String[]{ raw, "" };
} catch (Exception e) {
// fail-safe: do not split
return new String[]{ raw, "" };
}
}
// Normal "IP:Port" split
int idx = raw.lastIndexOf(":");
if (idx == -1) {
return new String[]{ raw, "" };
}
return new String[]{
raw.substring(0, idx),
raw.substring(idx + 1)
};
}
}

View File

@ -1,193 +0,0 @@
package com.utsmm.kbz.ui.settings;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.nexgo.downloadkey.downloadflow.DownloadFEntity;
import com.nexgo.downloadkey.downloadflow.DownloadFlow;
import com.nexgo.downloadkey.downloadflow.DownloadFlowProcessListener;
import com.nexgo.downloadkey.downloadflow.DownloadFlowResultEntity;
import com.nexgo.downloadkey.downloadflow.DownloadResult;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.FragmentInjectKeyBinding;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmm.kbz.util.tms.TMSUtil;
public class InjectKeyFragment extends DataBindingFragment {
private static final String TAG = InjectKeyFragment.class.getSimpleName();
// Data binding will handle view access automatically
private FragmentInjectKeyBinding binding;
// Key injection variables
private DownloadFlow mDownloadFlow;
private int keyIndexTmp = 8; // Default key index
@Override
protected void initViewModel() {
// No specific viewmodels needed for this fragment
}
@Override
protected DataBindingConfig getDataBindingConfig() {
// This is the key method that links the XML and fragment properly
return new DataBindingConfig(R.layout.fragment_inject_key, 0, null)
.addBindingParam(BR.click, new ClickEvent());
}
@Override
protected int currentId() {
return R.id.injectKeyFragment;
}
@Override
protected int hostId() {
return R.id.nav_host_fragment;
}
@Override
protected int routeId() {
return 0;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
try {
// Get the binding from the base class - this is automatically created
binding = (FragmentInjectKeyBinding) mBinding;
updateConfigurationInfo();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon("Inject Key");
}
private void updateConfigurationInfo() {
String terminalId = SystemParamsOperation.getInstance().getTerminalId();
binding.terminalIdValue.setText(terminalId != null && !terminalId.isEmpty() ?
terminalId : "Not configured");
// Update Merchant ID
String merchantId = SystemParamsOperation.getInstance().getMerchantId();
binding.merchantIdValue.setText(merchantId != null && !merchantId.isEmpty() ?
merchantId : "Not configured");
// Update Serial Number
String serialNo = TMSUtil.getInstance().getSerialNumber();
binding.serialNumberValue.setText(serialNo != null && !serialNo.isEmpty() ?
serialNo : "Not configured");
}
private void loadKeyFromKeyPOS() {
try {
if (TextUtils.isEmpty(binding.etKeyIndex.getText())) {
Toast.makeText(getContext(), "Please input key index", Toast.LENGTH_SHORT).show();
return;
}
String keyIndexText = binding.etKeyIndex.getText().toString().trim();
try {
keyIndexTmp = Integer.parseInt(keyIndexText);
} catch (NumberFormatException e) {
Toast.makeText(getContext(), "Invalid key index format", Toast.LENGTH_SHORT).show();
return;
}
showLoadingDialog("Loading key...");
mDownloadFlow = DownloadFlow.getInstance();
String terminalId = SystemParamsOperation.getInstance().getTerminalId();
String merchantId = SystemParamsOperation.getInstance().getMerchantId();
String serialNo = TMSUtil.getInstance().getSerialNumber();
// Validate configuration
if (TextUtils.isEmpty(terminalId) || TextUtils.isEmpty(merchantId) || TextUtils.isEmpty(serialNo)) {
dismissLoadingDialog();
showDeclineDialog("Please configure Terminal ID, Merchant ID first in TMS Configuration");
return;
}
final DownloadFEntity downloadFEntity = new DownloadFEntity();
downloadFEntity.setSn(serialNo.getBytes());
downloadFEntity.setMid(merchantId.getBytes());
downloadFEntity.setTid(terminalId.getBytes());
downloadFEntity.setTmkIndex(keyIndexTmp);
downloadFEntity.setPort(0);
downloadFEntity.setTimeOut(10);
int result = mDownloadFlow.startLoadKey(getActivity(), downloadFEntity, onDownloadFlowProcessListener);
if (result != DownloadResult.Success) {
dismissLoadingDialog();
showDeclineDialog("Failed to start key injection process");
LogUtil.e(TAG, "Failed to start key injection, result: " + result);
}
} catch (Exception e) {
dismissLoadingDialog();
LogUtil.e(TAG, "Error in key injection: " + e.getMessage());
showDeclineDialog("Error occurred during key injection: " + e.getMessage());
}
}
private DownloadFlowProcessListener onDownloadFlowProcessListener = new DownloadFlowProcessListener() {
@Override
public void onFinish(int ret, DownloadFlowResultEntity downloadFlowResultEntity) {
try {
dismissLoadingDialog();
if (ret == DownloadResult.Success) {
// Show success dialog with key index
showSuccessDialog("Key injection successful!\nKey Index: " + keyIndexTmp);
LogUtil.d(TAG, "Key injection successful for index: " + keyIndexTmp);
} else {
// Show decline dialog
showDeclineDialog("Key injection failed!\nError code: " + ret);
LogUtil.e(TAG, "Key injection failed with error code: " + ret);
}
} catch (Exception e) {
LogUtil.e(TAG, "Error handling injection result: " + e.getMessage());
showDeclineDialog("Error processing injection result");
}
}
};
// ClickEvent class for data binding - this is the proper pattern
public class ClickEvent {
public void onInjectKeyClick() {
try {
LogUtil.d(TAG, "Inject key button clicked");
loadKeyFromKeyPOS();
} catch (Exception e) {
LogUtil.e(TAG, "Error in inject key click: " + e.getMessage());
showDeclineDialog("Error occurred: " + e.getMessage());
}
}
}
}

View File

@ -1,388 +0,0 @@
package com.utsmm.kbz.ui.settlement;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.QRSettleData;
import com.utsmyanmar.paylibs.model.SettleData;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsSettings;
import com.utsmyanmar.paylibs.utils.enums.HostType;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.params.Params;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.management.ManagementViewModel;
import com.utsmm.kbz.util.ecr.CoreUtils;
import java.util.ArrayList;
import java.util.List;
public class QRSettlementTransactionFragment extends DataBindingFragment implements DataBindingFragment.BackPressCallback {
private static final String TAG = QRSettlementTransactionFragment.class.getSimpleName();
private SharedViewModel sharedViewModel;
private ManagementViewModel managementViewModel;
private SettlementViewModel settlementViewModel;
ArrayList<PayDetail> qrTransactionsList = new ArrayList<>();
ArrayList<PayDetail> qrTransListAll = new ArrayList<>();
SettleData settleData;
private int routeId;
private int count = 0;
private long totalAmount = 0;
@Override
protected void initViewModel() {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
managementViewModel = getFragmentScopeViewModel(ManagementViewModel.class);
settlementViewModel = getFragmentScopeViewModel(SettlementViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_qr_settlement_screen, BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.manageViewModel, managementViewModel)
.addBindingParam(BR.settleViewModel, settlementViewModel)
.addBindingParam(BR.click, new ClickEvent());
}
@Override
protected int currentId() {
return R.id.QRSettlementTransactionFragment;
}
@Override
protected int hostId() {
return Constants.NAV_HOST_ID;
}
@Override
protected int routeId() {
return routeId;
}
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon(getString(R.string.title_qr_settlement));
String merchantName = SystemParamsOperation.getInstance().getMerchantName();
if (!TextUtils.equals(merchantName, "")) {
sharedViewModel.merchantName.postValue(merchantName);
} else {
sharedViewModel.merchantName.postValue("Default Value");
}
if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT) {
setToolBarTitleWithBackIcon(getString(R.string.txt_subtitle_reprint_last_settle_report));
delayFunctionCall(this::observeQRLastSettlementTransactions);
} else {
setToolBarTitleWithBackIcon(getString(R.string.title_view_batch));
delayFunctionCall(this::observeQRTransactions);
}
showLoadingView();
// setupQRSettlementData();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setupBackButtonPressDetection(this);
setupQRSettlementData();
}
private void showLoadingView() {
managementViewModel.detailReportLayoutLoadingVisibility.setValue(0);
managementViewModel.detailReportLayoutVisibility.setValue(8);
managementViewModel.detailReportLayoutViewVisibility.setValue(8);
managementViewModel.detailReportBottomLayoutVisibility.setValue(8);
}
private void showDataView() {
managementViewModel.detailReportLayoutLoadingVisibility.setValue(8);
managementViewModel.detailReportLayoutVisibility.setValue(8);
managementViewModel.detailReportLayoutViewVisibility.setValue(0);
managementViewModel.detailReportBottomLayoutVisibility.setValue(0);
}
private void showEmptyDataView() {
managementViewModel.detailReportLayoutLoadingVisibility.setValue(8);
managementViewModel.detailReportLayoutVisibility.setValue(0);
managementViewModel.detailReportLayoutViewVisibility.setValue(8);
managementViewModel.detailReportBottomLayoutVisibility.setValue(8);
}
private void setupQRSettlementData() {
managementViewModel.hostTypeDR.setValue("PAYMENT");
managementViewModel.cardTypeDR.setValue("QR PAY");
}
private void observeQRTransactions() {
managementViewModel.getTransactionHistory().observe(getViewLifecycleOwner(), payDetailList -> {
if (payDetailList != null) {
qrTransactionsList.clear();
qrTransListAll.clear();
count = 0;
totalAmount = 0;
try {
for (PayDetail payDetail : payDetailList) {
// Filter for QR transactions only
if ((payDetail.getTransactionType() == TransactionsType.MMQR.value
|| payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value)
&& payDetail.getQrTransStatus() == 1) {
boolean isNeedMinusSign = payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value;
qrTransactionsList.add(payDetail);
count++;
if (isNeedMinusSign) {
totalAmount -= payDetail.getAmount();
} else {
totalAmount += payDetail.getAmount();
}
}
else if(payDetail.getTransactionType() == TransactionsType.MMQR.value || payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
qrTransListAll.add(payDetail);
}
}
} catch (IllegalStateException e) {
LogUtil.e(TAG,"QRSettlement : Database cursor error - likely due to large data size:"+ e);
showEmptyDataView();
settlementViewModel.isNoData.setValue(true);
return;
}
if (qrTransactionsList.isEmpty()) {
showEmptyDataView();
settlementViewModel.isNoData.setValue(true);
} else {
showDataView();
settlementViewModel.isNoData.setValue(false);
setupSettlementDisplayData();
}
} else {
showEmptyDataView();
settlementViewModel.isNoData.setValue(true);
}
});
}
private void observeQRLastSettlementTransactions() {
List<PayDetail> payDetailList = managementViewModel.payDetails.getValue();
if( payDetailList != null) {
PayDetail payDetail = payDetailList.get(payDetailList.size() - 1);
int qrSaleCount = 0;
long qrSaleAmount = 0;
int qrRefundCount = 0;
long qrRefundAmount = 0;
count = 0;
totalAmount = 0;
SettleData settleData = payDetail.getSettleDataObj();
qrSaleCount = settleData.getSaleCount();
qrSaleAmount = settleData.getSaleAmount();
qrRefundAmount = settleData.getRefundAmount();
qrRefundCount = settleData.getRefundCount();
totalAmount = qrSaleAmount - qrRefundAmount;
count = qrSaleCount + qrRefundCount;
settlementViewModel.sale_count.setValue(qrSaleCount);
settlementViewModel.sale_amount.setValue(qrSaleAmount);
settlementViewModel.refund_count.setValue(qrRefundCount);
settlementViewModel.refund_amount.setValue(qrRefundAmount);
managementViewModel.totalAmountDR.setValue(totalAmount);
managementViewModel.trnxCountDR.setValue(String.valueOf(count));
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount));
sharedViewModel.payDetail.setValue(payDetail);
showDataView();
settlementViewModel.isNoData.setValue(false);
// if (qrTransactionsList.isEmpty()) {
// showEmptyDataView();
// settlementViewModel.isNoData.setValue(true);
// } else {
// showDataView();
// settlementViewModel.isNoData.setValue(false);
// }
} else {
showEmptyDataView();
settlementViewModel.isNoData.setValue(true);
}
}
private void setupSettlementDisplayData() {
// Calculate QR sale and refund counts/amounts
int qrSaleCount = 0;
long qrSaleAmount = 0;
int qrRefundCount = 0;
long qrRefundAmount = 0;
totalAmount = 0;
for (PayDetail payDetail : qrTransactionsList) {
if (payDetail.getTransactionType() == TransactionsType.MMQR.value) {
qrSaleCount++;
qrSaleAmount += payDetail.getAmount();
} else if (payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
qrRefundCount++;
qrRefundAmount += payDetail.getAmount();
}
}
totalAmount = qrSaleAmount - qrRefundAmount;
// Set values in settlement view model for display
settlementViewModel.sale_count.setValue(qrSaleCount);
settlementViewModel.sale_amount.setValue(qrSaleAmount);
settlementViewModel.refund_count.setValue(qrRefundCount);
settlementViewModel.refund_amount.setValue(qrRefundAmount);
managementViewModel.totalAmountDR.setValue(totalAmount);
managementViewModel.trnxCountDR.setValue(String.valueOf(count));
// Create settlement data for transaction result
settleData = new SettleData(qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
}
private void finishECRProcess() {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getString(R.string.txt_cancel_trans));
sharedViewModel.isEcrFinished.postValue(true);
sharedViewModel.isEcr.postValue(false);
}
private void navigateToResult() {
routeId = R.id.action_QRSettlementTransactionFragment_to_transactionResultFragment;
safeNavigateToRouteId();
}
private void processData() {
TradeData tradeData = Params.newTrade(false);
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setSettleDataObj(settleData);
payDetail.setTransactionType(TransactionsType.MMQR_SETTLEMENT.value);
payDetail.setTransType(TransactionsType.MMQR_SETTLEMENT.name);
payDetail.setAmount(totalAmount);
payDetail.setTradeAnswerCode("000");
payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum());
payDetail.setQrSettleData(QRSettleData.convertFromPayDetail(qrTransactionsList));
if(sharedViewModel.getTransMenu().getValue() != TransMenu.LAST_SETTLEMENT) {
sharedViewModel.insertPayDetail(payDetail);
}
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount));
sharedViewModel.payDetails.setValue(qrTransactionsList);
sharedViewModel.payDetail.setValue(payDetail);
for (PayDetail pay : qrTransactionsList) {
settlementViewModel.deletePayDetail(pay);
}
for (PayDetail pay : qrTransListAll) {
settlementViewModel.deletePayDetail(pay);
}
}
private void updateData() {
// EReceiptRequest request = EReceiptUtil.getInstance().generateMPUReceipt(sharedViewModel.payDetail.getValue());
EReceiptRequest request = EReceiptUtil.getInstance().generateQRSettlement(sharedViewModel.payDetail.getValue(), QRSettleData.convertFromPayDetail(qrTransactionsList));
sharedViewModel.pushReceipt(request);
}
@Override
public void onBackPress() {
if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) {
finishECRProcess();
}
popBackStack();
}
private void navigateToMain() {
routeId = R.id.action_QRSettlementTransactionFragment_to_nav_main;
safeNavigateToRouteId();
}
public class ClickEvent {
public void onCancel() {
if(sharedViewModel.getTransMenu().getValue() == TransMenu.SETTLEMENT) {
if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) {
finishECRProcess();
}
popBackStack();
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT) {
navigateToMain();
}
}
public void onConfirm() {
if(sharedViewModel.getTransMenu().getValue() == TransMenu.SETTLEMENT) {
if (!qrTransactionsList.isEmpty()) {
SystemParamsOperation.getInstance().getIncrementBatchNo();
processData();
updateData();
navigateToResult();
}
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT) {
routeId = R.id.action_QRSettlementTransactionFragment_to_reprintReceiptFragment;
safeNavigateToRouteId();
}
}
}
}

View File

@ -1,113 +0,0 @@
package com.utsmm.kbz.ui.settlement;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.utils.enums.HostType;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.ecr.CoreUtils;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmm.kbz.util.Connectivity;
import com.utsmm.kbz.config.data.model.ValidityStatus;
public class SelectSettlementFragment extends DataBindingFragment implements DataBindingFragment.BackPressCallback {
private SharedViewModel sharedViewModel;
private int routeId;
@Override
protected void initViewModel() {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_select_settlement_screen, BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.click, new ClickEvent());
}
@Override
protected int currentId() {
return R.id.selectSettlementFragment;
}
@Override
protected int hostId() {
return Constants.NAV_HOST_ID;
}
@Override
protected int routeId() {
return routeId;
}
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon(getString(R.string.title_select_settlement_type));
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setupBackButtonPressDetection(this);
}
private void finishECRProcess() {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getString(R.string.txt_cancel_trans));
sharedViewModel.isEcrFinished.postValue(true);
sharedViewModel.isEcr.postValue(false);
}
@Override
public void onBackPress() {
if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) {
finishECRProcess();
}
popBackStack();
}
public class ClickEvent {
public void onCardSettlement() {
if (TMSUtil.getInstance().checkParams().isStatus() == ValidityStatus.FAILURE) {
showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkParams().getMessage());
} else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
} else{
routeId = R.id.action_selectSettlementFragment_to_settlementTransactionFragment;
safeNavigateToRouteId();
}
}
public void onQRSettlement() {
if (TMSUtil.getInstance().checkQRParams().isStatus() == ValidityStatus.FAILURE) {
showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkQRParams().getMessage());
} else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
} else {
sharedViewModel.hostType.setValue(HostType.QR);
routeId = R.id.action_selectSettlementFragment_to_QRSettlementTransactionFragment;
safeNavigateToRouteId();
}
}
public void onCancel() {
if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) {
finishECRProcess();
}
popBackStack();
}
}
}

View File

@ -8,17 +8,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import com.utsmm.kbz.ui.management.ManagementViewModel;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
import com.utsmyanmar.paylibs.sign_on.EchoTestProcess;
import com.utsmyanmar.paylibs.sign_on.SignOnListener;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionType;
@ -41,8 +36,6 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
private SettlementViewModel settlementViewModel;
private SharedViewModel sharedViewModel;
private ManagementViewModel managementViewModel;
private int routeId;
int saleCount = 0;
@ -58,14 +51,12 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
protected void initViewModel() {
settlementViewModel = getFragmentScopeViewModel(SettlementViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
managementViewModel = getFragmentScopeViewModel(ManagementViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_view_batch_screen, BR.settleViewModel,settlementViewModel)
.addBindingParam(BR.sharedViewModel,sharedViewModel)
.addBindingParam(BR.managementViewModel,managementViewModel)
.addBindingParam(BR.click,new ClickEvent());
}
@ -142,20 +133,7 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
settlementViewModel.getLastSettlement(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), payDetails -> {
if (payDetails != null) {
if (!payDetails.isEmpty()) {
PayDetail payDetail = null;
for (int i = payDetails.size() - 1; i >= 0; i--) {
PayDetail candidate = payDetails.get(i);
if (candidate != null && candidate.getTransactionType() == TransactionsType.SETTLEMENT.value) {
payDetail = candidate;
break;
}
}
if (payDetail == null) {
settlementViewModel.isNoData.setValue(true);
setSettlementViewModelData(0, 0, 0, 0, 0, 0, 0, 0);
return;
}
PayDetail payDetail = payDetails.get(payDetails.size() - 1);
saleCount = payDetail.getSettleDataObj().getSaleCount();
@ -176,10 +154,6 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
setSettlementViewModelData(saleCount, saleAmount, preCount, preAmount, refundCount, refundAmount, caCount, caAmount);
settlementViewModel.setPayDetails(payDetails);
managementViewModel.payDetail.setValue(payDetail);
sharedViewModel.payDetail.setValue(payDetail);
}
} else {
@ -212,35 +186,32 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
}
settlementViewModel.getSettlementPOS().observe(getViewLifecycleOwner(), payDetails -> {
resetSettlementCounters();
if(payDetails != null && !payDetails.isEmpty()) {
if(!payDetails.isEmpty()) {
for(PayDetail payDetail:payDetails) {
int transType = payDetail.getTransactionType();
String transName = payDetail.getTransType();
if((transType == TransactionType.SALE || "SALE".equalsIgnoreCase(transName)) && !payDetail.isCanceled){
saleCount ++;
saleAmount += payDetail.getAmount();
} else if((transType == TransactionType.PRE_SALE_COMPLETE
|| "PREAUTH COMPLETION".equalsIgnoreCase(transName)
|| "PRE_AUTH_COMPLETE".equalsIgnoreCase(transName)) && !payDetail.isCanceled){
preCount ++;
preAmount += payDetail.getAmount();
}
else if(transType == TransactionType.REFUND || "REFUND".equalsIgnoreCase(transName)){
refundCount ++;
refundAmount += payDetail.getAmount();
}else if(transType == TransactionType.CASH_ADVANCE
|| "CASH_OUT".equalsIgnoreCase(transName)
|| "CASH_ADVANCE".equalsIgnoreCase(transName)){
caCount ++;
caAmount += payDetail.getAmount();
}
// if(payDetail.isSettlementEnabled()) {
if(payDetail.getTransactionType() == TransactionType.SALE && !payDetail.isCanceled){
saleCount ++;
saleAmount += payDetail.getAmount();
} else if(payDetail.getTransactionType() == TransactionType.PRE_SALE_COMPLETE && !payDetail.isCanceled){
preCount ++;
preAmount += payDetail.getAmount();
}
else if(payDetail.getTransactionType() == TransactionType.REFUND){
refundCount ++;
refundAmount += payDetail.getAmount();
}else if(payDetail.getTransactionType() == TransactionType.CASH_ADVANCE){
caCount ++;
caAmount += payDetail.getAmount();
}
// }
// sharedViewModel.payDetail.setValue(payDetail);
}
long totalAmount = saleAmount + preAmount + caAmount;
sharedViewModel.totalAmount.postValue(totalAmount);
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount));
settlementViewModel.isNoData.setValue(false);
@ -249,9 +220,17 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
} else {
settlementViewModel.isNoData.setValue(true);
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(0));
int saleCount = 0;
int preCount = 0;
int refundCount = 0;
int caCount = 0;
long saleAmount = 0;
long preAmount = 0;
long refundAmount = 0;
long caAmount = 0;
settlementViewModel.isNoData.setValue(true);
setSettlementViewModelData(saleCount,saleAmount,preCount,preAmount,refundCount,refundAmount,caCount,caAmount);
}
@ -267,17 +246,6 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
});
}
private void resetSettlementCounters() {
saleCount = 0;
preCount = 0;
refundCount = 0;
caCount = 0;
saleAmount = 0L;
preAmount = 0L;
refundAmount = 0L;
caAmount = 0L;
}
private void setSettlementViewModelData(int saleCount,long saleAmount,int preCount,long preAmount,int refundCount,long refundAmount,int caCount,long caAmount) {
settlementViewModel.sale_count.setValue(saleCount);
settlementViewModel.sale_amount.setValue(saleAmount);
@ -348,9 +316,7 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
dismissLoadingDialog();
updateData();
if (!SystemParamsOperation.getInstance().getDemoStatus()) {
networkCutOver(); // bpc
navigateToNext();
networkCutOver();
} else {
navigateToNext();
}
@ -370,10 +336,6 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
private void updateData() {
sharedViewModel.payDetail.setValue(settlementViewModel.getPayDetail());
EReceiptRequest request = EReceiptUtil.getInstance().generateMPUReceipt(sharedViewModel.payDetail.getValue());
sharedViewModel.pushReceipt(request);
}
@Override
@ -416,23 +378,12 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
}
public void onConfirm(){
if(sharedViewModel.getTransMenu().getValue() == TransMenu.SETTLEMENT) {
/* April 10 , 2024 Smile requested not to send to host even settlement button was clicked */
settlementViewModel.startSettlementProcess();
showLoadingDialog("Sending ...");
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH) {
sharedViewModel.startPrintSettlement(new PrintXStatus() {
@Override
public void onSuccess() {
}
@Override
public void onFailure() {
}
});
sharedViewModel.startPrintProcessSettlement();
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT) {
routeId = R.id.action_settlementTransactionFragment_to_reprintReceiptFragment;
safeNavigateToRouteId();

View File

@ -7,8 +7,6 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.batch_upload.BatchListener;
@ -16,7 +14,6 @@ import com.utsmyanmar.paylibs.batch_upload.BatchUploadProcess;
import com.utsmyanmar.paylibs.isobuilder.ISOMode;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion;
import com.utsmyanmar.paylibs.model.CardSettleData;
import com.utsmyanmar.paylibs.model.MsgField;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.SettleData;
@ -212,21 +209,16 @@ public class SettlementViewModel extends ViewModel {
repository.updatePayDetail(payDetail);
}
public void deletePayDetail(PayDetail payDetail){
repository.deletePayDetail(payDetail);
}
private void updateDB() {
if(payDetails != null && payDetails.size() > 0) {
for (PayDetail pay:payDetails) {
for (PayDetail paydetail:payDetails) {
// if(paydetail.getTransactionType() == TransactionsType.SALE.value) {
// paydetail.setIsSettle(true);
// updatePayDetail(paydetail);
// } else {
deletePayDetail(pay);
// repository.deletePayDetail(paydetail);
repository.deletePayDetail(paydetail);
// }
@ -236,8 +228,7 @@ public class SettlementViewModel extends ViewModel {
for (PayDetail pay:deleteTrans
) {
// repository.deletePayDetail(pay);
deletePayDetail(pay);
repository.deletePayDetail(pay);
}
if (payDetails != null) {
payDetails.clear();
@ -254,8 +245,6 @@ public class SettlementViewModel extends ViewModel {
repository.insertPayDetail(payDetail);
}
@SuppressWarnings("ConstantConditions")
public void startSettlementProcess() {
saleCount = sale_count.getValue();
@ -372,26 +361,14 @@ public class SettlementViewModel extends ViewModel {
payDetail = tradeData.getPayDetail();
//
if(hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_SETTLEMENT;
} else {
bitmap = BitmapConfig.MPU_NEW_SETTLE;
}
bitmap = BitmapConfig.BPC_SETTLEMENT;
payDetail.setTransType(TransactionsType.SETTLEMENT.name);
payDetail.setTransactionType(TransactionType.SETTLEMENT);
if (!flag) {
payDetail.setProcessCode(TransactionsType.SETTLEMENT.processCode);
} else {
if(hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_SETTLEMENT_TRAILER;
payDetail.setProcessCode("910000");
} else {
bitmap = BitmapConfig.MPU_NEW_SETTLE;
payDetail.setProcessCode("960000");
}
bitmap = BitmapConfig.BPC_SETTLEMENT_TRAILER;
payDetail.setProcessCode("910000");
}
// CA:CA - CD - FT
@ -403,9 +380,6 @@ public class SettlementViewModel extends ViewModel {
SettleData settleData = new SettleData(saleCount,saleAmount,preAuthCount,preAuthAmount,refundCount,refundAmount,caCount,caAmount);
payDetail.setSettleDataObj(settleData);
if(payDetails != null)
payDetail.setCardSettleData(CardSettleData.convertFromPayDetail(payDetails));
if(hostName == HostName.BPC) {
long totalAmount = saleAmount + preAuthAmount + refundAmount + caAmount;
@ -429,8 +403,7 @@ public class SettlementViewModel extends ViewModel {
payDetail.setSettleData(settlementData);
payDetail.setAmount(totalAmount);
} else {
// payDetail.setSettleData(totalSaleCount + totalSaleAmount + totalRefundCount + totalRefundAmount + totalDebitSaleCount + totalDebitSaleAmount + totalERefundCount + totalERefundAmount); //field 63 BPC
payDetail.setSettleData(totalSaleCount + totalSaleAmount + totalRefundCount + totalRefundAmount + totalDebitSaleCount + totalDebitSaleAmount ); //field 63
payDetail.setSettleData(totalSaleCount + totalSaleAmount + totalRefundCount + totalRefundAmount + totalDebitSaleCount + totalDebitSaleAmount + totalERefundCount + totalERefundAmount); //field 63
}
@ -462,7 +435,11 @@ public class SettlementViewModel extends ViewModel {
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
//reversal
// if (!flag && isNoData.getValue()) {
payDetail.setIsNeedReversal(!flag);
if (!flag ) {
payDetail.setIsNeedReversal(true);
} else {
payDetail.setIsNeedReversal(false);
}
}
} else {
@ -509,12 +486,8 @@ public class SettlementViewModel extends ViewModel {
// to leave data for testing
// if (settlementType.getValue() == SettlementType.NORMAL) {
updateDB();
// }
insertPayDetail(payDetail);
if (errorFlag) {

View File

@ -1,12 +1,5 @@
package com.utsmm.kbz.ui.tms;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.PowerManager;
import android.provider.Settings;
import android.os.Bundle;
import android.view.View;
@ -15,7 +8,6 @@ import androidx.annotation.Nullable;
import com.google.gson.Gson;
import com.google.gson.stream.MalformedJsonException;
import com.utsmm.kbz.service.AutoAlarmReceiver;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusError;
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest;
@ -34,8 +26,6 @@ import com.utsmm.kbz.util.enums.TMSDownloadStatus;
import com.utsmm.kbz.util.tms.TMSUtil;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
@ -180,22 +170,12 @@ public class TMSProcessFragment extends DataBindingFragment {
} else if (e instanceof HttpException) {
HttpException error = (HttpException)e;
try {
String errorBody = error.response() != null && error.response().errorBody() != null
? error.response().errorBody().string()
: "";
String message = (errorBody == null || errorBody.trim().isEmpty())
? ("Network error (" + error.code() + ")")
: errorBody;
if (errorBody != null) {
String trimmed = errorBody.trim();
if (trimmed.startsWith("{")) {
SiriusError siriusError = new Gson().fromJson(trimmed, SiriusError.class);
message = siriusError != null ? siriusError.getMessage() : trimmed;
}
}
SiriusError siriusError = new Gson().fromJson(error.response().errorBody().string(), SiriusError.class);
if(tmsUpdate == TMSUpdate.CHECK){
tmsProcessViewModel.setTmsDownloadMsg(message);
tmsProcessViewModel.setTmsDownloadMsg(siriusError.getMessage());
}
} catch (IOException ex) {
throw new RuntimeException(ex);
} catch (Exception ex) {
@ -232,12 +212,7 @@ public class TMSProcessFragment extends DataBindingFragment {
}
CurrencyType currencyType = SystemParamsOperation.getInstance().getCurrencyType();
sharedViewModel.set_currencyText(currencyType.name);
tmsProcessViewModel.loadEmvParameters();
// Check and request battery optimization exemption before scheduling alarm
requestBatteryOptimizationExemption();
scheduleAutoSettlement();
// tmsProcessViewModel.loadEmvParameters();
navigateToMain();
}
});
@ -249,135 +224,4 @@ public class TMSProcessFragment extends DataBindingFragment {
}
private void scheduleAutoSettlement() {
String timeStr = SystemParamsOperation.getInstance().getClearBatchTime();
LogUtil.d(TAG,"timeStr:" + timeStr );
if(timeStr == null || timeStr.trim().isEmpty()) {
LogUtil.d(TAG, "Clear batch time is empty, skipping auto settlement scheduling");
return;
}
String[] parts = timeStr.trim().split(":");
if(parts.length != 2) {
LogUtil.d(TAG, "Invalid time format: " + timeStr + ", expected HH:MM");
return;
}
int hour;
int minute;
try {
hour = Integer.parseInt(parts[0]);
minute = Integer.parseInt(parts[1]);
// Validate time range
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
LogUtil.d(TAG, "Invalid time values - hour: " + hour + ", minute: " + minute);
return;
}
} catch (Exception e) {
LogUtil.d(TAG, "Error parsing time string: " + timeStr + ", error: " + e.getMessage());
return;
}
LogUtil.d(TAG, "Scheduling auto settlement for hour:" + hour + " minute:" + minute);
AlarmManager alarmManager = (AlarmManager) requireContext().getSystemService(Context.ALARM_SERVICE);
if (alarmManager == null) {
LogUtil.d(TAG, "AlarmManager is null, cannot schedule alarm");
return;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(java.util.Calendar.HOUR_OF_DAY, hour);
calendar.set(java.util.Calendar.MINUTE, minute);
calendar.set(java.util.Calendar.SECOND, 0);
calendar.set(java.util.Calendar.MILLISECOND, 0);
long triggerAtMillis = calendar.getTimeInMillis();
long currentTime = System.currentTimeMillis();
LogUtil.d(TAG, "Current time: " + new java.util.Date(currentTime).toString());
LogUtil.d(TAG, "Initial trigger time: " + new java.util.Date(triggerAtMillis).toString());
if (triggerAtMillis <= currentTime) {
calendar.add(Calendar.DAY_OF_YEAR, 1);
triggerAtMillis = calendar.getTimeInMillis();
LogUtil.d(TAG, "Updated trigger time for NEXT DAY: " + new java.util.Date(triggerAtMillis).toString());
} else {
LogUtil.d(TAG, "Scheduling alarm for TODAY: " + new java.util.Date(triggerAtMillis).toString());
}
Intent intent = new Intent(requireContext(), AutoAlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
requireContext(),
1001,
intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
try {
alarmManager.cancel(pendingIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
if (alarmManager.canScheduleExactAlarms()) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
} else {
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
}
} else {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
}
} else {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
}
long hoursUntilTrigger = (triggerAtMillis - currentTime) / 1000 / 60 / 60;
long minutesUntilTrigger = ((triggerAtMillis - currentTime) / 1000 / 60) % 60;
LogUtil.d(TAG, "Auto settlement alarm setup completed. Next occurrence: " + new Date(triggerAtMillis).toString());
LogUtil.d(TAG, "Time until next trigger: " + hoursUntilTrigger + " hours, " + minutesUntilTrigger + " minutes");
} catch (Exception e) {
LogUtil.e(TAG, "Error scheduling main alarm: " + e.getMessage());
e.printStackTrace();
LogUtil.e(TAG, "Alarm scheduling failed - Check if app has SCHEDULE_EXACT_ALARM permission");
LogUtil.e(TAG, "Failed alarm details - Target time: " + new Date(triggerAtMillis).toString());
}
}
private void requestBatteryOptimizationExemption() {
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
PowerManager powerManager = (PowerManager) requireContext().getSystemService(Context.POWER_SERVICE);
String packageName = requireContext().getPackageName();
if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
LogUtil.d(TAG, "Requesting battery optimization exemption for reliable alarms");
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
try {
startActivity(intent);
LogUtil.d(TAG, "Battery optimization exemption dialog opened");
} catch (Exception e) {
LogUtil.e(TAG, "Failed to open battery optimization dialog: " + e.getMessage());
// Fallback: Open battery optimization settings page
try {
Intent fallbackIntent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
startActivity(fallbackIntent);
LogUtil.d(TAG, "Battery optimization settings opened as fallback");
} catch (Exception fallbackException) {
LogUtil.e(TAG, "Fallback also failed: " + fallbackException.getMessage());
}
}
} else {
LogUtil.d(TAG, "App is already exempted from battery optimizations");
}
}
} catch (Exception e) {
LogUtil.e(TAG, "Error checking battery optimization status: " + e.getMessage());
}
}
}

View File

@ -1,142 +0,0 @@
package com.utsmm.kbz.util;
import com.utsmm.kbz.MyApplication;
import com.utsmyanmar.paylibs.utils.LogUtil;
import java.io.File;
import java.io.FileOutputStream;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class DownloadUtil {
private static final String TAG = DownloadUtil.class.getSimpleName();
public interface DownloadCallback {
void onDownloadSuccess(String path);
}
// ==============================
// RX ASYNC DOWNLOAD METHOD
// ==============================
public static void downloadCertificateRx(String url,
String dynamicFilename,
String timestamp,
String signature,
DownloadCallback callback) {
Observable.fromCallable(() ->
downloadCert(url, dynamicFilename, timestamp, signature)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(path -> {
if (callback != null) {
callback.onDownloadSuccess(path);
}
}, error -> {
LogUtil.e(TAG, "Download error : " + error);
if (callback != null) callback.onDownloadSuccess(null);
});
}
// ==============================
// ACTUAL DOWNLOAD LOGIC
// ==============================
private static String downloadCert(String url,
String dynamicFilename,
String timestamp,
String signature) {
// LogUtil.d(TAG, "cert timestamp => " + timestamp);
// LogUtil.d(TAG, "cert signature => " + signature);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
.readTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
.build();
Request request = new Request.Builder()
.url(url)
.addHeader("x-timestamp", timestamp)
.addHeader("x-api-key", signature)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful() || response.body() == null) {
LogUtil.e(TAG, "Download failed: " + response.code());
return null;
}
String contentType = response.header("Content-Type", "");
String ext = getExtensionFromContentType(contentType);
if (ext.isEmpty()) ext = getExtensionFromUrl(url);
if (ext.isEmpty()) ext = ".bin";
String filename = dynamicFilename + ext;
byte[] data = response.body().bytes();
return saveFile(filename, data);
} catch (Exception e) {
LogUtil.e(TAG, "Download exception : " + e);
return null;
}
}
// ==============================
// SAVE FILE
// ==============================
private static String saveFile(String filename, byte[] data) {
try {
File dir = MyApplication.getInstance().getFilesDir();
File file = new File(dir, filename);
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(data);
fos.flush();
}
return file.getAbsolutePath();
} catch (Exception e) {
LogUtil.e(TAG, "File save failed : " + e);
return null;
}
}
// ==============================
// MIME EXTENSION
// ==============================
private static String getExtensionFromContentType(String contentType) {
if (contentType == null) return "";
switch (contentType) {
case "application/x-x509-ca-cert":
return ".crt";
case "application/pkix-cert":
return ".cer";
case "application/x-pem-file":
case "application/octet-stream":
return ".pem";
case "application/x-pkcs12":
return ".p12";
default:
return "";
}
}
private static String getExtensionFromUrl(String url) {
if (url == null) return "";
int lastDot = url.lastIndexOf('.');
if (lastDot == -1) return "";
return url.substring(lastDot);
}
}

View File

@ -1,334 +0,0 @@
package com.utsmm.kbz.util;
import com.utsmm.kbz.BuildConfig;
import com.utsmm.kbz.util.enums.TransResultStatus;
import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.network.model.e_receipt.Transaction;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.QRSettleData;
import com.utsmyanmar.paylibs.model.SettleData;
import com.utsmyanmar.paylibs.system.BaseErrorCode;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class EReceiptUtil {
private static EReceiptUtil instance;
public static EReceiptUtil getInstance() {
instance = new EReceiptUtil();
return instance;
}
private String terminalId;
private String merchantId;
private String traceNo;
private String invoiceNo;
private String serialNum;
private String batchNumber;
private String packageName;
private String qrTerminalId;
private String qrMerchantId;
private EReceiptUtil() {
terminalId = SystemParamsOperation.getInstance().getTerminalId();
merchantId = SystemParamsOperation.getInstance().getMerchantId();
traceNo = SystemParamsOperation.getInstance().getCurrentSerialNum();
invoiceNo = SystemParamsOperation.getInstance().getCurrentInvoiceNum();
batchNumber = SystemParamsOperation.getInstance().getCurrentBatchNum();
serialNum = TMSUtil.getInstance().getSerialNumber();
packageName = BuildConfig.APPLICATION_ID;
qrTerminalId = SystemParamsOperation.getInstance().getSecHostTerminalId();
qrMerchantId = SystemParamsOperation.getInstance().getShortCode();
}
public EReceiptRequest generateQRReceipt(PayDetail payDetail, TransResultStatus status) {
String terminalIdForEreceipt = SystemParamsOperation.getInstance().getTerminalIdForEreceipt();
String hostId = SystemParamsOperation.getInstance().getSecHostId();
double realAmount = payDetail.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
String amount = df.format(realAmount);
String currentTimeStamp = new java.text.SimpleDateFormat("MMddHHmmss", java.util.Locale.getDefault())
.format(new java.util.Date());
EReceiptRequest request = new EReceiptRequest();
request.setDE3("QR");
request.setDE7(currentTimeStamp);
request.setDE37(payDetail.getReferNo());
request.setDE49("MMK");
request.setDE38(payDetail.getQrTransId());
request.setSerial(serialNum);
request.setAppId(packageName);
request.setDE41(qrTerminalId);
request.setDE42(qrMerchantId);
request.setTerminalId(terminalIdForEreceipt);
request.setShortCode(qrMerchantId);
request.setMmqrRef(payDetail.getQrReferNo() == null ? "" : payDetail.getQrReferNo());
request.setHostId(hostId);
request.setPaymentIdentifier(payDetail.getCustomerMobile());
request.setInvoiceNumber(payDetail.getInvoiceNo());
request.setDE11(payDetail.getVoucherNo());
// need to add payment identifier field too
if (status == TransResultStatus.SUCCESS) {
request.setDE4(amount);
request.setDescription("qr pay success");
request.setDE39("A");
} else if (status == TransResultStatus.TIME_OUT) {
request.setDE4("0");
request.setDescription("qr timeout");
request.setDE39("D");
} else if (status == TransResultStatus.FAIL) {
request.setDE4("0");
request.setDescription("qr failed");
request.setDE39("E");
}
return request;
}
public EReceiptRequest generateQRRefundReceipt(
String refundAmount,
String referenceNo,
String invoiceNo,
String voucherNo,
String mmqrRef,
String paymentIdentifier,
TransResultStatus status
) {
long amt = POSUtil.getInstance().convertAmount(refundAmount);
double realAmount = amt / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
String amount = df.format(realAmount);
String terminalIdForEreceipt = SystemParamsOperation.getInstance().getTerminalIdForEreceipt();
String hostId = SystemParamsOperation.getInstance().getSecHostId();
String currentTimeStamp = new java.text.SimpleDateFormat("MMddHHmmss", java.util.Locale.getDefault())
.format(new java.util.Date());
EReceiptRequest request = new EReceiptRequest();
request.setDE3("QRV");
request.setDE7(currentTimeStamp);
request.setDE37(referenceNo);
request.setDE49("MMK");
request.setSerial(serialNum);
request.setAppId(packageName);
request.setDE41(qrTerminalId);
request.setDE42(qrMerchantId);
request.setTerminalId(terminalIdForEreceipt);
request.setShortCode(qrMerchantId);
request.setInvoiceNumber(invoiceNo != null ? invoiceNo : "");
request.setDE11(voucherNo != null ? voucherNo : "");
request.setHostId(hostId);
request.setMmqrRef(mmqrRef);
request.setPaymentIdentifier(paymentIdentifier);
// need to add payment identifier field too
if (status == TransResultStatus.SUCCESS) {
request.setDE4(amount);
request.setDescription("qr refund success");
request.setDE39("A");
} else if (status == TransResultStatus.TIME_OUT) {
request.setDE4("0");
request.setDescription("qr refund timeout");
request.setDE39("D");
} else if (status == TransResultStatus.FAIL) {
request.setDE4("0");
request.setDescription("qr refund failed");
request.setDE39("E");
}
return request;
}
public EReceiptRequest generateMPUReceipt(PayDetail payDetail) {
double realAmount = payDetail.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
String amount = df.format(realAmount);
String currentTimeStamp = new java.text.SimpleDateFormat("MMddHHmmss", java.util.Locale.getDefault())
.format(new java.util.Date());
EReceiptRequest request = new EReceiptRequest();
request.setDE3(convertTransactionType(payDetail.getTransactionType()));
request.setDE7(currentTimeStamp);
request.setDE11(payDetail.getVoucherNo());
if (payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value) {
SettleData settleData = payDetail.getSettleDataObj();
long totalAmt = settleData.getSaleAmount() + settleData.getRefundAmount() + settleData.getPreAuthCompAmount() + settleData.getCashAdvanceAmount();
double realTotalAmount = totalAmt / 100.0;
String totalAmount = df.format(realTotalAmount);
request.setDE4(totalAmount);
request.setDE63_01(settleData.getSaleCount() + "");
request.setDE63_02(settleData.getSaleAmount() + "");
request.setDE63_03(settleData.getRefundCount() + "");
request.setDE63_04(settleData.getRefundAmount() + "");
request.setDE63_05(settleData.getPreAuthCompCount() + "");
request.setDE63_06(settleData.getPreAuthCompAmount() + "");
request.setDE63_07(settleData.getCashAdvanceCount() + "");
request.setDE63_08(settleData.getCashAdvanceAmount() + "");
invoiceNo = SystemParamsOperation.getInstance().getIncrementInvoiceNum();
request.setBatchNumber(batchNumber);
request.setInvoiceNumber(invoiceNo);
request.setDescription("success");
request.setDE39("A");
request.setDE37("0000");
request.setDE49("MMK");
} else {
request.setDE2(POSUtil.getInstance().getCardNumMasking(payDetail.getCardNo()));
request.setDE4(amount);
request.setDE37(payDetail.getReferNo());
request.setDE38(payDetail.getApprovalCode());
// will check it later for currency code
request.setDE49("MMK");
request.setInvoiceNumber(payDetail.getInvoiceNo());
request.setCardLabel("MPU");
if (payDetail.getTradeAnswerCode().equals("000") || payDetail.getTradeAnswerCode().equals("00")) {
request.setDescription("success");
request.setDE39("A");
} else {
request.setDescription(BaseErrorCode.getErrorMessage(payDetail.getTradeAnswerCode()));
request.setDE39("E");
}
}
request.setDE41(terminalId);
request.setDE42(merchantId);
request.setSerial(serialNum);
request.setAppId(packageName);
return request;
}
public EReceiptRequest generateQRSettlement(PayDetail payDetail, List<QRSettleData> transactions) {
double realAmount = payDetail.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
String amount = df.format(realAmount);
String currentTimeStamp = new java.text.SimpleDateFormat("MMddHHmmss", java.util.Locale.getDefault())
.format(new java.util.Date());
String terminalId = SystemParamsOperation.getInstance().getTerminalIdForEreceipt();
EReceiptRequest request = new EReceiptRequest();
// request.setDE3(convertTransactionType(payDetail.getTransactionType()));
request.setDE3("QRST");
request.setDE7(currentTimeStamp);
request.setDE11(payDetail.getVoucherNo());
String hostId = SystemParamsOperation.getInstance().getSecHostId();
request.setHostId(hostId);
request.setTerminalId(terminalId);//terminalId is not tid
request.setShortCode(qrMerchantId);
request.setTransactions(buildTransactions(transactions));
SettleData settleData = payDetail.getSettleDataObj();
long totalAmt = settleData.getSaleAmount() + settleData.getRefundAmount();
double realTotalAmount = totalAmt / 100.0;
String totalAmount = df.format(realTotalAmount);
request.setDE4(totalAmount);
request.setDE63_01(settleData.getSaleCount() + "");
request.setDE63_02(settleData.getSaleAmount() + "");
request.setDE63_03(settleData.getRefundCount() + "");
request.setDE63_04(settleData.getRefundAmount() + "");
invoiceNo = SystemParamsOperation.getInstance().getIncrementInvoiceNum();
request.setBatchNumber(batchNumber);
request.setInvoiceNumber(invoiceNo);
request.setDescription("success");
request.setDE39("A");
request.setDE37("0000");
request.setDE49("MMK");
request.setDE41(terminalId);
request.setDE42(merchantId);
request.setSerial(serialNum);
request.setAppId(packageName);
return request;
}
private static List<Transaction> buildTransactions(List<QRSettleData> qrSettleData) {
List<Transaction> list = new ArrayList<>();
for (QRSettleData pay : qrSettleData) {
double realAmount = pay.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
String amount = df.format(realAmount);
Transaction txn = new Transaction();
txn.setTran_id(pay.getTransId()); // or ref no
txn.setStatus(
pay.getTransactionType() == TransactionsType.MMQR_REFUND.value
? "REFUND_SUCCESS"
: "PAY_SUCCESS"
);
txn.setDate(pay.getDate()); // yyyyMMdd
txn.setTime(pay.getTime()); // HHmmss
txn.setAmount(amount);
list.add(txn);
}
return list;
}
public String convertTransactionType(int transactionType) {
if (transactionType == TransactionsType.SALE.value) {
return "S";
} else if (transactionType == TransactionsType.VOID.value) {
return "V";
} else if (transactionType == TransactionsType.PRE_AUTH_SALE.value) {
return "P";
} else if (transactionType == TransactionsType.PRE_AUTH_VOID.value) {
return "PV";
} else if (transactionType == TransactionsType.PRE_AUTH_COMPLETE.value) {
return "PC";
} else if (transactionType == TransactionsType.PRE_AUTH_COMPLETE_VOID.value) {
return "PCV";
} else if (transactionType == TransactionsType.CASH_OUT.value) {
return "CAV";
} else if (transactionType == TransactionsType.REFUND.value) {
return "R";
} else if (transactionType == TransactionsType.SETTLEMENT.value) {
return "ST";
} else if (transactionType == TransactionsType.MMQR_SETTLEMENT.value) {
return "ST";
}
return "E";
}
}

View File

@ -1,15 +1,13 @@
package com.utsmm.kbz.util;
import com.utsmyanmar.checkxread.model.CardDataX;
import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.utsmyanmar.paylibs.model.CardInfo;
import com.utsmyanmar.paylibs.model.ICCardInfo;
import com.utsmyanmar.paylibs.model.MAGCardInfo;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.model.enums.TransCVM;
import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.BaseCardType;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.config.Constants;
@ -44,50 +42,15 @@ public class MockData {
// .cardScheme("VISA")
// .cardHolderName("U AYE")
// .iccData("5F21BLAHBLAH")
// .build();
// mockCardData = new MockCardData.Builder()
// .cardNo("9503051034047056")
// .expDate("3002")
// .cardScheme("MPU")
// .cardHolderName("KBZ Debit")
// .iccData("9503051034047056=30021015930000000000")
// .build();
// 9505050178841157=28111011310000000000
// mockCardData = new MockCardData.Builder()
// .cardNo("9505050161133125")
// .expDate("2701")
// .cardScheme("MPU")
// .cardHolderName("KBZ Credit")
// .iccData("9505050161133125=27011017250000000000")
// .build();
mockCardData = new MockCardData.Builder()
.cardNo("9505050178841157")
.expDate("2811")
.cardNo("9503190006079422")
.expDate("0725")
.cardScheme("MPU")
.cardHolderName("KBZ Preprod")
.iccData("9505050178841157=28111011310000000000")
.cardHolderName("YOMA VALUED CUSTOMER")
.build();
// mockCardData = new MockCardData.Builder()
// .cardNo("9503712156912514")
// .expDate("2912")
// .cardScheme("MPU")
// .cardHolderName("Htin Kyaw Win")
// .iccData("9503712156912514=29121010000000000000")
// .build();
// mockCardData = new MockCardData.Builder()
// .cardNo("9503742975107251")
// .expDate("0629")
// .cardScheme("MPU")
// .cardHolderName("Bank Q")
// .iccData("9503742975107251=22081010000000000000")
// .build();
// mockCardData = new MockCardData.Builder()
// .phoneNo("9794452506")
// .expDate("0425")
@ -111,15 +74,6 @@ public class MockData {
return String.valueOf(randomNumber);
}
public CardDataX generateMPUCard() {
CardDataX cardDataX = new CardDataX();
cardDataX.setPan(mockCardData.getCardNo());
cardDataX.setExp(mockCardData.getExpDate());
cardDataX.setCardHolderName(mockCardData.getCardHolderName());
cardDataX.setTrack2(mockCardData.getIccData());
return cardDataX;
}
public TradeData generateMockDataWithTime(TransactionsType transType,int cardInputType,String transDate,String transTime) {
String strDate = SystemDateTime.getMMDD();
String strTime = SystemDateTime.getHHmmss();
@ -160,7 +114,6 @@ public class MockData {
payDetail.setOriginalTransDate(SystemDateTime.getMMDD()+SystemDateTime.getYYYY());
payDetail.setTransCVM(TransCVM.NO_CVM);
if(transType == TransactionsType.MMQR) {
payDetail.setCardType(cardInputType);
payDetail.setTransType(transType.name);
@ -168,13 +121,7 @@ public class MockData {
payDetail.setCardHolderName(mockCardData.getCardHolderName());
payDetail.setAccountType(mockCardData.getCardScheme());
payDetail.setCustomerMobile(mockCardData.getPhoneNo());
payDetail.setCustomerMobile("kbzpay");
payDetail.setOriginalTransDate("2024-09-16 15:57:10");
payDetail.setQrTransId("12345678");
payDetail.setQrTransStatus(1);
payDetail.setQrReferNo("123456789012");
payDetail.setReferNo("123456789012");
payDetail.setApprovalCode("12345678");
} else {
payDetail.setCardType(cardInputType);
@ -213,7 +160,7 @@ public class MockData {
// payDetail.setTransDate(strTransDate);
// payDetail.setTransTime(strTransTime);
payDetail.setAmount(100000);
payDetail.setAmount(10000);
payDetail.setTransactionType(transType.value);
tradeData.setPayDetail(payDetail);
@ -351,7 +298,7 @@ public class MockData {
String refundAmount = "1000";
int caCount = 0;
String caAmount = "0";
int cardInputType = BaseCardType.IC.getValue();
int cardInputType = AidlConstantsV2.CardType.IC.getValue();
TradeData tradeData = generateMockData(TransactionsType.SETTLEMENT,cardInputType);
PayDetail payDetail = tradeData.getPayDetail();
int totalAmount = Integer.parseInt(saleAmount) + Integer.parseInt(preAuthAmount) + Integer.parseInt(refundAmount);

Some files were not shown because too many files have changed in this diff Show More