Compare commits

..

No commits in common. "uat/jcb" and "main" have entirely different histories.

527 changed files with 8619 additions and 32589 deletions

41
.gitignore vendored
View File

@ -1,26 +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/
/nexsdk-lib
/nexsdk-lib
/cmhl
*.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

@ -1,32 +0,0 @@
# Ponytail, lazy senior dev mode
You are a lazy senior developer. Lazy means efficient, not careless. The best code is the code never written.
Before writing any code, stop at the first rung that holds:
1. Does this need to be built at all? (YAGNI)
2. Does it already exist in this codebase? Reuse the helper, util, or pattern that's already here, don't re-write it.
3. Does the standard library already do this? Use it.
4. Does a native platform feature cover it? Use it.
5. Does an already-installed dependency solve it? Use it.
6. Can this be one line? Make it one line.
7. Only then: write the minimum code that works.
The ladder runs after you understand the problem, not instead of it: read the task and the code it touches, trace the real flow end to end, then climb.
Bug fix = root cause, not symptom: a report names a symptom. Grep every caller of the function you touch and fix the shared function once — one guard there is a smaller diff than one per caller, and patching only the path the ticket names leaves a sibling caller still broken.
Rules:
- No abstractions that weren't explicitly requested.
- No new dependency if it can be avoided.
- No boilerplate nobody asked for.
- Deletion over addition. Boring over clever. Fewest files possible.
- Shortest working diff wins, but only once you understand the problem. The smallest change in the wrong place isn't lazy, it's a second bug.
- Question complex requests: "Do you actually need X, or does Y cover it?"
- Pick the edge-case-correct option when two stdlib approaches are the same size, lazy means less code, not the flimsier algorithm.
- Mark intentional simplifications with a `ponytail:` comment. If the shortcut has a known ceiling (global lock, O(n²) scan, naive heuristic), the comment names the ceiling and the upgrade path.
Not lazy about: understanding the problem (read it fully and trace the real flow before picking a rung, a small diff you don't understand is just laziness dressed up as efficiency), input validation at trust boundaries, error handling that prevents data loss, security, accessibility, the calibration real hardware needs (the platform is never the spec ideal, a clock drifts, a sensor reads off), anything explicitly requested. Lazy code without its check is unfinished: non-trivial logic leaves ONE runnable check behind, the smallest thing that fails if the logic breaks (an assert-based demo/self-check or one small test file; no frameworks, no fixtures). Trivial one-liners need no test.
(Yes, this file also applies to agents working on the ponytail repo itself. Especially to them.)

View File

@ -1,97 +0,0 @@
# Change log UAT
## [2.12] - 06-05-2026
- **Pin pad Sound Toggle**
- Beep is ON by default
- Can Toggle PinPad sound on Side Navigation ( Under SystemManagement Tab)
- **Transaction Search**
- Search now matches by both Trace No and RRN instead of Trace No only
- Trace No uses partial match (`contains`), RRN uses exact match (`equals`)
## [2.31] - 22-05-2026
- **Control Bar Disabled**
- Control Bar disabled in normal status and could not be down to go settings
- But can auto enable when password is correct in function tab
- **Void Fixed**
- Void transaction fixed
## [2.34] - 29-05-2026
- **General**
- Settlement fix for qr records missing after Card settlement run
- fixed receipt printing loop for auto settlement
-
- **MMQR Refund**
- new auto-retry when MMQR status is "REFUNDING" in response
- no more fail records on refund list if "DUPLICATED" response
- removed "CANCEL" records in MMQR History
-
- **CARD Payments**
- signature saved in pos device
- signature re-show on re-printing receipt
- signature re-show on void
- signature re-show on refund
- pre-auth, pre-auth can, pre-auth com s' manual entry flow are changed
- can show/hide manual entry in all transactions
## [2.35] - 29-05-2026
- app crash fix
## [2.36] - 29-05-2026
- local database migration
## [2.37] - 06-07-2026
- **General**
- E-receipt send to backend service
- One Click Settlement
## [2.38] - 06-07-2026
- **General**
- SETTLEMENT both in one click
- showing each transaction detail when SETTLE
-
## [2.39] - 19-07-2026
- **General**
- New E-receipt for settlement
## [2.39] -
- **General**
- show total for each currency for duel currency
- void, pre-auth, cash adv, refund can now control from TMS for paper receipt
## [2.40]
- 1. QR Host
When we generate QR , this transaction not successful.
But this transaction included as success transaction in summary report and history.
Please remove "CANCEL" records in summary report and history.
- 2. Card Host
Settlement Screen
- 3. KBZ Host MMK - 3000 (Not include in total net amount for void , preauth , preauth cancel)
Sale - 2000
Void - 1000
Preauth - 2500
Preauth cancel - 500
Preauth complete - 2000
- 4. KBZ Host USD - 3000 (Not include in total net amount for void , preauth , preauth cancel)
Sale - 2000
Void - 1000
Preauth - 2500
Preauth cancel - 500
Preauth complete - 2000
- 5. MMQR Pay - 3000 (Not include in total net amount for refund transaction and cancel transaction)
QR pay - 4000
Refund - 1000
- 6. Reprint Last Settlement Report
Same process with settlement
## [2.41]
- clear batch time fix
- removed mock qr button
- support Id fix for signature

View File

View File

@ -14,54 +14,32 @@ android {
applicationId "com.utsmm.kbz"
minSdk 24
targetSdk 33
versionCode 44
versionName "2.39"
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"
versionCode 31
versionName "2.11"
}
uat {
dimension "env"
applicationId "com.utsmm.kbz.uat"
versionNameSuffix "-uat"
resValue "string", "app_name", "KBZ-UAT"
versionCode 46
versionName "2.41"
}
prod {
dimension "env"
applicationId "com.utsmm.kbz"
versionNameSuffix ""
resValue "string", "app_name", "KBZ-POS"
versionCode 6
versionName "2.3.1"
}
}
// Configure CMake
// externalNativeBuild {
// cmake {
// path "src/main/cpp/CMakeLists.txt"
// version "3.22.1"
// }
// }
buildTypes {
release {
minifyEnabled true
shrinkResources true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
@ -79,11 +57,6 @@ android {
buildConfig = true
}
lint {
abortOnError false
checkReleaseBuilds false
}
packagingOptions {
pickFirst '**/libnative-lib.so'
pickFirst '**/libxgd_ddi_jni.so'
@ -111,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"
@ -192,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'
@ -208,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
@ -238,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"
}

247
app/proguard-rules.pro vendored
View File

@ -20,250 +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 javax.lang.model.element.Modifier
-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,18 +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" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<!-- android:noHistory="true"-->
<!-- android:excludeFromRecents="true"-->
@ -59,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,41 +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.utsmm.kbz.util.LocationUtil;
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.util.enums.SettlementType;
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;
@ -59,12 +40,14 @@ import com.utsmm.kbz.ui.navigation.NaviMainFragment;
import com.utsmm.kbz.ui.navigation.NaviSetupFragment;
import com.utsmm.kbz.util.ecr.CoreUtils;
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;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
@ -73,7 +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
*/
@ -113,9 +95,6 @@ public class MainActivity extends AppCompatActivity implements
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
// Keep screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@ -145,41 +124,10 @@ 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.kbzbank.com/sirius");
// SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms.kbzbank.com/receipt");
// SystemParamsOperation.getInstance().setTmsAddress("https://api-tms-uat.kbzbank.com:8443/sirius");
// SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms-uat.kbzbank.com:8443/receipt");
SystemParamsOperation.getInstance().setTmsAddress("https://sirius-nest.utsmyanmar.com/api/v1");
SystemParamsOperation.getInstance().setEReceiptAddress("https://receipt-nest.utsmyanmar.com");
// 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);
sharedViewModel.getToastMsg().observe(this, this::showToast);
}
private void setupUI() {
@ -292,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,77 +379,23 @@ public class MainActivity extends AppCompatActivity implements
@Override
public void onResume() {
super.onResume();
getLocation();
SystemParamsOperation.getInstance().setSetupEcr(false);
SystemParamsOperation.getInstance().setDownloadedParams(false);
handleAutoSettlementIntent(getIntent());
// BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
}
@Override
public void onStop(){
super.onStop();
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
handleAutoSettlementIntent(intent);
}
public void getLocation() {
LocationUtil.getCurrentLocation(MainActivity.this, new LocationUtil.LocationCallback() {
@Override
public void onSuccess(double lat, double lng) {
LogUtil.d("Location", "Current Location: " + lat + ", " + lng);
LocationUtil.setLat(lat);
LocationUtil.setLng(lng);
}
@Override
public void onError(String reason) {
LogUtil.e("Location", "get Location error: " + reason);
LocationUtil.setLat(0.00);
LocationUtil.setLng(0.00);
}
});
}
private void handleAutoSettlementIntent(Intent intent) {
if (intent == null) return;
boolean hasAutoSettle = intent.getBooleanExtra("AUTO_SETTLEMENT", false);
if (!hasAutoSettle) return;
intent.removeExtra("AUTO_SETTLEMENT");
sharedViewModel.settlementType.setValue(SettlementType.NORMAL);
sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT);
sharedViewModel.setTransMenu(TransMenu.SETTLEMENT);
sharedViewModel.autoSettle.setValue(true);
try {
navController.navigate(R.id.settlementTransactionFragment);
} catch (Exception e) {
LogUtil.e(TAG, "Navigation error: " + e.getMessage());
}
}
@Override
public void onDestroy() {
super.onDestroy();
// Clean up RxJava disposables
compositeDisposable.clear();
// Reset screen mode
// Disconnect ECR
ECRHelper.INSTANCE.disconnect();
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
}
// Navigation drawer interaction listeners
@ -512,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();
@ -608,4 +496,4 @@ public class MainActivity extends AppCompatActivity implements
private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
}
}

File diff suppressed because it is too large Load Diff

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
@ -128,8 +123,8 @@ public class MainViewModel extends ViewModel {
public LiveData<List<PayDetail>> getDeleteTrans() {
return repository.getDeleteTrans();
public LiveData<List<PayDetail>> getDeleteTrans(String batchNo) {
return repository.getDeleteTrans(batchNo);
}
private LiveData<List<PayDetail>> getPreAuthTrans() {
@ -171,7 +166,7 @@ public class MainViewModel extends ViewModel {
settlementPOS.postValue(payDetails);
}
});
getDeleteTrans().observeForever(new Observer<List<PayDetail>>() {
getDeleteTrans(SystemParamsOperation.getInstance().getCurrentBatchNum()).observeForever(new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetails) {
deleteTrans.postValue(payDetails);

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,135 +0,0 @@
package com.utsmm.kbz.service;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import com.utsmm.kbz.MainActivity;
import com.utsmm.kbz.BuildConfig;
import com.utsmm.kbz.R;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import dagger.hilt.android.AndroidEntryPoint;
@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";
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);
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
);
channel.setDescription("Auto settlement background service");
notificationManager.createNotificationChannel(channel);
}
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(false)
.setAutoCancel(false);
startForeground(1002, builder.build());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtil.d(TAG, "<<<<<<<<<<<<<<< Auto Settlement Service Started >>>>>>>>>>>>>>>>.");
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
startForegroundService();
}
if (SystemParamsOperation.getInstance().getSettlementStatus()) {
launchSettlementFragment();
} 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 launchSettlementFragment() {
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);
launchIntent.putExtra("AUTO_SETTLEMENT", true);
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")
.setContentText("Tap to view settlement and print receipt")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setFullScreenIntent(pendingIntent, true);
notificationManager.notify(2001, builder.build());
startActivity(launchIntent);
} catch (Exception e) {
LogUtil.e(TAG, "Error launching settlement: " + e.getMessage());
e.printStackTrace();
}
}
@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();
}
}

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,26 +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.MainActivity;
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.BaseApplication;
import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusError;
@ -32,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;
@ -60,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
@ -71,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());
}
@ -101,24 +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");
BaseApplication.getInstance().deviceEngine.getPlatform().enableControlBar();
try {
setToolBarTitleWithBackIcon("Settings");
LogUtil.d(TAG, "Settings screen resumed");
} catch (Exception e) {
LogUtil.e(TAG, "Error in onResume: " + e.getMessage());
}
}
@ -150,25 +144,22 @@ 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 isVisible = SystemParamsOperation.getInstance().getAutoReversalEnable();
LogUtil.d("SettingsFragment", "isVisible " + isVisible);
binding.reversalCard.setVisibility(isVisible ? View.VISIBLE : View.GONE);
private void updateReversalSettings() {
boolean isEnabled = SystemParamsOperation.getInstance().isReversalOn();
binding.reversalSwitch.setChecked(isEnabled);
binding.reversalSummary.setText(isEnabled ?
@ -178,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() {
@ -192,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 {
@ -212,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();
@ -303,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) {
@ -323,28 +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 onClearReversalClick() {
try {
sharedViewModel.transactionsType.postValue(TransactionsType.CLEAR_REVERSAL);
sharedViewModel.setTransMenu(TransMenu.CLEAR_REVERSAL);
Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)
.navigate(R.id.inputPasswordFragment);
} catch (Exception e) {
LogUtil.e(TAG, "Error in clear reversal click: " + e.getMessage());
}
}
public void onTmsConfigClick() {
try {
LogUtil.d(TAG, "TMS Config clicked");
@ -411,9 +365,6 @@ public class SettingsFragment extends DataBindingFragment {
private void downloadParams(String lastTransName, String lastTransTime) {
try {
LogUtil.d(TAG, "Downloading params for transaction: " + lastTransName);
((MainActivity) requireActivity()).getLocation();
SiriusRequest siriusReq = TMSUtil.getInstance().generateRequestParams(getContext(), lastTransName, lastTransTime);
mainViewModel.getParams(siriusReq)
@ -483,4 +434,4 @@ public class SettingsFragment extends DataBindingFragment {
showDeclineDialog(getResourceString(R.string.txt_error_occurred));
}
}
}
}

View File

@ -2,10 +2,7 @@ package com.utsmm.kbz.ui.adapters;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PorterDuff;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
@ -265,19 +262,6 @@ public class MyBindingAdapter {
imageView.setImageBitmap(bitmap);
}
@BindingAdapter("signatureBlob")
public static void setSignatureFromBlob(ImageView imageView, byte[] blob) {
if (blob != null && blob.length > 0) {
Bitmap bitmap = BitmapFactory.decodeByteArray(blob, 0, blob.length);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
imageView.setVisibility(View.VISIBLE);
return;
}
}
imageView.setVisibility(View.GONE);
}
@BindingAdapter({"mmpayData"})
public static void setMMPayQRCode(AppCompatImageView imageView,String data) {
//250
@ -310,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,50 +106,11 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
public void onClickManualEntry() {
// showSingleInfoDialogAutoHide("Coming Soon!");
routeId = R.id.action_cardWaitingFragment_to_manualEntryFragment;
safeNavigateToRouteId();
}
public void onClickTap() {
cardReadViewModel.setCardTransactionType(CardTransactionType.MOCK);
routeId = R.id.action_cardWaitingFragment_to_processingCardFragment;
safeNavigateToRouteId();
}
}
private void updateManualEntryVisibility() {
TransactionsType type = sharedViewModel.transactionsType.getValue();
boolean manualEntryStatus = SystemParamsOperation.getInstance().getManualEntryStatus();
boolean preAuthManualEntryStatus = SystemParamsOperation.getInstance().getPreAuthManualEnabled();
boolean preAuthCompManualEntryStatus = SystemParamsOperation.getInstance().getPreAuthCompleteManualEnabled();
boolean preAuthCancelManualEntryStatus = SystemParamsOperation.getInstance().getPreAuthVoidManualEnabled();
boolean show;
if (type == null) {
show = manualEntryStatus;
} else {
switch (type) {
case SALE:
case CASH_OUT:
case CASH_DEPOSIT:
case REFUND:
case VOID:
show = manualEntryStatus;
break;
case PRE_AUTH_SALE:
show = preAuthManualEntryStatus;
break;
case PRE_AUTH_VOID:
show = preAuthCancelManualEntryStatus;
break;
case PRE_AUTH_COMPLETE:
show = preAuthCompManualEntryStatus;
break;
default:
show = false;
break;
}
}
sharedViewModel.setManualEntryStatus(show);
}
@Override
@ -170,8 +119,6 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
resetUI();
updateManualEntryVisibility();
setToolBarTitleWithBackIcon(getResourceString(R.string.txt_title_card_capture));
delayFunctionCall(()-> {
@ -185,15 +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 if(sharedViewModel.getIsContactlessRestricted().getValue() != null && sharedViewModel.getIsContactlessRestricted().getValue()) {
cardReadViewModel.setCheckCardAlertMsg("Tap not allowed!",false);
setupCardReadProcess(true);
} else {
setupCardReadProcess(false);
}
@ -205,8 +143,6 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
super.onPause();
sharedViewModel.setIsFallback(false);
sharedViewModel.setIsSeePhone(false);
sharedViewModel.setIsContactlessRestricted(false);
// cardReadViewModel.cancelCheckCard();
@ -278,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();
//
//
@ -293,33 +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 if(!SystemParamsOperation.getInstance().isNfcEnabled()) {
allType.add(CardSlotTypeEnum.ICC1);
allType.add(CardSlotTypeEnum.SWIPE);
} else if(sharedViewModel.getIsContactlessRestricted().getValue() != null && sharedViewModel.getIsContactlessRestricted().getValue()) {
allType.add(CardSlotTypeEnum.ICC1);
// allType.add(CardSlotTypeEnum.SWIPE);
} else {
allType.add(CardSlotTypeEnum.ICC1);
allType.add(CardSlotTypeEnum.RF);
if(SystemParamsOperation.getInstance().isMagStripeEnabled()) {
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 *****");
@ -341,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);
@ -246,6 +234,7 @@ public class ConfirmTransactionFragment extends DataBindingFragment implements D
public void onConfirm(){
if (sharedViewModel.transactionsType.getValue() == TransactionsType.TIP_ADJUSTMENT) {
routeId = R.id.action_confirmTransactionFragment_to_inputTipAmountFragment;
safeNavigateToRouteId();
@ -269,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,86 +203,22 @@ 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;
case ON_NEXT_SCREEN:
navigateToRRNScreen();
break;
case INSERT_OR_MANUAL:
if(cardReadViewModel.cardTypeData.getValue() != null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.NFC.value) {
isCardTaped("Please insert or type card",new CardDetectCallback() {
@Override
public void onComplete() {
sharedViewModel.setIsContactlessRestricted(true);
navigateToCheckCard();
}
});
}
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:
@ -362,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);

View File

@ -201,7 +201,7 @@ public class InputRRNFragment extends DataBindingFragment {
private void checkRRNPreAuthVoid(boolean isECR) {
rrnViewModel.searchPayDetailPreCancel(cardNo,rrnNo).observe(getViewLifecycleOwner(), new Observer<PayDetail>() {
rrnViewModel.searchPayDetail(cardNo,rrnNo).observe(getViewLifecycleOwner(), new Observer<PayDetail>() {
@Override
public void onChanged(PayDetail payDetail) {
if(payDetail != null) {
@ -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()) {
@ -245,8 +243,6 @@ public class InputRRNFragment extends DataBindingFragment {
} else {
LogUtil.d(TAG,"PreAuth Cancel RRN not found!");
terminateProcess(isECR);
}
@ -315,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);
@ -481,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) {
@ -524,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;
@ -537,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);
@ -548,12 +533,11 @@ public class InputRRNFragment extends DataBindingFragment {
callNextScreen();
// } else {
// terminatedTransRefund(isECR);
// }
} else {
terminatedTransRefund(isECR);
}
} else {
// terminatedTransRefund(isECR);
PayDetail newPay = transProcessViewModel.getPayDetail();
newPay.setReferNo(rrnNo);
@ -570,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

@ -116,14 +116,7 @@ public class InputTraceNoFragment extends DataBindingFragment {
clearInputView();
TransactionsType currentTransType = sharedViewModel.transactionsType.getValue();
if (currentTransType == TransactionsType.VOID
|| currentTransType == TransactionsType.TIP_ADJUSTMENT
|| currentTransType == TransactionsType.PRE_AUTH_COMPLETE_VOID) {
setToolBarTitleWithBackIcon(getResourceString(R.string.title_invoice_number));
} else {
setToolBarTitleWithBackIcon(getResourceString(R.string.title_trace_number));
}
setToolBarTitleWithBackIcon(getResourceString(R.string.title_trace_number));
if (sharedViewModel.isEcr.getValue() != null) {
if (sharedViewModel.isEcr.getValue()) {
@ -158,9 +151,10 @@ public class InputTraceNoFragment extends DataBindingFragment {
configTime = "23:00";
}
LogUtil.d(TAG,"Input invoice :"+traceNo);
LogUtil.d(TAG,"Input trace :"+traceNo);
voidViewModel.getVoidTransByInvoice(transType, POSUtil.getInstance().formatTrace(traceNo)).observe(getViewLifecycleOwner(), new Observer<PayDetail>() {
// voidViewModel.getGenericVoidTransactions(transType,POSUtil.getInstance().formatTrace(traceNo),isEmv).observe(getViewLifecycleOwner(), new Observer<PayDetail>() {
voidViewModel.getVoidTrans(transType,POSUtil.getInstance().formatTrace(traceNo)).observe(getViewLifecycleOwner(), new Observer<PayDetail>() {
@Override
public void onChanged(PayDetail payDetail) {
@ -170,7 +164,7 @@ public class InputTraceNoFragment extends DataBindingFragment {
LogUtil.d(TAG,"transactions trace :"+payDetail.getVoucherNo());
// if(POSUtil.getInstance().checkVoid(configTime,date,time)) {
if(POSUtil.getInstance().checkVoid(configTime,date,time)) {
if(payDetail.getIsCanceled()) {
clearInputView();
@ -179,27 +173,19 @@ public class InputTraceNoFragment extends DataBindingFragment {
}
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount()));
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());
emvTransactionProcessViewModel.setPayDetail(payDetail);
}
safeNavigateToRouteId();
// }
}
} else {
if (isEcr)
@ -313,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,65 +102,38 @@ 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...");
sharedViewModel.isEmv.setValue(false);
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;
}
}
sharedViewModel.isEmv.setValue(false);
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.getTransMenu().getValue() == TransMenu.PRE_AUTH_PARTIAL_VOID ) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_function_not_supported));
routeId = R.id.action_processingCardFragment_to_errorFragment;
}
// else if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND) {
// sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_card_not_supported));
// routeId = R.id.action_processingCardFragment_to_errorFragment;
//
// }
sharedViewModel.setCardDataExist(true);
if(sharedViewModel.getTransMenu().getValue() != TransMenu.PRE_AUTH_FULL_VOID
&& sharedViewModel.getAmountExist().getValue() != null
&& !sharedViewModel.getAmountExist().getValue()) {
if(sharedViewModel.getAmountExist().getValue() != null && !sharedViewModel.getAmountExist().getValue()) {
routeId = R.id.action_processingCardFragment_to_inputAmountFragment;
}
@ -205,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*/
@ -229,6 +188,16 @@ public class ProcessingCardFragment extends DataBindingFragment {
transProcessViewModel.setTradeData(tradeData);
}
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;
// }
sharedViewModel.setCardDataExist(true);
if(sharedViewModel.getTransMenu().getValue() != TransMenu.PRE_AUTH_FULL_VOID && sharedViewModel.getAmountExist().getValue() != null && !sharedViewModel.getAmountExist().getValue()) {
@ -254,11 +223,8 @@ public class ProcessingCardFragment extends DataBindingFragment {
emvTransactionViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
if (SystemParamsOperation.getInstance().isEmvEnabled()) {
prepareEmvTransaction();
routeId = R.id.action_processingCardFragment_to_emvTransactionFragment;
} else {
routeId = R.id.action_processingCardFragment_to_errorFragment;
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_please_enable_emv));
@ -279,43 +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);
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 -> {
@ -325,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

@ -6,24 +6,12 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
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.model.TradeData;
import com.utsmyanmar.paylibs.print.PrintUtils;
import com.utsmyanmar.paylibs.reversal.ReversalAction;
import com.utsmyanmar.paylibs.reversal.ReversalListener;
import com.utsmyanmar.paylibs.system.BaseErrorCode;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
@ -36,10 +24,6 @@ import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmm.kbz.util.ecr.CoreUtils;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import java.text.DecimalFormat;
public class ProcessingFragment extends DataBindingFragment {
@ -113,17 +97,6 @@ public class ProcessingFragment extends DataBindingFragment {
setToolBarTitleWithoutBackIcon(getResourceString(R.string.title_processing));
checkReversal();
// disableNavigationBar();
getNavController(Constants.NAV_HOST_ID).addOnDestinationChangedListener(listener);
}
private void startTransactionProcess() {
if(isEmvTrans()) {
startTransactionProcess(emvTransactionProcessViewModel);
} else {
@ -131,55 +104,13 @@ public class ProcessingFragment extends DataBindingFragment {
}
sharedViewModel.loadingMsg(getResourceString(R.string.txt_sending));
// disableNavigationBar();
getNavController(Constants.NAV_HOST_ID).addOnDestinationChangedListener(listener);
}
private void checkReversal() {
observeOnce(sharedViewModel.getLastReversalTransaction(), payDetail -> {
if (payDetail != null) {
TradeData tradeData = new TradeData();
tradeData.setPayDetail(payDetail);
LogUtil.d(TAG, "Sending Reversal!");
sharedViewModel.loadingMsg(getResourceString(R.string.txt_sending_reversal));
ReversalAction.getInstance().setData(tradeData).enqueue().startReversal(new ReversalListener() {
@Override
public void onSuccessReversal() {
LogUtil.d(TAG, "Reversal Success!");
payDetail.setIsNeedReversal(false);
sharedViewModel.updatePayDetail(payDetail);
delayFunctionCall(()->startTransactionProcess());
}
@Override
public void onNetworkFail(String msg) {
LogUtil.d(TAG, "Reversal Network Fail!" + msg);
startTransactionProcess();
}
@Override
public void onFailReversal(String msg) {
LogUtil.d(TAG, "Reversal Fail!" + msg);
startTransactionProcess();
}
});
} else {
LogUtil.d(TAG,"No reversal found!");
startTransactionProcess();
}
});
}
private <T> void observeOnce(LiveData<T> liveData, Observer<T> observer) {
liveData.observe(getViewLifecycleOwner(), new Observer<T>() {
@Override
public void onChanged(T t) {
liveData.removeObserver(this);
observer.onChanged(t);
}
});
}
private boolean isEmvTrans() {
return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue();
}
@ -231,34 +162,20 @@ public class ProcessingFragment extends DataBindingFragment {
private void updateData(){
PayDetail payDetail;
if(isEmvTrans()) {
LogUtil.d(TAG,"Updated sharedViewmodel payDetail for emv");
payDetail = emvTransactionProcessViewModel.payDetailResult.getValue();
sharedViewModel.payDetail.setValue(emvTransactionProcessViewModel.payDetailResult.getValue());
} else {
LogUtil.d(TAG,"Updated sharedViewmodel payDetail for non emv");
payDetail = transProcessViewModel.payDetailResult.getValue();
}
sharedViewModel.payDetail.setValue(payDetail);
if (sharedViewModel.transactionsType.getValue() == TransactionsType.BALANCE_INQUIRY && payDetail != null) {
sharedViewModel.amount.setValue(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount()));
LogUtil.d(TAG,"amount :"+payDetail.getAmount());
sharedViewModel.payDetail.setValue(transProcessViewModel.payDetailResult.getValue());
}
// if(sharedViewModel.transactionsType.getValue() == TransactionsType.BALANCE_INQUIRY) {
// sharedViewModel.amount.setValue(Objects.requireNonNull(sharedViewModel.payDetail.getValue()).amount + "");
// }
// 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 {
@ -286,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
@ -329,43 +246,15 @@ public class ProcessingFragment extends DataBindingFragment {
safeNavigateToRouteId();
}
private void handleAfterTransaction() {
if (SystemParamsOperation.getInstance().getDemoStatus()) {
delayFunctionCall(() -> {
sharedViewModel.dismissLoadingMsg();
callNextScreen();
}, 1500);
} else {
sharedViewModel.dismissLoadingMsg();
callNextScreen();
}
}
private void observeData(ProcessingTransaction processingTransaction) {
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, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
handleAfterTransaction();
break;
case SUCCESS:
// sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
// handleAfterTransaction();
if(requiresSignature()){
handleAfterTransaction();
}else{
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
handleAfterTransaction();
}
break;
case OFFLINE_SUCCESS:
LogUtil.d(TAG,"This was called!");
if(SystemParamsOperation.getInstance().getDemoStatus()) {
delayFunctionCall(()->{
// updateData();
@ -374,14 +263,12 @@ public class ProcessingFragment extends DataBindingFragment {
},1500);
} else {
// updateData();
sharedViewModel.dismissLoadingMsg();
callNextScreen();
}
break;
case OFFLINE_FAILURE:
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, false, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
sharedViewModel.dismissLoadingMsg();
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_offline_failure));
navigateToError();
@ -479,126 +366,4 @@ public class ProcessingFragment extends DataBindingFragment {
});
}
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 String formatDE43(String value) {
if (value == null) value = "";
if (value.length() > 40) {
return value.substring(0, 40);
}
return String.format("%-40s", value); // right pad with space
}
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);
String rawName = PrintUtils.getInstance()
.getCardHolderName(payDetail.getCardHolderName());
String secondLine = PrintUtils.getInstance()
.processNameSpaceSecondLine(rawName);
String firstLine = PrintUtils.getInstance()
.processNameSpaceFirstLine(rawName, secondLine);
String cardHolderName = firstLine +
(secondLine.isEmpty() ? "" : " " + secondLine);
EReceiptCardRequest request = new EReceiptCardRequest();
request.setDE2(PrintUtils.getInstance().maskCardNumberPciDss(payDetail.getCardNo()));
request.setDE3(mapTransactionType(payDetail.getTransactionType()));
request.setDE4(amount);
request.setDE7(currentTimestamp);
request.setDE11(payDetail.getVoucherNo());
// request.setDE22(mapTransactionType(payDetail.getTransactionType()));
request.setDE22(PrintUtils.getInstance().getEntryType(payDetail.getCardType()));
request.setDE37(payDetail.getReferNo());
request.setDE38(payDetail.getApprovalCode());
request.setDE39(isSuccess ? "A" : "E");
request.setDE41(terminalId);
request.setDE42(merchantId);
request.setHostId(SystemParamsOperation.getInstance().getHostId());
request.setDE49(mapCurrency(payDetail.getCurrencyCode()));
request.setSerial(serial);
request.setInvoiceNumber(payDetail.getInvoiceNo());
request.setAppId(appId);
request.setDescription(reason);
request.setBatchNumber(payDetail.batchNo);
request.setDE55(payDetail.getAppLabel());
request.setCardLabel(payDetail.getAccountType());
request.setDE14(PrintUtils.getInstance().getFormatExpDate(payDetail.getEXPDate()));
request.setDE43(formatDE43(cardHolderName));
request.setDE48(payDetail.getAID());
request.setDE115("");
return request;
}
}

View File

@ -9,21 +9,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.github.gcacace.signaturepad.views.SignaturePad;
import com.utsmm.kbz.util.helper.EReceiptHelper;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptCardRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
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.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.print.printx.PrintX;
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.system.BaseErrorCode;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.print_utils.BitmapUtils;
public class SignatureFragment extends DataBindingFragment {
@ -47,8 +40,8 @@ public class SignatureFragment extends DataBindingFragment {
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_signature_view, BR.vm, sharedViewModel)
.addBindingParam(BR.click, new ClickEvent());
return new DataBindingConfig(R.layout.fragment_signature_view, BR.vm,sharedViewModel)
.addBindingParam(BR.click,new ClickEvent());
}
@Override
@ -87,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 !");
}
});
}
@ -130,27 +125,11 @@ public class SignatureFragment extends DataBindingFragment {
setToolBarTitleWithoutBackIcon(getResourceString(R.string.signature_title));
}
private void callNextScreen() {
private void callNextScreen(){
routeId = R.id.action_signatureFragment_to_transactionResultFragment;
safeNavigateToRouteId();
}
private void updateData() {
PayDetail payDetail = sharedViewModel.payDetail.getValue();
payDetail.setESignHexData(BitmapUtils.bitmapToHexString(mSignaturePad.getSignatureBitmap()));
byte[] blob = BitmapUtils.bitmapToBytes(mSignaturePad.getSignatureBitmap());
payDetail.setESignBlob(blob);
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.updateESignBlob(payDetail.voucherNo, blob);
EReceiptCardRequest request = EReceiptHelper.buildEReceiptCardReceipt(
requireContext(),
payDetail,
true,
BaseErrorCode.getCode(payDetail.getTradeAnswerCode()),
null);
sharedViewModel.pushReceiptWithImage(request, blob);
}
public class ClickEvent {
@ -159,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 {
@ -169,15 +146,8 @@ public class SignatureFragment extends DataBindingFragment {
} else {
// Handle manual signature on paper
sharedViewModel.signBitmap = null; // No digital signature
PayDetail payDetail = sharedViewModel.payDetail.getValue();
EReceiptCardRequest request = EReceiptHelper.buildEReceiptCardReceipt(
requireContext(),
payDetail,
true,
BaseErrorCode.getCode(payDetail.getTradeAnswerCode()),
null);
sharedViewModel.pushReceipt(request);
LogUtil.d(TAG, "Manual signature on paper selected - receipt submitted without image");
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,10 +8,7 @@ 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.utsmm.kbz.MainActivity;
import com.utsmm.kbz.util.LocationUtil;
import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusError;
@ -29,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;
@ -46,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<>();
@ -96,6 +91,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
@Override
public void onStart() {
super.onStart();
}
@Override
@ -115,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));
@ -124,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));
@ -151,15 +146,11 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
PayDetail payDetail = sharedViewModel.payDetail.getValue();
if (payDetail == null) {
navigateToMainScreen();
return;
}
((MainActivity) requireActivity()).getLocation();
SiriusRequest siriusReq = TMSUtil.getInstance().generateRequestParams(
getContext(),
payDetail.getTransType(),
@ -168,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);
}
@ -198,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();
@ -259,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();
}
@ -332,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();
@ -351,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
@ -378,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;
@ -78,21 +77,13 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
break;
}
try {
LogUtil.d("EmvTransactionProcessViewModel", "mPayDetail" + mPayDetail.PINCipher);
LogUtil.d("EmvTransactionProcessViewModel", "is offline pin entered " + isOfflinePinEntered);
if ((mPayDetail.PINCipher != null && !mPayDetail.PINCipher.isEmpty())) {
LogUtil.d("EmvTransactionProcessViewModel", "condition 1");
if (mPayDetail.PINCipher != null && !mPayDetail.PINCipher.isEmpty()) {
emvHandler.onSetPinInputResponse(true, false);
} else if(isOfflinePinEntered){
LogUtil.d("EmvTransactionProcessViewModel", "condition 2");
} else if (isOfflinePinEntered) {
emvHandler.onSetPinInputResponse(true, false);
}else {
LogUtil.d("EmvTransactionProcessViewModel", "condition 3");
emvHandler.onSetPinInputResponse(true, true);
} else {
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);
}
@ -170,13 +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_INSERT_OR_MANUAL:
emvResultStatus.postValue(EmvResultStatus.INSERT_OR_MANUAL);
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);
@ -190,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;
}
}
@ -225,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);
@ -287,11 +264,7 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
/*Jun 15 2022*/
PayDetail payDetailRes = tradeData.getPayDetail();
if (transType.getValue() == TransactionsType.VOID) {
payDetailRes.setInvoiceNo(mPayDetail.getInvoiceNo());
} else {
payDetailRes.setInvoiceNo(SystemParamsOperation.getInstance().getIncrementInvoiceNum());
}
payDetailRes.setInvoiceNo(SystemParamsOperation.getInstance().getIncrementInvoiceNum());
LogUtil.d(TAG,"Transaction Operation Success: "+payDetailRes.getTradeAnswerCode());
LogUtil.d(TAG,"Transaction Type: "+payDetailRes.getTransactionType());
@ -315,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 {
@ -324,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
@ -392,16 +361,13 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
@Override
public void startDemoProcess() {
if (transType.getValue() != TransactionsType.VOID) {
SystemParamsOperation.getInstance().getIncrementInvoiceNum();
}
SystemParamsOperation.getInstance().getIncrementInvoiceNum();
PayDetail payDetailRes;
if (transType.getValue() == TransactionsType.VOID) {
payDetailRes = DemoUtil.getInstance().builtDemoVoid(mPayDetail);
payDetailRes.setInvoiceNo(mPayDetail.getInvoiceNo());
processVoidDB(payDetailRes);
} else if (transType.getValue() == TransactionsType.REFUND) {
@ -459,14 +425,13 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
public void processVoidDB(PayDetail payResult) {
mPayDetail.setIsCanceled(true);
updatePayDetail(mPayDetail);
payResult.setESignBlob(mPayDetail.getESignBlob());
repository.insertPayDetail(updateCurrentDateAndTime(payResult));
}
@Override
public void processPreVoidDb(PayDetail payResult) {
oldTransPayDetail.setIsCanceled(true);
updatePayDetail(oldTransPayDetail);
mPayDetail.setIsCanceled(true);
updatePayDetail(mPayDetail);
repository.insertPayDetail(updateCurrentDateAndTime(payResult));
}
@ -480,11 +445,9 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
if(oldTransPayDetail.getAmount() == payResult.getAmount()) {
oldTransPayDetail.setIsCanceled(true);
oldTransPayDetail.setAdjust(true);
updatePayDetail(oldTransPayDetail);
} else {
oldTransPayDetail.setIsCanceled(false);
oldTransPayDetail.setAdjust(true);
updatePayDetail(oldTransPayDetail);
}
repository.insertPayDetail(updateCurrentDateAndTime(payResult));
@ -529,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

@ -41,12 +41,6 @@ public class InputRRNViewModel extends ViewModel {
return repository.searchPayDetail(cardNo,rrn);
}
public LiveData<PayDetail> searchPayDetailPreCancel(String cardNo,String rrn) {
return repository.searchPayDetailPreCancel(cardNo,rrn);
}
public NumberKeyboard.KeyClickCallback onKeyClick(){
return new NumberKeyboard.KeyClickCallback() {

View File

@ -1,28 +1,18 @@
package com.utsmm.kbz.ui.core_viewmodel;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.Looper;
import android.util.Log;
import android.widget.ListView;
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.EReceiptCardRequest;
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;
@ -36,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
@ -70,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<>();
@ -121,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<>();
@ -132,8 +113,6 @@ public class SharedViewModel extends ViewModel {
public MutableLiveData<Boolean> _manualEntryStatus = new MutableLiveData<>();
public MutableLiveData<Boolean> autoSettle = new MutableLiveData<>(false);
public MutableLiveData<Boolean> fullVoidPreauthStatus = new MutableLiveData<>();
public MutableLiveData<Boolean> partialVoidPreauthStatus = new MutableLiveData<>();
@ -169,13 +148,8 @@ public class SharedViewModel extends ViewModel {
public MutableLiveData<Integer> loadingView = new MutableLiveData<>(8);
public SingleLiveEvent<String> loadingMsg = new SingleLiveEvent<>();
private final SingleLiveEvent<String> toastMsg = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isFallback = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isSeePhone = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isContactlessRestricted = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isCardAppBlock = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> _isCardDataExist = new SingleLiveEvent<>();
@ -183,19 +157,13 @@ 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);
}
@ -203,9 +171,7 @@ public class SharedViewModel extends ViewModel {
isEmv.setValue(status);
}
public SingleLiveEvent<Boolean> isEmvTrans() {
return isEmv;
}
public SingleLiveEvent<Boolean> isEmvTrans() { return isEmv;}
private PayDetail getPayDetail() {
return mPayDetail;
@ -219,100 +185,26 @@ public class SharedViewModel extends ViewModel {
printReceiptButtons.postValue(value);
}
public void setTransactionsType(TransactionsType transactionsType) {
this.transactionsType.setValue(transactionsType);
}
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); }
public SingleLiveEvent<TransactionsType> getTransactionsType() {
return transactionsType;
}
public SingleLiveEvent<PrintStatus> getPrintStatus() { return this.printStatus; }
public void setAmount(String amount) {
this.amount.setValue(amount);
}
public void setIsFallback(boolean status) { isFallback.setValue(status);}
public SingleLiveEvent<String> getAmount() {
return amount;
}
public SingleLiveEvent<Boolean> getIsFallback() { return isFallback;}
public void setPrintReceiptMsg(String msg) {
this.printReceiptMsg.setValue(msg);
}
public void setCardDataExist(boolean exist) { _isCardDataExist.setValue(exist);}
public void postPrintReceiptMsg(String msg) {
this.printReceiptMsg.postValue(msg);
}
public SingleLiveEvent<Boolean> getCardDataExist() { return _isCardDataExist; }
public void setPrintStatus(PrintStatus printStatus) {
// this.printStatus.postValue(printStatus);
if (Looper.myLooper() == Looper.getMainLooper()) {
this.printStatus.setValue(printStatus);
} else {
this.printStatus.postValue(printStatus);
}
public void setAmountExist(boolean exist) { _isAmountExist.setValue(exist);}
}
public void postPrintStatus(PrintStatus printStatus) {
this.printStatus.postValue(printStatus);
}
public SingleLiveEvent<PrintStatus> getPrintStatus() {
return this.printStatus;
}
public void setIsFallback(boolean status) {
isFallback.setValue(status);
}
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 setIsContactlessRestricted(boolean status) {
isContactlessRestricted.setValue(status);
}
public SingleLiveEvent<Boolean> getIsContactlessRestricted() {
return isContactlessRestricted;
}
public void setCardDataExist(boolean exist) {
_isCardDataExist.setValue(exist);
}
public SingleLiveEvent<Boolean> getCardDataExist() {
return _isCardDataExist;
}
public void setAmountExist(boolean exist) {
_isAmountExist.setValue(exist);
}
public SingleLiveEvent<Boolean> getAmountExist() {
return _isAmountExist;
}
public SingleLiveEvent<Boolean> getAmountExist() { return _isAmountExist; }
public MutableLiveData<Boolean> getManualEntryStatus() {
return _manualEntryStatus;
}
public MutableLiveData<Boolean> getManualEntryStatus() { return _manualEntryStatus;}
public void setManualEntryStatus(boolean status) {
_manualEntryStatus.setValue(status);
@ -330,18 +222,11 @@ public class SharedViewModel extends ViewModel {
return _successFragmentMsg;
}
public void set_currencyText(String msg) {
this._currencyText.setValue(msg);
}
public void set_currencyText(String msg) { this._currencyText.setValue(msg);}
public SingleLiveEvent<String> get_currencyText() {
return _currencyText;
}
public void set_successFragmentMsg(String msg) {
this._successFragmentMsg.setValue(msg);
}
public SingleLiveEvent<String> get_currencyText() { return _currencyText; }
public void set_successFragmentMsg(String msg) { this._successFragmentMsg.setValue(msg);}
public SingleLiveEvent<TransMenu> getTransMenu() {
return _transMenu;
}
@ -361,28 +246,19 @@ public class SharedViewModel extends ViewModel {
loadingMsg.setValue("");
}
public SingleLiveEvent<String> getToastMsg() {
return toastMsg;
}
public void postToastMsg(String msg) {
toastMsg.postValue(msg);
}
public Observable<SiriusResponse> getParams(SiriusRequest siriusRequest) {
return repository.getParams(siriusRequest);
}
private void printReceipt(boolean isMerchantCopy) {
PrintXReceipt.getInstance().printSmileReceipt(payDetail.getValue(), isMerchantCopy, new PrintXStatus() {
@Override
public void onSuccess() {
if (isMerchantCopy) {
if(isMerchantCopy) {
if (!SystemParamsOperation.getInstance().getDemoStatus()) {
if (SystemParamsOperation.getInstance().getPrintISOStatus()) {
if(!SystemParamsOperation.getInstance().getDemoStatus()) {
if(SystemParamsOperation.getInstance().getPrintISOStatus()) {
PrintXReceipt.getInstance().printSmileISoReceipt(payDetail.getValue());
}
}
@ -396,7 +272,7 @@ public class SharedViewModel extends ViewModel {
@Override
public void onFailure() {
LogUtil.d(TAG, "Print Status Result Failure!");
LogUtil.d(TAG,"Print Status Result Failure!");
printXStatus.postValue(PrintStatus.EMPTY_PAPER_ROLL);
printReceiptButtons.postValue(0);
}
@ -404,34 +280,35 @@ public class SharedViewModel extends ViewModel {
}
public void startPrintReceipt(boolean isFirstPrint) {
/*
* First Print is Merchant Copy..
* */
if (payDetail.getValue() != null) {
if(payDetail.getValue() != null) {
setPayDetail(payDetail.getValue());
}
LogUtil.d(TAG, "PayDetail trade Answer Code :" + getPayDetail().getTradeAnswerCode());
LogUtil.d(TAG,"PayDetail trade Answer Code :"+getPayDetail().getTradeAnswerCode());
LogUtil.d(TAG, "PayDetail trade Answer Code :" + payDetail.getValue().getTradeAnswerCode());
LogUtil.d(TAG,"PayDetail trade Answer Code :"+payDetail.getValue().getTradeAnswerCode());
PrintXReceipt.getInstance().printSmileReceipt(getPayDetail(), isFirstPrint, new PrintXStatus() {
@Override
public void onSuccess() {
if (isFirstPrint) {
if(isFirstPrint) {
if (!SystemParamsOperation.getInstance().getDemoStatus()) {
if (SystemParamsOperation.getInstance().getPrintISOStatus()) {
if(!SystemParamsOperation.getInstance().getDemoStatus()) {
if(SystemParamsOperation.getInstance().getPrintISOStatus()) {
PrintXReceipt.getInstance().printSmileISoReceipt(getPayDetail());
}
}
postPrintStatus(PrintStatus.FIRST_PRINT_DONE);
if (isEcr.getValue() != null &&
if(isEcr.getValue() != null &&
isEcr.getValue() &&
SystemParamsOperation.getInstance().isAutoPrintCustomerCopy()) {
printReceiptButtons.postValue(8);
@ -446,7 +323,7 @@ public class SharedViewModel extends ViewModel {
@Override
public void onFailure() {
LogUtil.d(TAG, "Print Status Result Failure!");
LogUtil.d(TAG,"Print Status Result Failure!");
if (isFirstPrint) {
setPrintStatus(PrintStatus.EMPTY_PAPER_ROLL_FIRST);
} else {
@ -458,9 +335,10 @@ public class SharedViewModel extends ViewModel {
}
@SuppressWarnings("ConstantConditions")
public void startPrintProcess() {
LogUtil.d(TAG, "Print status :" + getPrintStatus().getValue());
LogUtil.d(TAG,"Print status :"+getPrintStatus().getValue());
switch (getPrintStatus().getValue()) {
case FIRST_PRINT:
@ -483,32 +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() {
public void startPrintProcessSettlement(PrintXStatus printXStatus) {
if(payDetail.getValue() == null) return;
if (payDetail.getValue() == null) return;
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(), new PrintXStatus() {
@Override
public void onSuccess() {
if (payDetails.getValue() != null && !payDetails.getValue().isEmpty()) {
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(), QRSettleData.convertFromPayDetail(payDetails.getValue()), printXStatus);
} else {
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(), printXStatus);
}
}
}
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);
}
@ -517,32 +386,19 @@ public class SharedViewModel extends ViewModel {
}
public LiveData<PayDetail> getReversalTransaction(String voucherNo) {
return repository.getReversalTransaction(voucherNo);
}
public LiveData<PayDetail> getLastReversalTransaction() {
return repository.getLastReversalTransaction();
}
public LiveData<List<PayDetail>> getAllReversalTransaction() {
return repository.getAllReversalTransactions();
}
public void updatePayDetail(PayDetail payDetail) {
public void updatePayDetail(PayDetail payDetail){
repository.updatePayDetail(payDetail);
}
public void updateESignBlob(String voucherNo, byte[] blob) {
repository.updateESignBlob(voucherNo, blob);
}
public void insertPayDetail(PayDetail payDetail) {
repository.insertPayDetail(payDetail);
}
public void insertPayDetail(PayDetail payDetail) { repository.insertPayDetail(payDetail); }
public void enableCardStatusIcon(boolean tapCard, boolean tapDevice, boolean insertCard, boolean swipeCard) {
public void enableCardStatusIcon(boolean tapCard,boolean tapDevice,boolean insertCard, boolean swipeCard) {
tapCardStatus.setValue(tapCard ? 1 : 0);
tapDeviceStatus.setValue(tapDevice ? 1 : 0);
insertCardStatus.setValue(insertCard ? 1 : 0);
@ -550,86 +406,4 @@ public class SharedViewModel extends ViewModel {
}
@SuppressLint("CheckResult")
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());
postToastMsg("E-Receipt saved successfully");
},
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());
postToastMsg("E-Receipt could not save!");
} catch (Exception e) {
e.printStackTrace();
postToastMsg("E-Receipt could not save!");
}
} else {
Log.e("E-Receipt", "Unexpected error => " + error.getMessage());
postToastMsg("E-Receipt could not save!");
}
}
);
}
@SuppressLint("CheckResult")
public void pushReceiptWithImage(EReceiptCardRequest request, byte[] imageBytes) {
Log.d("push receipt", new Gson().toJson(request));
repository.sendReceiptWithImage(request, imageBytes)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> {
Log.d("E-Receipt", "Success =>" + response.getMessage());
postToastMsg("E-Receipt saved successfully");
},
error -> {
if (error instanceof HttpException) {
HttpException httpEx = (HttpException) error;
try {
String errorJson = httpEx.response().errorBody().string();
Log.e("E-Receipt", "Raw error JSON => " + errorJson);
EReceiptResponse res = new Gson().fromJson(errorJson, EReceiptResponse.class);
Log.e("E-Receipt", "Parsed Error => " + res.getMessage());
postToastMsg("E-Receipt could not save!");
} catch (Exception e) {
e.printStackTrace();
postToastMsg("E-Receipt could not save!");
}
} else {
Log.e("E-Receipt", "Unexpected error => " + error.getMessage());
postToastMsg("E-Receipt could not save!");
}
}
);
}
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

@ -139,11 +139,7 @@ public class TransProcessViewModel extends ViewModel implements ProcessingTransa
LogUtil.d(TAG,"Transaction Operation Success: "+payDetailRes.getTradeAnswerCode());
if (TextUtils.equals(payDetailRes.getTradeAnswerCode(),RC_APPROVED_V1) || TextUtils.equals(payDetailRes.getTradeAnswerCode(),RC_APPROVED_V2)) {
if (transType.getValue() == TransactionsType.VOID) {
payDetailRes.setInvoiceNo(payDetail.getInvoiceNo());
} else {
payDetailRes.setInvoiceNo(SystemParamsOperation.getInstance().getIncrementInvoiceNum());
}
payDetailRes.setInvoiceNo(SystemParamsOperation.getInstance().getIncrementInvoiceNum());
LogUtil.d(TAG,"MPU Transaction type :"+transType.getValue());
@ -233,16 +229,13 @@ public class TransProcessViewModel extends ViewModel implements ProcessingTransa
@Override
public void startDemoProcess() {
if (transType.getValue() != TransactionsType.VOID) {
SystemParamsOperation.getInstance().getIncrementInvoiceNum();
}
SystemParamsOperation.getInstance().getIncrementInvoiceNum();
PayDetail payDetailRes;
if (transType.getValue() == TransactionsType.VOID) {
payDetailRes = DemoUtil.getInstance().builtDemoVoid(payDetail);
payDetailRes.setInvoiceNo(payDetail.getInvoiceNo());
processVoidDB(payDetailRes);
} else if (transType.getValue() == TransactionsType.REFUND) {
@ -299,7 +292,6 @@ public class TransProcessViewModel extends ViewModel implements ProcessingTransa
public void processVoidDB(PayDetail payResult) {
payDetail.setIsCanceled(true);
updatePayDetail(payDetail);
payResult.setESignBlob(payDetail.getESignBlob());
repository.insertPayDetail(updateCurrentDateAndTime(payResult));
}
@ -312,16 +304,13 @@ public class TransProcessViewModel extends ViewModel implements ProcessingTransa
}
@Override
public void processPreCompDb(PayDetail payResult) {
if(oldTransPayDetail.getAmount() == payResult.getAmount()) {
oldTransPayDetail.setIsCanceled(true);
oldTransPayDetail.setAdjust(true);
updatePayDetail(oldTransPayDetail);
} else {
oldTransPayDetail.setIsCanceled(false);
oldTransPayDetail.setAdjust(true);
updatePayDetail(oldTransPayDetail);
}
repository.insertPayDetail(updateCurrentDateAndTime(payResult));

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

@ -9,14 +9,12 @@ import com.utsmm.kbz.MainViewModel;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.CurrencySelectionHelper;
public class DashboardPreAuthBottomSheet extends DataBindingBottomSheetFragment {
private MainViewModel mainViewModel;
private SharedViewModel sharedViewModel;
private CurrencySelectionHelper currencySelectionHelper;
private static final int hostId = Constants.NAV_HOST_ID;
private int routeId;
@ -26,7 +24,6 @@ public class DashboardPreAuthBottomSheet extends DataBindingBottomSheetFragment
protected void initViewModel() {
mainViewModel = getFragmentScopeViewModel(MainViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
currencySelectionHelper = new CurrencySelectionHelper(this, sharedViewModel);
}
@Override
@ -55,11 +52,10 @@ public class DashboardPreAuthBottomSheet extends DataBindingBottomSheetFragment
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_SALE);
routeId = R.id.action_dashboardPreAuthBottomSheet_to_inputAmountFragment;
safeRouteTo(currentId, routeId, hostId);
});
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_SALE);
routeId = R.id.action_dashboardPreAuthBottomSheet_to_inputAmountFragment;
safeRouteTo(currentId,routeId,hostId);
}
}
@ -69,11 +65,10 @@ public class DashboardPreAuthBottomSheet extends DataBindingBottomSheetFragment
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_COMPLETE);
routeId = R.id.action_dashboardPreAuthBottomSheet_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_COMPLETE);
routeId = R.id.action_dashboardPreAuthBottomSheet_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
}
@ -91,8 +86,4 @@ public class DashboardPreAuthBottomSheet extends DataBindingBottomSheetFragment
}
}
}
private void showCurrencyChooserForCardFlow(Runnable onSelected) {
currencySelectionHelper.showCardCurrencyChooser(onSelected);
}
}

View File

@ -10,7 +10,6 @@ import com.utsmm.kbz.MainViewModel;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.CurrencySelectionHelper;
public class DashboardPreAuthCancelBottomSheet extends DataBindingBottomSheetFragment {
@ -18,7 +17,6 @@ public class DashboardPreAuthCancelBottomSheet extends DataBindingBottomSheetFra
private MainViewModel mainViewModel;
private SharedViewModel sharedViewModel;
private CurrencySelectionHelper currencySelectionHelper;
private int currentId = R.id.dashboardPreAuthCancelBottomSheet;
private int routeId;
@ -28,7 +26,6 @@ public class DashboardPreAuthCancelBottomSheet extends DataBindingBottomSheetFra
protected void initViewModel() {
mainViewModel = getFragmentScopeViewModel(MainViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
currencySelectionHelper = new CurrencySelectionHelper(this, sharedViewModel);
}
@Override
@ -64,13 +61,12 @@ public class DashboardPreAuthCancelBottomSheet extends DataBindingBottomSheetFra
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_FULL_VOID);
sharedViewModel.amount.postValue(null);
routeId = R.id.action_dashboardPreAuthCancelBottomSheet_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_FULL_VOID);
sharedViewModel.amount.postValue(null);
routeId = R.id.action_dashboardPreAuthCancelBottomSheet_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
}
@ -86,19 +82,14 @@ public class DashboardPreAuthCancelBottomSheet extends DataBindingBottomSheetFra
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_PARTIAL_VOID);
sharedViewModel.amount.postValue(null);
routeId = R.id.action_dashboardPreAuthCancelBottomSheet_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_PARTIAL_VOID);
sharedViewModel.amount.postValue(null);
routeId = R.id.action_dashboardPreAuthCancelBottomSheet_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
}
}
private void showCurrencyChooserForCardFlow(Runnable onSelected) {
currencySelectionHelper.showCardCurrencyChooser(onSelected);
}
}

View File

@ -2,25 +2,14 @@ package com.utsmm.kbz.ui.dashboard;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatButton;
import androidx.core.content.ContextCompat;
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.CurrencyType;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
@ -30,30 +19,19 @@ import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.config.data.model.Features;
import com.utsmm.kbz.ui.adapters.MainAdapter;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.CurrencySelectionHelper;
import com.utsmm.kbz.util.tms.TMSUtil;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
public class DashboardTransFragment extends DataBindingFragment {
private MainViewModel mainViewModel;
private SharedViewModel sharedViewModel;
private CurrencySelectionHelper currencySelectionHelper;
private ArrayList<Features> featuresList = new ArrayList<>();
MainAdapter mainAdapter;
private boolean cardPrimaryHostCached = false;
private String cardPrimaryHostName = "";
private String cardPrimaryTid = "";
private String cardPrimaryMid = "";
private String cardPrimaryIp = "";
private String cardPrimarySecIp = "";
private CurrencyType cardPrimaryCurrency = CurrencyType.MMK;
private static final int hostId = Constants.NAV_HOST_ID;
private int routeId;
@ -78,7 +56,6 @@ public class DashboardTransFragment extends DataBindingFragment {
protected void initViewModel() {
mainViewModel = getFragmentScopeViewModel(MainViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
currencySelectionHelper = new CurrencySelectionHelper(this, sharedViewModel);
}
@Override
@ -89,66 +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();
Boolean isBalanceInquiryEnabled = SystemParamsOperation.getInstance().getBalanceInquiryStatus();
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;
// case BALANCE_INQUIRY:
// if(isBalanceInquiryEnabled){
// featuresList.add(feature);
// }
// break;
default:
featuresList.add(feature);
break;
}
}
TMSUtil.getInstance().checkFeaturesList(requireActivity(),featuresList);
mainAdapter.notifyDataSetChanged();
}
@ -184,14 +103,8 @@ public class DashboardTransFragment extends DataBindingFragment {
case CASH_ADVANCE:
new DashboardTransFragment.ClickEvent().onClickCashAdvance();
break;
case CLEAR_REVERSAL:
new DashboardTransFragment.ClickEvent().onClickClearReversal();
break;
case DEVICE_CONFIG:
new DashboardTransFragment.ClickEvent().onClickDeviceConfig();
break;
case BALANCE_INQUIRY:
new DashboardTransFragment.ClickEvent().onClickBalanceInquiry();
case HISTORY:
new DashboardTransFragment.ClickEvent().onClickHistory();
break;
}
@ -212,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 {
@ -222,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);
@ -234,19 +147,18 @@ 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() {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.setTransactionsType(TransactionsType.REFUND);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
sharedViewModel.transactionsType.setValue(TransactionsType.REFUND);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickPreAuth () {
@ -255,38 +167,32 @@ public class DashboardTransFragment extends DataBindingFragment {
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_SALE);
routeId = R.id.action_dashboardTransFragment_to_inputAmountFragment;
safeRouteTo(currentId, routeId, hostId);
});
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_SALE);
routeId = R.id.action_dashboardTransFragment_to_inputAmountFragment;
safeRouteTo(currentId,routeId,hostId);
}
}
public void onClickPreAuthCancel () {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_FULL_VOID);
sharedViewModel.amount.postValue("0"); // null to 0
// sharedViewModel.amount.postValue(null);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_FULL_VOID);
sharedViewModel.amount.postValue(null);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickPreAuthComp () {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_COMPLETE);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
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);
@ -294,223 +200,18 @@ public class DashboardTransFragment extends DataBindingFragment {
public void onClickCashAdvance() {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.setTransactionsType(TransactionsType.CASH_OUT);
sharedViewModel.setTransMenu(TransMenu.CASH_OUT);
routeId = R.id.action_dashboardTransFragment_to_inputAmountFragment;
safeRouteTo(currentId, routeId, hostId);
});
sharedViewModel.transactionsType.setValue(TransactionsType.CASH_OUT);
routeId = R.id.action_dashboardTransFragment_to_inputAmountFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickBalanceInquiry() {
showCurrencyChooserForCardFlow(() -> {
sharedViewModel.setTransactionsType(TransactionsType.BALANCE_INQUIRY);
sharedViewModel.setTransMenu(TransMenu.BALANCE_INQUIRY);
routeId = R.id.action_dashboardTransFragment_to_cardWaitingFragment;
safeRouteTo(currentId, routeId, hostId);
});
public void onClickHistory() {
routeId = R.id.action_dashboardTransFragment_to_manageFunctionFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickClearReversal() {
sharedViewModel.transactionsType.postValue(TransactionsType.CLEAR_REVERSAL);
sharedViewModel.setTransMenu(TransMenu.CLEAR_REVERSAL);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
}
public void onClickDeviceConfig(){
routeId = R.id.action_dashboardTransFragment_to_deviceConfig;
safeRouteTo(currentId, routeId, hostId);
}
}
private void showCurrencyChooserForCardFlow(Runnable onSelected) {
List<String> currencies = getAvailableCardSaleCurrencies();
if (currencies.isEmpty()) {
applyCardCurrencyAndHost("MMK");
onSelected.run();
return;
}
if (currencies.size() == 1) {
applyCardCurrencyAndHost(currencies.get(0));
onSelected.run();
return;
}
showCurrencyPickerDialog("Choose Currency", currencies, currency -> {
applyCardCurrencyAndHost(currency);
onSelected.run();
});
}
private List<String> getAvailableCardSaleCurrencies() {
cachePrimaryCardHostIfNeeded();
LinkedHashSet<String> values = new LinkedHashSet<>();
if (cardPrimaryCurrency != null && !TextUtils.isEmpty(cardPrimaryCurrency.name)) {
values.add(normalizeCurrency(cardPrimaryCurrency.name));
}
String secondaryCurrency = normalizeCurrency(SystemParamsOperation.getInstance().getThirdHostCurrency());
if (!TextUtils.isEmpty(SystemParamsOperation.getInstance().getThirdHostName()) && !TextUtils.isEmpty(secondaryCurrency)) {
values.add(secondaryCurrency);
}
return new ArrayList<>(values);
}
private void applyCardCurrencyAndHost(String selectedCurrency) {
cachePrimaryCardHostIfNeeded();
String selected = normalizeCurrency(selectedCurrency);
String secondaryCurrency = normalizeCurrency(SystemParamsOperation.getInstance().getThirdHostCurrency());
boolean useSecondaryCardHost = !TextUtils.isEmpty(SystemParamsOperation.getInstance().getThirdHostName())
&& !TextUtils.isEmpty(secondaryCurrency)
&& secondaryCurrency.equals(selected);
if (useSecondaryCardHost) {
SystemParamsOperation.getInstance().setHostName(SystemParamsOperation.getInstance().getThirdHostName());
SystemParamsOperation.getInstance().setTerminalId(SystemParamsOperation.getInstance().getThirdHostTerminalId());
SystemParamsOperation.getInstance().setMerchantId(SystemParamsOperation.getInstance().getThirdHostMerchantId());
SystemParamsOperation.getInstance().setIpAddress(SystemParamsOperation.getInstance().getThirdHostIpAddress());
SystemParamsOperation.getInstance().setSecIpAddress(SystemParamsOperation.getInstance().getThirdHostSecIpAddress());
} else {
SystemParamsOperation.getInstance().setHostName(cardPrimaryHostName);
SystemParamsOperation.getInstance().setTerminalId(cardPrimaryTid);
SystemParamsOperation.getInstance().setMerchantId(cardPrimaryMid);
SystemParamsOperation.getInstance().setIpAddress(cardPrimaryIp);
SystemParamsOperation.getInstance().setSecIpAddress(cardPrimarySecIp);
}
CurrencyType currencyType = useSecondaryCardHost ? toCurrencyType(selected) : cardPrimaryCurrency;
SystemParamsOperation.getInstance().setCurrencyType(currencyType);
sharedViewModel.set_currencyText(currencyType.name);
}
private void cachePrimaryCardHostIfNeeded() {
if (cardPrimaryHostCached) {
return;
}
cardPrimaryHostName = SystemParamsOperation.getInstance().getHostName();
cardPrimaryTid = SystemParamsOperation.getInstance().getTerminalId();
cardPrimaryMid = SystemParamsOperation.getInstance().getMerchantId();
cardPrimaryIp = SystemParamsOperation.getInstance().getIpAddress();
cardPrimarySecIp = SystemParamsOperation.getInstance().getSecIpAddress();
CurrencyType activeCurrency = SystemParamsOperation.getInstance().getCurrencyType();
cardPrimaryCurrency = activeCurrency == null ? CurrencyType.MMK : activeCurrency;
cardPrimaryHostCached = true;
}
private CurrencyType toCurrencyType(String value) {
String normalized = normalizeCurrency(value);
try {
return CurrencyType.valueOf(normalized);
} catch (Exception ignored) {
return CurrencyType.MMK;
}
}
private String normalizeCurrency(String raw) {
if (TextUtils.isEmpty(raw)) {
return "";
}
String value = raw.trim().toUpperCase();
switch (value) {
case "104":
case "MMK":
return "MMK";
case "840":
case "USD":
return "USD";
case "156":
case "CNY":
case "RMB":
return "CNY";
case "764":
case "THB":
return "THB";
case "643":
case "RUB":
return "RUB";
default:
return value;
}
}
private void showCurrencyPickerDialog(String title, List<String> currencies, CurrencySelectCallback callback) {
LinearLayout root = new LinearLayout(requireContext());
root.setOrientation(LinearLayout.VERTICAL);
root.setPadding(dp(20), dp(20), dp(20), dp(12));
TextView tvTitle = new TextView(requireContext());
tvTitle.setText(title);
tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
tvTitle.setTextColor(ContextCompat.getColor(requireContext(), R.color.colorTextTitle));
tvTitle.setPadding(0, 0, 0, dp(16));
root.addView(tvTitle);
final AlertDialog[] dialogHolder = new AlertDialog[1];
for (String currency : currencies) {
AppCompatButton button = new AppCompatButton(requireContext());
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dp(56)
);
lp.bottomMargin = dp(10);
button.setLayoutParams(lp);
button.setAllCaps(false);
button.setText(currency);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
button.setGravity(Gravity.CENTER);
button.setBackgroundResource(R.drawable.bg_rounded_btn_cv);
button.setTextColor(ContextCompat.getColor(requireContext(), R.color.white));
button.setOnClickListener(v -> {
if (dialogHolder[0] != null) {
dialogHolder[0].dismiss();
}
callback.onSelected(currency);
});
root.addView(button);
}
AppCompatButton cancel = new AppCompatButton(requireContext());
LinearLayout.LayoutParams cancelLp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dp(52)
);
cancel.setLayoutParams(cancelLp);
cancel.setAllCaps(false);
cancel.setText("Cancel");
cancel.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
cancel.setBackgroundResource(R.drawable.bg_rounded_btn_cancel_cv);
cancel.setTextColor(ContextCompat.getColor(requireContext(), R.color.colorPrimary));
cancel.setOnClickListener(v -> {
if (dialogHolder[0] != null) {
dialogHolder[0].dismiss();
}
});
root.addView(cancel);
AlertDialog dialog = new AlertDialog.Builder(requireContext())
.setView(root)
.create();
dialogHolder[0] = dialog;
dialog.show();
}
private int dp(int value) {
return Math.round(value * requireContext().getResources().getDisplayMetrics().density);
}
private interface CurrencySelectCallback {
void onSelected(String currency);
// currencySelectionHelper.showCardCurrencyChooser(onSelected);
}
}

View File

@ -4,7 +4,6 @@ import androidx.databinding.library.baseAdapters.BR;
import androidx.lifecycle.Observer;
import com.google.gson.stream.MalformedJsonException;
import com.utsmm.kbz.MainActivity;
import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest;
@ -105,7 +104,6 @@ public class DisabledTerminalFragment extends DataBindingFragment {
private void downloadParams(String lastTransName,String lastTransTime) {
showLoadingDialog("Downloading...");
((MainActivity) requireActivity()).getLocation();
SiriusRequest siriusReq = TMSUtil.getInstance().generateRequestParams(getContext(),lastTransName,lastTransTime);
mainViewModel.getParams(siriusReq).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

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 1–120
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,53 +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);
}
public KPayQRRequest.QRQueryRefundRequest getQueryRefundRequest(String merchOrderId, String mid) {
String currentTime = String.valueOf(System.currentTimeMillis());
String nonceStr = generateNonceStr();
Map<String, Object> bizContentMap = new HashMap<>();
bizContentMap.put("appid", appId);
bizContentMap.put("merch_code", mid);
bizContentMap.put("merch_order_id", merchOrderId);
Map<String, Object> requestMap = new HashMap<>();
requestMap.put("timestamp", currentTime);
requestMap.put("nonce_str", nonceStr);
requestMap.put("method", "kbz.payment.queryrefund");
requestMap.put("sign_type", "SHA256");
requestMap.put("version", "1.0");
requestMap.put("biz_content", bizContentMap);
String sign = Sign.INSTANCE.generateSign(requestMap, appKey);
KPayQRRequest.QRQueryRefundRequest.Request.BizContent bizContent =
new KPayQRRequest.QRQueryRefundRequest.Request.BizContent(appId, mid, merchOrderId);
KPayQRRequest.QRQueryRefundRequest.Request requestBody =
new KPayQRRequest.QRQueryRefundRequest.Request(
currentTime,
nonceStr,
"kbz.payment.queryrefund",
"SHA256",
sign,
"1.0",
bizContent
);
return new KPayQRRequest.QRQueryRefundRequest(requestBody);
}
public Observable<KPayRefund.RefundResponse> checkRefundStatus(KPayQRRequest.QRQueryRefundRequest request) {
return repository.checkRefundStatus(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,11 +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.KPayQRRequest;
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;
@ -37,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;
@ -57,8 +52,6 @@ public class QRRefundFragment extends DataBindingFragment {
private boolean isPartialRefund = false;
CompositeDisposable refundDisposable = new CompositeDisposable();
CompositeDisposable refundStatusDisposable = new CompositeDisposable();
CompositeDisposable retrieveUpdateDisposable = new CompositeDisposable();
private static final String TAG = QRRefundFragment.class.getSimpleName();
@ -102,7 +95,6 @@ public class QRRefundFragment extends DataBindingFragment {
public void onDestroyView() {
super.onDestroyView();
refundDisposable.dispose();
refundStatusDisposable.dispose();
retrieveUpdateDisposable.dispose();
}
@ -175,7 +167,7 @@ public class QRRefundFragment extends DataBindingFragment {
.subscribe(
response -> {
dismissLoadingDialog();
handleRefundResponse(response, referenceNo, originalAmount);
handleRefundResponse(response, referenceNo);
},
throwable -> {
dismissLoadingDialog();
@ -190,39 +182,7 @@ public class QRRefundFragment extends DataBindingFragment {
refundDisposable.add(refundDi);
}
private void callQueryRefund(String referenceNo, String orgAmount) {
String mid = payDetail.getMerchantNo();
KPayQRRequest.QRQueryRefundRequest request = KPayViewModel.getQueryRefundRequest(referenceNo, mid);
showLoadingDialog("Checking refund...");
refundStatusDisposable.add(KPayViewModel.checkRefundStatus(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(response -> {
dismissLoadingDialog();
if (response == null || response.getResponse() == null) {
LogUtil.d(TAG, "Query refund: null response");
sharedViewModel.payDetail.setValue(payDetail);
navigateToNext();
return;
}
LogUtil.d(TAG, "Query refund result: " + response.getResponse().getResult());
LogUtil.d(TAG, "Query refund status: " + response.getResponse().getRefundStatus());
handleRefundResponse(response, referenceNo, orgAmount);
}, throwable -> {
throwable.printStackTrace();
dismissLoadingDialog();
sharedViewModel.payDetail.setValue(payDetail);
navigateToNext();
}));
}
private void handleRefundResponse(KPayRefund.RefundResponse response, String referenceNo, String orgAmount) {
private void handleRefundResponse(KPayRefund.RefundResponse response, String referenceNo) {
if (response != null && response.getResponse() != null && "REFUND_SUCCESS".equalsIgnoreCase(response.getResponse().getRefundStatus())) {
LogUtil.d(TAG, "Refund successful!");
@ -232,25 +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 if (response != null && response.getResponse() != null
&& "DUPLICATED_REFUND_REQ_NO".equalsIgnoreCase(response.getResponse().getCode())){
LogUtil.d(TAG, "Duplicated refund request, querying actual result...");
callQueryRefund(referenceNo , orgAmount);
} else if (response != null && response.getResponse() != null
&& "REFUNDING".equalsIgnoreCase(response.getResponse().getRefundStatus())){
LogUtil.d(TAG, "Refunding refund request, querying actual result...");
callQueryRefund(referenceNo , orgAmount);
}
else {
} else {
LogUtil.d(TAG, "Refund failed!");
payDetail.setQrTransStatus(-1);
payDetail.setQrReferNo(referenceNo);
payDetail.setReferNo(referenceNo);
String errorMsg = "Refund failed";
@ -259,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();
}
@ -379,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

@ -2,11 +2,9 @@ package com.utsmm.kbz.ui.management;
import androidx.lifecycle.Observer;
import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
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;
@ -55,7 +53,6 @@ public class ManagementFunctionFragment extends DataBindingFragment {
public void onResume() {
super.onResume();
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
setToolBarTitleWithBackIcon(getString(R.string.title_select_function));
}
@ -125,7 +122,6 @@ public class ManagementFunctionFragment extends DataBindingFragment {
public void onClickReprintLastTrans() {
sharedViewModel.setTransMenu(TransMenu.REPRINT);
sharedViewModel.suppressReprintButtons.setValue(false);
observeLastTransaction();
}
@ -140,7 +136,7 @@ public class ManagementFunctionFragment extends DataBindingFragment {
// observeLastSettlement();
sharedViewModel.setTransMenu(TransMenu.LAST_SETTLEMENT);
routeId = R.id.action_managementFunctionFragment_to_settlementTransactionFragment;
routeId = R.id.action_managementFunctionFragment_to_selectHostFragment;
safeNavigateToRouteId();
}

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);
}
}
@ -145,18 +144,6 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
cardViewAdapter.updateList(searchedLists);
}
private void searchByTraceAndRRN(String input) {
for (PayDetail s : lists) {
boolean matchTrace = s.getVoucherNo() != null && s.getVoucherNo().contains(input);
boolean matchRRN = s.getReferNo() != null && s.getReferNo().contains(input);
if (matchTrace || matchRRN) {
searchedLists.add(s);
}
}
cardViewAdapter.updateList(searchedLists);
}
public class ClickEvent {
public void onClickSearch() {
@ -164,13 +151,19 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
String input = managementViewModel.txtRRNTrace.getValue();
if(input != null && !input.isEmpty()) {
searchByTraceAndRRN(input);
if(input.length() == 6) {
searchByTrace(input);
} else if(input.length() == 12) {
searchByRRN(input);
}
} else {
searchedLists.addAll(lists);
}
cardViewAdapter.updateList(searchedLists);
KeyboardHelper.hide(requireActivity());
}
}
@ -303,33 +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) ) {
//
// filteredLists.add(pay);
// }
if(yesterday.compareTo(transDate) <= 0
&& (pay.getTransactionType() == TransactionsType.MMQR.value
|| pay.getTransactionType() == TransactionsType.MMQR_REFUND.value)
&& pay.getQrTransStatus() == 1) {
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);
}
@ -339,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);
}
}
}
@ -379,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

@ -1,14 +1,10 @@
package com.utsmm.kbz.ui.management;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import com.github.gcacace.signaturepad.BR;
@ -17,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;
@ -30,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 {
@ -41,12 +34,9 @@ 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;
private List<QRSettleData> lastQrSettleData;
private ObjectAnimator slideUpAnimator;
private View printingCard;
@Override
protected void initViewModel() {
@ -83,7 +73,6 @@ public class ReprintReceiptFragment extends DataBindingFragment {
@Override
public void onPause() {
super.onPause();
stopPrintingAnimation();
}
@ -113,13 +102,13 @@ public class ReprintReceiptFragment extends DataBindingFragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
printingCard = mBinding.getRoot().findViewById(R.id.printingCard);
}
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) {
@ -148,132 +137,45 @@ public class ReprintReceiptFragment extends DataBindingFragment {
}
} else if (PrintHelper.getInstance().paperRollStatus() == SdkResult.Success) {
startPrintingAnimation();
printReceipt(payDetail);
}
}
private void observeLastSettlement() {
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)");
if (payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value) {
observeLastQrSettlement(payDetail);
} else {
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();
// }
// }
// });
}
private void observeLastQrSettlement(PayDetail settlePayDetail) {
lastQrSettleData = null;
LiveData<List<PayDetail>> liveData = managementViewModel.getLastSettlementQR(SystemParamsOperation.getInstance().getCurrentSerialNum());
liveData.observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
managementViewModel.getLastSettlement(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> qrSettlements) {
liveData.removeObserver(this);
if (qrSettlements != null) {
for (int i = qrSettlements.size() - 1; i >= 0; i--) {
PayDetail qrSettle = qrSettlements.get(i);
if (qrSettle != null
&& qrSettle.getTransactionType() == TransactionsType.MMQR_SETTLEMENT.value
&& TextUtils.equals(qrSettle.getBatchNo(), settlePayDetail.getBatchNo())
&& qrSettle.getQrSettleData() != null
&& !qrSettle.getQrSettleData().isEmpty()) {
lastQrSettleData = qrSettle.getQrSettleData();
break;
}
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);
} else {
showSingleInfoDialog(getString(R.string.txt_no_trans_to_print));
navigateMainScreen();
}
}
checkPaperExists(settlePayDetail);
}
});
}
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) {
@Override
public void onFailure() {
updateUIPrintReceiptFailure(payDetail);
PrintXReceipt.getInstance().printQRSettlementReport(payDetail, payDetail.getQrSettleData(), printXStatus);
} else if (lastQrSettleData != null && !lastQrSettleData.isEmpty()) {
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail, lastQrSettleData, printXStatus);
} else {
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail, printXStatus);
}
}
private PrintXStatus printXStatus = new PrintXStatus() {
@Override
public void onSuccess() {
stopPrintingAnimation();
delayFunctionCall(ReprintReceiptFragment.this::navigateMainScreen);
}
@Override
public void onFailure() {
stopPrintingAnimation();
updateUIPrintReceiptFailure(payDetail);
// checkPaperExists(payDetail);
}
};
private void startPrintingAnimation() {
if (printingCard == null) {
return;
}
if (slideUpAnimator != null && slideUpAnimator.isRunning()) {
return;
}
slideUpAnimator = ObjectAnimator.ofFloat(printingCard, View.TRANSLATION_Y, 0f, -20f);
slideUpAnimator.setDuration(420);
slideUpAnimator.setRepeatMode(ValueAnimator.REVERSE);
slideUpAnimator.setRepeatCount(ValueAnimator.INFINITE);
slideUpAnimator.start();
}
private void stopPrintingAnimation() {
if (slideUpAnimator != null) {
slideUpAnimator.cancel();
slideUpAnimator = null;
}
if (printingCard != null) {
printingCard.setTranslationY(0f);
}
checkPaperExists(payDetail);
}
});
}

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);
}
}
@ -210,43 +207,21 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
private void clearReversal() {
checkPointReversal = false;
// sharedViewModel.getReversalTransaction(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), payDetail -> {
// if (payDetail != null) {
// if (!checkPointReversal) {
// payDetail.setIsNeedReversal(false);
// sharedViewModel.updatePayDetail(payDetail);
// checkPointReversal = true;
//
// showSuccessDialog("Clear reversal success!");
// }
// } else {
// if (!checkPointReversal) {
// showInfoDialog("Clear reversal", "No reversal found!");
// checkPointReversal = true;
// }
//
// }
// });
sharedViewModel.getReversalTransaction(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), payDetail -> {
if (payDetail != null) {
if (!checkPointReversal) {
payDetail.setIsNeedReversal(false);
sharedViewModel.updatePayDetail(payDetail);
checkPointReversal = true;
sharedViewModel.getAllReversalTransaction().observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetails) {
if(payDetails != null && !payDetails.isEmpty()) {
if(!checkPointReversal) {
for (PayDetail payDetail : payDetails) {
payDetail.setIsNeedReversal(false);
sharedViewModel.updatePayDetail(payDetail);
}
checkPointReversal = true;
showSuccessDialog("Clear reversal success!");
}
} else {
if (!checkPointReversal) {
showInfoDialog("Clear reversal", "No reversal found!");
checkPointReversal = true;
}
showSuccessDialog("Clear reversal success!");
}
} else {
if (!checkPointReversal) {
showInfoDialog("Clear reversal", "No reversal found!");
checkPointReversal = true;
}
}
});
}
@ -287,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:
@ -356,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();
@ -397,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;
@ -452,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;
@ -51,8 +49,6 @@ public class TransactionSummaryFragment extends DataBindingFragment {
final Calendar myCalendar = Calendar.getInstance();
final Calendar myCalendar2 = Calendar.getInstance();
ArrayList<PayDetail> filteredLists = new ArrayList<>();
@Override
protected void initViewModel() {
managementViewModel = getFragmentScopeViewModel(ManagementViewModel.class);
@ -64,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());
}
@ -89,8 +84,6 @@ public class TransactionSummaryFragment extends DataBindingFragment {
setToolBarTitleWithBackIcon(getString(R.string.title_trans_summary));
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
summaryViewModel.resetField();
}
@ -160,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());
@ -226,15 +211,10 @@ public class TransactionSummaryFragment extends DataBindingFragment {
}
}
private SettleData processTransactionData(List<PayDetail> payDetailList,
SimpleDateFormat formatter,
Date yesterday,
Date start,
Date end) {
private SettleData processTransactionData(List<PayDetail> payDetailList, SimpleDateFormat formatter,
Date yesterday, Date start, Date end) {
try {
// ✅ IMPORTANT: clear old data
filteredLists.clear();
// Create a local helper class for readable mutability
class Counter {
int count = 0;
long amount = 0L;
@ -257,59 +237,84 @@ public class TransactionSummaryFragment extends DataBindingFragment {
Counter preAuthCompVoid = new Counter();
Counter refund = new Counter();
// ✅ Use ONE consistent format
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm", Locale.getDefault());
ArrayList<PayDetail> filteredLists = new ArrayList<>();
// Filter transactions by date
for (PayDetail pay : payDetailList) {
try {
// ✅ Combine date + time correctly
Date transDate = formatter.parse(pay.getTransDate());
if (yesterday.compareTo(transDate) <= 0) {
filteredLists.add(pay);
}
} catch (ParseException e) {
LogUtil.e(TAG, "Error parsing transaction date: " + e.getMessage());
}
}
LogUtil.d(TAG, "Filtered transactions count: " + filteredLists.size());
// Process filtered transactions
for (PayDetail pay : filteredLists) {
try {
Date currentDate = sdf.parse(pay.transDate + " " + pay.transTime);
if (currentDate == null) continue;
// ✅ Correct inclusive range check
if (!currentDate.before(start) && !currentDate.after(end)) {
// ✅ Keep filtered list for printing
filteredLists.add(pay);
if ((currentDate.after(start) || currentDate.equals(start)) &&
(currentDate.before(end) || currentDate.equals(end))) {
if (sharedViewModel.hostType.getValue() == HostType.QR) {
if (pay.getTransactionType() == TransactionsType.MMQR.value && pay.getQrTransStatus() == 1) {
wave.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.MMQR_REFUND.value && pay.getQrTransStatus() == 1) {
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);
}
}
}
}
} catch (ParseException e) {
LogUtil.e(TAG, "Error parsing transaction datetime: " + e.getMessage());
}
}
LogUtil.d(TAG, "Filtered transactions count: " + filteredLists.size());
return new SettleData(
sale.count, sale.amount,
wave.count, wave.amount,
@ -322,7 +327,6 @@ public class TransactionSummaryFragment extends DataBindingFragment {
refund.count, refund.amount,
waveRefund.count, waveRefund.amount
);
} catch (Exception e) {
LogUtil.e(TAG, "Error processing transaction data: " + e.getMessage());
return null;
@ -333,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 "";
}
@ -371,7 +377,7 @@ public class TransactionSummaryFragment extends DataBindingFragment {
private void printReceipt(PayDetail payDetail) {
try {
LogUtil.d(TAG, "Starting receipt print");
PrintXReceipt.getInstance().printSmileSummaryReport(payDetail, filteredLists, sharedViewModel.hostType.getValue(), new PrintXStatus() {
PrintXReceipt.getInstance().printSmileSummaryReport(payDetail, new PrintXStatus() {
@Override
public void onSuccess() {
LogUtil.d(TAG, "Receipt printed successfully");
@ -457,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

@ -77,7 +77,7 @@ public class ManualEntryFragment extends DataBindingFragment {
}
private void processEmvCard() {
if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND || 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_VOID) {
routeId = R.id.action_manualEntryFragment_to_inputRRNFragment;
} else {
routeId = R.id.action_manualEntryFragment_to_emvTransactionFragment;
@ -104,9 +104,9 @@ 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.cardNum.setValue(cardNo);
emvTransactionProcessViewModel.setTradeData(tradeData);
safeNavigateToRouteId();
@ -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

@ -1,39 +1,18 @@
package com.utsmm.kbz.ui.navigation;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import androidx.databinding.ObservableBoolean;
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.BaseApplication;
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;
import com.utsmyanmar.paylibs.sign_on.SignOnListener;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import java.util.List;
import java.util.Observable;
public class NaviMainFragment extends DataBindingFragment {
private OnFragmentInteractionListener mListener;
@ -121,36 +100,6 @@ public class NaviMainFragment extends DataBindingFragment {
}
public class ClickEvent {
private static final String PREF_NAME = "pinpad_prefs";
private static final String KEY_PINPAD_SOUND = "pinpad_sound_enabled";
public final ObservableBoolean pinpadSoundEnabled;
public ClickEvent() {
boolean savedValue = loadPinpadSoundState();
this.pinpadSoundEnabled = new ObservableBoolean(savedValue);
BaseApplication.getInstance().deviceEngine.getPlatform().enablePinpadBeep(savedValue);
}
public boolean loadPinpadSoundState(){
return BaseApplication.getInstance().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).getBoolean(KEY_PINPAD_SOUND, true);
}
public void savePinpadSoundState(boolean enabled){
BaseApplication.getInstance().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit().putBoolean(KEY_PINPAD_SOUND, enabled).apply();
}
public void onClickPinpadSound(){
boolean newState = !pinpadSoundEnabled.get();
int result = BaseApplication.getInstance().deviceEngine.getPlatform().enablePinpadBeep(newState);
if(result == SdkResult.Success){
pinpadSoundEnabled.set(newState);
savePinpadSoundState(newState);
// LogUtil.d("NaviMainFragment", "pinpad enabled");
}
}
public void onClickEcho() {
showLoadingDialog("Sending Echo!");
@ -188,15 +137,6 @@ public class NaviMainFragment extends DataBindingFragment {
});
}
public void onClickWifi(){
try {
Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
startActivity(intent);
} catch (Exception e) {
LogUtil.e("NaviMainFragment", "error on going wifi");
}
}
public void onClickLogOff() {
showLoadingDialog("Sending LogOff!");
@ -236,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();
}
@ -272,6 +184,7 @@ public class NaviMainFragment extends DataBindingFragment {
mListener.onClickExit();
}
}
public interface OnFragmentInteractionListener {
@ -282,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);
@ -359,10 +351,7 @@ public class PinPadViewModel extends ViewModel {
handler.obtainMessage(ON_ERROR_PIN_PAD,retCode).sendToTarget();
}
LogUtil.d(TAG,"RetCode:"+retCode);
if(retCode != SdkResult.PinPad_No_Pin_Input) {
payDetail.setPINCipher(ByteUtil.bytes2HexStr(data));
}
payDetail.setPINCipher(ByteUtil.bytes2HexStr(data));
LogUtil.d(TAG,"data bytes:"+ByteUtil.bytes2HexStr(data));
}

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,430 +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.MainActivity;
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 com.utsmm.kbz.util.MockData;
import com.utsmyanmar.paylibs.model.TradeData;
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));
features.add(new QRPayItem("Mock QR", R.drawable.ic_qr_pay, 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;
case "Mock QR":
onClickMockQR();
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 onClickMockQR(){
TradeData sale1 = MockData.getInstance().generateMockQRWithAmount(TransactionsType.MMQR, 5000L, "QR001");
sharedViewModel.insertPayDetail(sale1.getPayDetail());
TradeData sale2 = MockData.getInstance().generateMockQRWithAmount(TransactionsType.MMQR, 10000L, "QR002");
sharedViewModel.insertPayDetail(sale2.getPayDetail());
TradeData sale3 = MockData.getInstance().generateMockQRWithAmount(TransactionsType.MMQR, 3500L, "QR003");
sharedViewModel.insertPayDetail(sale3.getPayDetail());
TradeData refund1 = MockData.getInstance().generateMockQRWithAmount(TransactionsType.MMQR_REFUND, 2000L, "QR004");
sharedViewModel.insertPayDetail(refund1.getPayDetail());
showSingleInfoDialog("Mock QR inserted successfully");
}
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,260 +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 if (response != null && response.getResponse() != null && "DUPLICATED_REFUND_REQ_NO".equalsIgnoreCase(response.getResponse().getRefundStatus())) {
}
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,106 +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() + "/file/download?filePath=";
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

@ -39,10 +39,6 @@ public class VoidViewModel extends ViewModel {
return repository.getVoidTransaction(transType,voucherNo);
}
public LiveData<PayDetail> getVoidTransByInvoice(int transType, String invoiceNo) {
return repository.getVoidTransactionByInvoice(transType, invoiceNo);
}
public void observeVoidTrans(int transType) {
getVoidTransactions(transType).observeForever(new Observer<List<PayDetail>>() {

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,169 +0,0 @@
package com.utsmm.kbz.ui.settings;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.util.Log;
import android.view.animation.LinearInterpolator;
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.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
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;
private ObjectAnimator rollUpAnimator;
private View hostCardView;
private volatile boolean isPrintingHostConfig = false;
@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;
hostCardView = binding.getRoot().findViewById(R.id.hostCard);
viewModel.loadConfig();
}
@Override
public void onResume(){
super.onResume();
setToolBarTitleWithBackIcon("Host Configs");
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
}
@Override
public void onPause() {
super.onPause();
stopRollUpAnimation();
isPrintingHostConfig = false;
}
@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;
}
if (isPrintingHostConfig) {
return;
}
startHostConfigPrint();
}
}
private void startHostConfigPrint() {
isPrintingHostConfig = true;
startRollUpAnimation();
PrintXReceipt.getInstance().printTerminalHostConfig(new PrintXStatus() {
@Override
public void onSuccess() {
requireActivity().runOnUiThread(() -> {
isPrintingHostConfig = false;
stopRollUpAnimation();
Log.d("PrintConfig", "Print Terminal Config Success.");
});
}
@Override
public void onFailure() {
requireActivity().runOnUiThread(() -> {
isPrintingHostConfig = false;
stopRollUpAnimation();
Log.e("PrintConfig", "Print Terminal Config Failure.");
showDeclineDialog("Failed to print host config.");
});
}
});
}
private void startRollUpAnimation() {
if (hostCardView == null) {
return;
}
if (rollUpAnimator != null && rollUpAnimator.isRunning()) {
return;
}
hostCardView.post(() -> {
int cardTop = hostCardView.getTop();
int cardHeight = hostCardView.getHeight();
if (cardHeight <= 0) {
return;
}
// Move past the top edge so the card fully leaves the screen.
float offScreenDistance = cardTop + cardHeight + 80f;
rollUpAnimator = ObjectAnimator.ofFloat(hostCardView, View.TRANSLATION_Y, 0f, -offScreenDistance);
rollUpAnimator.setDuration(3000);
rollUpAnimator.setInterpolator(new LinearInterpolator());
rollUpAnimator.setRepeatMode(ValueAnimator.RESTART);
rollUpAnimator.setRepeatCount(ValueAnimator.INFINITE);
rollUpAnimator.start();
});
}
private void stopRollUpAnimation() {
if (rollUpAnimator != null) {
rollUpAnimator.cancel();
rollUpAnimator = null;
}
if (hostCardView != null) {
hostCardView.setTranslationY(0f);
}
}
}

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,218 +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> secHostCurrency = new MutableLiveData<>();
// Third Host
public MutableLiveData<String> thirdHostName = new MutableLiveData<>();
public MutableLiveData<String> thirdHostTid = new MutableLiveData<>();
public MutableLiveData<String> thirdHostMid = new MutableLiveData<>();
public MutableLiveData<String> thirdHostShortCode = new MutableLiveData<>();
public MutableLiveData<String> thirdHostPrimaryIp = new MutableLiveData<>();
public MutableLiveData<String> thirdHostPrimaryPort = new MutableLiveData<>();
public MutableLiveData<String> thirdHostSecondaryIp = new MutableLiveData<>();
public MutableLiveData<String> thirdHostSecondaryPort = new MutableLiveData<>();
public MutableLiveData<String> thirdHostCurrency = 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(wrapTerminalName(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(normalizeCurrency(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]);
secHostCurrency.setValue(normalizeCurrency(sp.getSecHostCurrency()));
}
if (sp.getThirdHostName() != null && !sp.getThirdHostName().isEmpty()) {
thirdHostName.setValue(sp.getThirdHostName());
thirdHostTid.setValue(sp.getThirdHostTerminalId());
thirdHostMid.setValue(sp.getThirdHostMerchantId());
thirdHostShortCode.setValue(sp.getThirdHostShortCode());
String[] thp = split(sp.getThirdHostIpAddress());
thirdHostPrimaryIp.setValue(thp[0]);
thirdHostPrimaryPort.setValue(thp[1]);
String[] ths = split(sp.getThirdHostSecIpAddress());
thirdHostSecondaryIp.setValue(ths[0]);
thirdHostSecondaryPort.setValue(ths[1]);
thirdHostCurrency.setValue(normalizeCurrency(sp.getThirdHostCurrency()));
}
}
private String normalizeCurrency(String raw) {
if (TextUtils.isEmpty(raw)) return "";
String value = raw.trim().toUpperCase();
switch (value) {
case "104":
case "MMK":
return "MMK";
case "840":
case "USD":
return "USD";
case "156":
case "CNY":
case "RMB":
return "CNY";
case "764":
case "THB":
return "THB";
case "643":
case "RUB":
return "RUB";
default:
return value;
}
}
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 wrapTerminalName(String name) {
if (TextUtils.isEmpty(name)) return "";
String formattedName = name
.replace("\\r\\n", "\n")
.replace("\\n", "\n")
.replace("\r\n", "\n")
.trim();
List<String> lines = wrapAddressText(formattedName, 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)
};
}
}

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