Merge branch 'production_2.2' into test

This commit is contained in:
moon 2026-05-25 11:51:30 +06:30
commit c3246b907a
108 changed files with 3901 additions and 1272 deletions

View File

@ -13,7 +13,6 @@
<option value="$PROJECT_DIR$/app" /> <option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/baselib" /> <option value="$PROJECT_DIR$/baselib" />
<option value="$PROJECT_DIR$/ecr" /> <option value="$PROJECT_DIR$/ecr" />
<option value="$PROJECT_DIR$/ecr-service" />
<option value="$PROJECT_DIR$/ecr-service-lib" /> <option value="$PROJECT_DIR$/ecr-service-lib" />
<option value="$PROJECT_DIR$/link-service-lib" /> <option value="$PROJECT_DIR$/link-service-lib" />
<option value="$PROJECT_DIR$/mpulib" /> <option value="$PROJECT_DIR$/mpulib" />

11
CHANGELOG.md Normal file
View File

@ -0,0 +1,11 @@
# Change log UAT
## [2.12] - 2026-05-06
- **Pinpad 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`)

View File

@ -14,8 +14,8 @@ android {
applicationId "com.utsmm.kbz" applicationId "com.utsmm.kbz"
minSdk 24 minSdk 24
targetSdk 33 targetSdk 33
versionCode 21 versionCode 2
versionName "2.1" versionName "2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@ -50,7 +50,7 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled true minifyEnabled true
shrinkResources false shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
debug { debug {
@ -204,7 +204,7 @@ dependencies {
// ECR Dependencies - Modern ECR Client Library // ECR Dependencies - Modern ECR Client Library
// implementation project(path: ':ecr-client-lib') // implementation project(path: ':ecr-client-lib')
implementation project(path: ':ecr-service-lib') // implementation project(path: ':ecr-service-lib')
// Core Libraries // Core Libraries
implementation project(path: ':paylibs') implementation project(path: ':paylibs')

View File

@ -265,4 +265,5 @@
-dontshrink -dontshrink
-dontwarn com.xgd.smartpos.manager.app.UsageInfo -dontwarn com.xgd.smartpos.manager.app.UsageInfo
-dontwarn com.xgd.smartpos.manager.app.UsageStats -dontwarn com.xgd.smartpos.manager.app.UsageStats
-dontwarn javax.lang.model.element.Modifier

View File

@ -35,6 +35,10 @@
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <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:noHistory="true"-->
<!-- android:excludeFromRecents="true"--> <!-- android:excludeFromRecents="true"-->

View File

@ -4,6 +4,7 @@ import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil; import androidx.databinding.DataBindingUtil;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDestination; import androidx.navigation.NavDestination;
@ -32,6 +33,7 @@ import com.nexgo.downloadkey.downloadflow.DownloadFlowResultEntity;
import com.nexgo.downloadkey.downloadflow.DownloadResult; import com.nexgo.downloadkey.downloadflow.DownloadResult;
import com.nexgo.oaf.apiv3.device.pinpad.PinPad; import com.nexgo.oaf.apiv3.device.pinpad.PinPad;
import com.nexgo.oaf.apiv3.device.pinpad.WorkKeyTypeEnum; import com.nexgo.oaf.apiv3.device.pinpad.WorkKeyTypeEnum;
import com.utsmm.kbz.util.LocationUtil;
import com.utsmyanmar.baselib.BaseApplication; import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.repo.Repository; import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.baselib.ui.AnimationDialog; import com.utsmyanmar.baselib.ui.AnimationDialog;
@ -115,6 +117,7 @@ public class MainActivity extends AppCompatActivity implements
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar(); BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
// Keep screen on // Keep screen on
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@ -157,10 +160,8 @@ public class MainActivity extends AppCompatActivity implements
} }
private void initKey(){ private void initKey(){
SystemParamsOperation.getInstance().setTmsAddress("https://api-tms-uat.kbzbank.com:8443/sirius"); SystemParamsOperation.getInstance().setTmsAddress("https://api-tms.kbzbank.com/sirius");
// SystemParamsOperation.getInstance().setTmsAddress("https://sirius-nest.utsmyanmar.com"); SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms.kbzbank.com/receipt");
SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms-uat.kbzbank.com:8443/receipt");
// SystemParamsOperation.getInstance().setEReceiptAddress("http://receipt-nest.utsmyanmar.com");
PinPad pinPad = MyApplication.getInstance().deviceEngine.getPinPad(); PinPad pinPad = MyApplication.getInstance().deviceEngine.getPinPad();
byte[] encryptedPIK = SystemParamsOperation.getInstance().getPIK(); byte[] encryptedPIK = SystemParamsOperation.getInstance().getPIK();
@ -176,6 +177,7 @@ public class MainActivity extends AppCompatActivity implements
private void initViewModels() { private void initViewModels() {
sharedViewModel = new ViewModelProvider(this).get(SharedViewModel.class); sharedViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
sharedViewModel.getToastMsg().observe(this, this::showToast);
} }
private void setupUI() { private void setupUI() {
@ -427,20 +429,19 @@ public class MainActivity extends AppCompatActivity implements
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
getLocation();
SystemParamsOperation.getInstance().setSetupEcr(false); SystemParamsOperation.getInstance().setSetupEcr(false);
SystemParamsOperation.getInstance().setDownloadedParams(false); SystemParamsOperation.getInstance().setDownloadedParams(false);
handleAutoSettlementIntent(getIntent()); handleAutoSettlementIntent(getIntent());
BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar(); BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
} }
@Override @Override
public void onStop(){ public void onStop(){
super.onStop(); super.onStop();
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar(); BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
// BaseApplication.getInstance().deviceEngine.getPlatform().enableHomeButton();
// BaseApplication.getInstance().deviceEngine.getPlatform().enableTaskButton();
} }
@Override @Override
@ -450,69 +451,114 @@ public class MainActivity extends AppCompatActivity implements
handleAutoSettlementIntent(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) { private void handleAutoSettlementIntent(Intent intent) {
if (intent == null) return; if (intent == null) return;
// Handle regular auto settlement boolean hasPOS = intent.getBooleanExtra("AUTO_SETTLEMENT", false);
boolean auto = intent.getBooleanExtra("AUTO_SETTLEMENT", false); boolean hasQR = intent.getBooleanExtra("AUTO_QR_SETTLEMENT", false);
if (auto) {
if (hasPOS) {
PayDetail payDetail = (PayDetail) intent.getSerializableExtra("EXTRA_PAY_DETAIL"); PayDetail payDetail = (PayDetail) intent.getSerializableExtra("EXTRA_PAY_DETAIL");
if (payDetail != null) { if (payDetail != null) {
sharedViewModel.payDetail.setValue(payDetail); sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT); sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT);
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount())); sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount()));
try { try {
navController.navigate(R.id.transactionResultFragment); navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Navigation error: " + e.getMessage()); LogUtil.e(TAG, "Navigation error: " + e.getMessage());
} }
// If QR also exists, trigger it AFTER POS result is done
if (hasQR) {
navigateToQRSettlementAfterPOS(intent);
}
} else {
// POS had no data, go straight to QR if available
if (hasQR) {
handleQRSettlement(intent);
}
} }
return;
} else if (hasQR) {
// Only QR settlement, no POS
handleQRSettlement(intent);
} }
}
// Handle QR auto settlement
boolean autoQR = intent.getBooleanExtra("AUTO_QR_SETTLEMENT", false);
if (autoQR) {
int qrSaleCount = intent.getIntExtra("QR_SALE_COUNT", 0);
long qrSaleAmount = intent.getLongExtra("QR_SALE_AMOUNT", 0L);
int qrRefundCount = intent.getIntExtra("QR_REFUND_COUNT", 0);
long qrRefundAmount = intent.getLongExtra("QR_REFUND_AMOUNT", 0L);
long totalAmount = intent.getLongExtra("QR_TOTAL_AMOUNT", 0L);
List<PayDetail> qrTransList = (List<PayDetail>) intent.getSerializableExtra("QR_TRANS_LIST");
// Create QR settlement PayDetail private void navigateToQRSettlementAfterPOS(Intent intent) {
SettleData settleData = new SettleData( // Observe transactionResultFragment's completion via ViewModel
qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L); // When POS result screen signals "done" (print complete / user dismissed),
// then navigate to QR result
TradeData tradeData = Params.newTrade(false); sharedViewModel.onSettlementResultDone.observe(this, new Observer<Boolean>() {
PayDetail payDetail = tradeData.getPayDetail(); @Override
payDetail.setSettleDataObj(settleData); public void onChanged(Boolean done) {
payDetail.setTransactionType(TransactionsType.MMQR_SETTLEMENT.value); if (done != null && done) {
payDetail.setTransType(TransactionsType.MMQR_SETTLEMENT.name); // Remove observer so it only fires once
payDetail.setAmount(totalAmount); sharedViewModel.onSettlementResultDone.removeObserver(this);
payDetail.setTradeAnswerCode("000"); // Reset flag
sharedViewModel.onSettlementResultDone.postValue(false);
// Now navigate to QR
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount)); handleQRSettlement(intent);
sharedViewModel.payDetails.setValue(qrTransList); }
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR_SETTLEMENT);
try {
navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) {
LogUtil.e(TAG, "QR Auto Settlement navigation error: " + e.getMessage());
} }
});
}
private void handleQRSettlement(Intent intent) {
int qrSaleCount = intent.getIntExtra("QR_SALE_COUNT", 0);
long qrSaleAmount = intent.getLongExtra("QR_SALE_AMOUNT", 0L);
int qrRefundCount = intent.getIntExtra("QR_REFUND_COUNT", 0);
long qrRefundAmount = intent.getLongExtra("QR_REFUND_AMOUNT", 0L);
long totalAmount = intent.getLongExtra("QR_TOTAL_AMOUNT", 0L);
List<PayDetail> qrTransList = (List<PayDetail>) intent.getSerializableExtra("QR_TRANS_LIST");
SettleData settleData = new SettleData(
qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
TradeData tradeData = Params.newTrade(false);
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setSettleDataObj(settleData);
payDetail.setTransactionType(TransactionsType.MMQR_SETTLEMENT.value);
payDetail.setTransType(TransactionsType.MMQR_SETTLEMENT.name);
payDetail.setAmount(totalAmount);
payDetail.setTradeAnswerCode("000");
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount));
sharedViewModel.payDetails.setValue(qrTransList);
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR_SETTLEMENT);
try {
navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) {
LogUtil.e(TAG, "QR Auto Settlement navigation error: " + e.getMessage());
} }
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
// BaseApplication.getInstance().deviceEngine.getPlatform().enableHomeButton();
// BaseApplication.getInstance().deviceEngine.getPlatform().enableTaskButton();
// Clean up RxJava disposables // Clean up RxJava disposables
compositeDisposable.clear(); compositeDisposable.clear();
// Reset screen mode // Reset screen mode
@ -625,4 +671,4 @@ public class MainActivity extends AppCompatActivity implements
private void showToast(String message) { private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
} }
} }

View File

@ -29,9 +29,11 @@ import com.denzcoskun.imageslider.constants.ScaleTypes;
import com.denzcoskun.imageslider.models.SlideModel; import com.denzcoskun.imageslider.models.SlideModel;
import com.nexgo.oaf.apiv3.emv.AidEntity; import com.nexgo.oaf.apiv3.emv.AidEntity;
import com.nexgo.oaf.apiv3.emv.CapkEntity; import com.nexgo.oaf.apiv3.emv.CapkEntity;
import com.pos.connection.bridge.binder.ECRConstant; //import com.pos.connection.bridge.binder.ECRConstant;
import com.utsmm.kbz.util.MockData; import com.utsmm.kbz.util.MockData;
//import com.utsmm.kbz.util.ecr.ModernECRFactory;
//import com.utsmm.kbz.util.ecr.ModernECRManager;
import com.utsmyanmar.baselib.BaseApplication; import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.emv.EmvParamOperation; import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
@ -63,6 +65,7 @@ import com.utsmm.kbz.ui.core_viewmodel.TMSProcessViewModel;
import com.utsmm.kbz.util.Connectivity; import com.utsmm.kbz.util.Connectivity;
import com.utsmm.kbz.util.CurrencySelectionHelper;
import com.utsmm.kbz.util.dialog.AlertXDialog; import com.utsmm.kbz.util.dialog.AlertXDialog;
import com.utsmm.kbz.util.enums.SettlementType; import com.utsmm.kbz.util.enums.SettlementType;
import com.utsmm.kbz.util.ecr.CoreUtils; import com.utsmm.kbz.util.ecr.CoreUtils;
@ -112,6 +115,7 @@ public class MainFragment extends DataBindingFragment {
private String cardPrimaryIp = ""; private String cardPrimaryIp = "";
private String cardPrimarySecIp = ""; private String cardPrimarySecIp = "";
private CurrencyType cardPrimaryCurrency = CurrencyType.MMK; private CurrencyType cardPrimaryCurrency = CurrencyType.MMK;
private CurrencySelectionHelper currencySelectionHelper;
@Inject @Inject
EmvParamOperation emvParamOperation; EmvParamOperation emvParamOperation;
@ -136,6 +140,7 @@ public class MainFragment extends DataBindingFragment {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class); sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
mainViewModel = getFragmentScopeViewModel(MainViewModel.class); mainViewModel = getFragmentScopeViewModel(MainViewModel.class);
tmsProcessViewModel = getFragmentScopeViewModel(TMSProcessViewModel.class); tmsProcessViewModel = getFragmentScopeViewModel(TMSProcessViewModel.class);
currencySelectionHelper = new CurrencySelectionHelper(this, sharedViewModel);
// Initialize ModernECRManager // Initialize ModernECRManager
// ModernECRFactory factory = new ModernECRFactory(requireContext(), sharedViewModel); // ModernECRFactory factory = new ModernECRFactory(requireContext(), sharedViewModel);
@ -170,12 +175,10 @@ public class MainFragment extends DataBindingFragment {
NexGoSDK.getInstance().cancelCheckCard(); NexGoSDK.getInstance().cancelCheckCard();
NexGoSDK.getInstance().closeReader(); NexGoSDK.getInstance().closeReader();
enableHomeButton(); enableHomeButton();
// disableTaskButton();
// BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
}); });
} }
private void disableHomeButton() { private void disableHomeButton() {
int result = BaseApplication.getInstance().deviceEngine.getPlatform().disableHomeButton(); int result = BaseApplication.getInstance().deviceEngine.getPlatform().disableHomeButton();
LogUtil.d(TAG, "Disable Home Button Result:" + result); LogUtil.d(TAG, "Disable Home Button Result:" + result);
@ -262,7 +265,7 @@ public class MainFragment extends DataBindingFragment {
sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus()); sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus());
// queryAidCAPKList(); // queryAidCAPKList();
queryAidCAPKList(); // queryAidCAPKList();
// generateMockQR(); // generateMockQR();
} }
@ -281,16 +284,21 @@ public class MainFragment extends DataBindingFragment {
LogUtil.d(TAG, "Total CAPK :" + noCAPK); LogUtil.d(TAG, "Total CAPK :" + noCAPK);
for (CapkEntity capkEntity : capkList) { for (CapkEntity capkEntity : capkList) {
LogUtil.d(TAG, "CAPK Entity :" + capkEntity.getRid()); LogUtil.d(TAG, "CAPK Entity :" + capkEntity.getRid());
if(capkEntity.getRid().equals("A000000003")) { if(capkEntity.getRid().equals("A000000004")) {
LogUtil.d(TAG, "CAPK Entity check sum:" + capkEntity.getCheckSum()); LogUtil.d(TAG, "CAPK Entity check sum:" + capkEntity.getCheckSum());
LogUtil.d(TAG, "CAPK Entity modulus:" + capkEntity.getModulus()); LogUtil.d(TAG, "CAPK Entity modulus:" + capkEntity.getModulus());
LogUtil.d(TAG, "CAPK Entity index:" + capkEntity.getCapkIdx()); LogUtil.d(TAG, "CAPK Entity index:" + capkEntity.getCapkIdx());
} }
} }
// for (AidEntity aidEntity : aidList) { for (AidEntity aidEntity : aidList) {
// LogUtil.d(TAG, "AID Entity :" + aidEntity.getAid()); LogUtil.d(TAG, "AID Entity :" + aidEntity.getAid());
// } // if(aidEntity.getAid().startsWith("A000000003")) {
LogUtil.d(TAG, "AID Entity AID:" + aidEntity.getAid());
LogUtil.d(TAG, "AID Entity ASI:" + aidEntity.getAsi());
LogUtil.d(TAG, "AID Entity Version:" + aidEntity.getAppVerNum());
// }
}
} }
@ -316,8 +324,8 @@ public class MainFragment extends DataBindingFragment {
if (checkECRServiceAppExistOrNot()) { if (checkECRServiceAppExistOrNot()) {
// Initialize Modern ECR Manager // Initialize Modern ECR Manager
// modernECRManager.init(); // modernECRManager.init();
// ////
// // Observe navigation requests //// // Observe navigation requests
// modernECRManager.getNavigationRequest().observe(getViewLifecycleOwner(), destinationId -> { // modernECRManager.getNavigationRequest().observe(getViewLifecycleOwner(), destinationId -> {
// if (destinationId != null) { // if (destinationId != null) {
// delayFunctionCall(() -> isRouteValidAndNavigateToRoute(destinationId)); // delayFunctionCall(() -> isRouteValidAndNavigateToRoute(destinationId));
@ -627,6 +635,16 @@ public class MainFragment extends DataBindingFragment {
default: default:
return value; return value;
} }
// currencySelectionHelper.showCardCurrencyChooser(this::startCardSaleFlow);
}
private void showCurrencyChooserForSignOn() {
currencySelectionHelper.showCardCurrencyChooser(this::navigateToSignOn);
}
private void navigateToSignOn() {
routeId = R.id.action_nav_main_to_nav_sign_on;
safeNavigateToRouteId();
} }
private void processBatch() { private void processBatch() {
@ -1017,12 +1035,10 @@ public class MainFragment extends DataBindingFragment {
showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet)); showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
} else if (SystemParamsOperation.getInstance().isNeedSettlement()) { } else if (SystemParamsOperation.getInstance().isNeedSettlement()) {
AlertXDialog.getInstance().showDialog(requireContext(), getResourceString(R.string.title_need_settle), getResourceString(R.string.txt_do_you_want_to_continue), () -> { AlertXDialog.getInstance().showDialog(requireContext(), getResourceString(R.string.title_need_settle), getResourceString(R.string.txt_do_you_want_to_continue), () -> {
routeId = R.id.action_nav_main_to_nav_sign_on; showCurrencyChooserForSignOn();
safeNavigateToRouteId();
}); });
} else { } else {
routeId = R.id.action_nav_main_to_nav_sign_on; showCurrencyChooserForSignOn();
safeNavigateToRouteId();
} }
} }

View File

@ -20,6 +20,7 @@ import com.google.gson.Gson;
import com.utsmm.kbz.MainActivity; import com.utsmm.kbz.MainActivity;
import com.utsmm.kbz.util.EReceiptUtil; import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmm.kbz.util.enums.TransactionStatus;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest; import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.repo.Repository; import com.utsmyanmar.baselib.repo.Repository;
import com.utsmm.kbz.BuildConfig; import com.utsmm.kbz.BuildConfig;
@ -34,6 +35,8 @@ import io.reactivex.rxjava3.schedulers.Schedulers;
import retrofit2.HttpException; import retrofit2.HttpException;
import com.utsmyanmar.paylibs.Constant; import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.batch_upload.BatchListener;
import com.utsmyanmar.paylibs.batch_upload.BatchUploadProcess;
import com.utsmyanmar.paylibs.isobuilder.ISOMode; import com.utsmyanmar.paylibs.isobuilder.ISOMode;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX; import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion; import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion;
@ -44,6 +47,8 @@ import com.utsmyanmar.paylibs.model.SettleData;
import com.utsmyanmar.paylibs.model.TradeData; import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.network.ISOCallback; import com.utsmyanmar.paylibs.network.ISOCallback;
import com.utsmyanmar.paylibs.network.ISOSocket; import com.utsmyanmar.paylibs.network.ISOSocket;
import com.utsmyanmar.paylibs.sign_on.EchoTestProcess;
import com.utsmyanmar.paylibs.sign_on.SignOnListener;
import com.utsmyanmar.paylibs.utils.LogUtil; import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.MessageType; import com.utsmyanmar.paylibs.utils.MessageType;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
@ -73,15 +78,26 @@ public class AutoSettleService extends Service {
// Flags to prevent infinite loops // Flags to prevent infinite loops
private boolean regularSettlementCompleted = false; private boolean regularSettlementCompleted = false;
private boolean qrSettlementCompleted = false; private boolean qrSettlementCompleted = false;
private boolean posHasData = false; // true = POS actually ran and has result
private boolean qrHasData = false; // true = QR actually ran and has result
// Observers to keep reference for cleanup // Observers to keep reference for cleanup
private Observer<java.util.List<com.utsmyanmar.paylibs.model.PayDetail>> regularSettlementObserver; private Observer<List<PayDetail>> regularSettlementObserver;
private Observer<java.util.List<com.utsmyanmar.paylibs.model.PayDetail>> qrSettlementObserver; private Observer<List<PayDetail>> qrSettlementObserver;
private int i = 0;
private boolean flag = false;
@Inject @Inject
Repository repository; Repository repository;
private PayDetail pendingPayDetail = null;
private Bundle pendingQrData = null;
private boolean posSettlementReady = false;
private boolean qrSettlementReady = false;
ArrayList<PayDetail> payDetails = new ArrayList<>();
public static final String NOTIFICATION_CHANNEL_ID = "10001"; public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default"; private final static String default_notification_channel_id = "default";
@ -188,6 +204,10 @@ public class AutoSettleService extends Service {
if (regularSettlementCompleted) { if (regularSettlementCompleted) {
return; return;
} }
payDetails.clear();
payDetails.addAll(list);
regularSettlementCompleted = true; regularSettlementCompleted = true;
repository.getSettlementPOS().removeObserver(this); repository.getSettlementPOS().removeObserver(this);
@ -225,7 +245,13 @@ public class AutoSettleService extends Service {
String bitmap = BitmapConfig.BPC_SETTLEMENT; String bitmap = BitmapConfig.BPC_SETTLEMENT;
payDetail.setTransType(TransactionsType.SETTLEMENT.name); payDetail.setTransType(TransactionsType.SETTLEMENT.name);
payDetail.setTransactionType(TransactionType.SETTLEMENT); payDetail.setTransactionType(TransactionType.SETTLEMENT);
payDetail.setProcessCode(TransactionsType.SETTLEMENT.processCode); if(!flag) {
payDetail.setProcessCode(TransactionsType.SETTLEMENT.processCode);
} else {
bitmap = BitmapConfig.BPC_SETTLEMENT_TRAILER;
payDetail.setProcessCode("910000");
}
payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum()); payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum());
SettleData settleData = new SettleData( SettleData settleData = new SettleData(
@ -245,6 +271,14 @@ public class AutoSettleService extends Service {
} else { } else {
settlementData = "C" + String.format(Locale.getDefault(), "%012d", totalAmount); settlementData = "C" + String.format(Locale.getDefault(), "%012d", totalAmount);
} }
if(totalAmount == 0 && (saleCount == 0 || preCount == 0 || refundCount == 0 || caCount == 0)) {
posSettlementReady = true;
posHasData = false;
checkAndLaunch();
checkIfBothSettlementsComplete();
return;
}
payDetail.setSettleData(settlementData); payDetail.setSettleData(settlementData);
payDetail.setAmount(totalAmount); payDetail.setAmount(totalAmount);
@ -269,7 +303,7 @@ public class AutoSettleService extends Service {
if (TextUtils.equals(resultStr, Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, Constant.ANSWER_CODE_APPROVED)) { if (TextUtils.equals(resultStr, Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, Constant.ANSWER_CODE_APPROVED)) {
payDetail.setIsNeedReversal(false); payDetail.setIsNeedReversal(false);
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) { } else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
payDetail.setIsNeedReversal(true); payDetail.setIsNeedReversal(!flag);
} }
} }
} }
@ -284,34 +318,25 @@ public class AutoSettleService extends Service {
public void onComplete() { public void onComplete() {
LogUtil.d(TAG, "Auto settlement transaction completed successfully"); LogUtil.d(TAG, "Auto settlement transaction completed successfully");
if (list != null && !list.isEmpty()) { if(payDetail.getIsNeedReversal()) {
for (PayDetail p : list) { flag = true;
repository.deletePayDetail(p); batchUploadProcess();
} else {
flag = false;
if (!list.isEmpty()) {
for (PayDetail p : list) {
repository.deletePayDetail(p);
}
} }
repository.insertPayDetail(payDetail);
networkCutOver(payDetail);
} }
repository.insertPayDetail(payDetail);
try {
PayDetail cleanPayDetail = new PayDetail();
cleanPayDetail.setTransType(payDetail.getTransType());
cleanPayDetail.setTransactionType(payDetail.getTransactionType());
cleanPayDetail.setProcessCode(payDetail.getProcessCode());
cleanPayDetail.setBatchNo(payDetail.getBatchNo());
cleanPayDetail.setSettleData(payDetail.getSettleData());
cleanPayDetail.setAmount(payDetail.getAmount());
cleanPayDetail.setTradeAnswerCode(payDetail.getTradeAnswerCode());
cleanPayDetail.setIsNeedReversal(payDetail.getIsNeedReversal());
// Use notification-based approach to reliably launch the app
launchAppWithSettlementResult("AUTO_SETTLEMENT", cleanPayDetail, null);
} catch (Exception e) {
LogUtil.e(TAG, "Error launching app with settlement result: " + e.getMessage());
e.printStackTrace();
} }
checkIfBothSettlementsComplete();
}
}); });
} }
}; };
@ -319,6 +344,41 @@ public class AutoSettleService extends Service {
repository.getSettlementPOS().observeForever(regularSettlementObserver); repository.getSettlementPOS().observeForever(regularSettlementObserver);
} }
private void batchUploadProcess() {
if(payDetails == null || payDetails.isEmpty()){
regularSettlementCompleted = false;
performSettlement();
return;
}
PayDetail payDetail = payDetails.get(i);
TradeData tradeData = new TradeData();
tradeData.setPayDetail(payDetail);
BatchUploadProcess.getInstance().enqueue(tradeData).startBatchUpload(new BatchListener() {
@Override
public void onSuccessBatch() {
if (i < payDetails.size() - 1) {
LogUtil.d(TAG, "Pay detail Size:" + payDetails.size());
LogUtil.d(TAG, "Count value:" + i);
i++;
batchUploadProcess();
} else {
regularSettlementCompleted = false;
performSettlement();
}
LogUtil.e(TAG, "Batch Upload Success");
}
@Override
public void onFailBatch() {
LogUtil.e(TAG, "Batch Upload Fail");
}
});
}
private void performQRSettlement() { private void performQRSettlement() {
if (qrSettlementCompleted) { if (qrSettlementCompleted) {
return; return;
@ -365,6 +425,9 @@ public class AutoSettleService extends Service {
} }
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
LogUtil.e(TAG, "QR Auto Settlement: Database cursor error - likely due to large data size: " + e); LogUtil.e(TAG, "QR Auto Settlement: Database cursor error - likely due to large data size: " + e);
qrSettlementReady = true;
qrHasData = false;
checkAndLaunch();
checkIfBothSettlementsComplete(); checkIfBothSettlementsComplete();
return; return;
} }
@ -422,19 +485,24 @@ public class AutoSettleService extends Service {
qrData.putLong("QR_TOTAL_AMOUNT", totalAmount); qrData.putLong("QR_TOTAL_AMOUNT", totalAmount);
qrData.putSerializable("QR_TRANS_LIST", qrTransactionsList); qrData.putSerializable("QR_TRANS_LIST", qrTransactionsList);
// Use notification-based approach to reliably launch the app // Use notification-based approach to reliably launch the app
launchAppWithSettlementResult("AUTO_QR_SETTLEMENT", null, qrData); pendingQrData = qrData;
qrHasData = true;
// launchAppWithSettlementResult("AUTO_QR_SETTLEMENT", null, qrData,false);
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Error launching app for QR settlement: " + e.getMessage()); LogUtil.e(TAG, "Error launching app for QR settlement: " + e.getMessage());
qrHasData = false;
e.printStackTrace(); e.printStackTrace();
} }
LogUtil.d(TAG, "QR Auto Settlement completed successfully"); LogUtil.d(TAG, "QR Auto Settlement completed successfully");
} else { } else {
LogUtil.d(TAG, "No QR transactions found for auto settlement"); LogUtil.d(TAG, "No QR transactions found for auto settlement");
qrHasData = false;
} }
} }
qrSettlementReady = true;
checkAndLaunch();
checkIfBothSettlementsComplete(); checkIfBothSettlementsComplete();
} }
}; };
@ -448,7 +516,7 @@ public class AutoSettleService extends Service {
stopSelf(); stopSelf();
} }
} }
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -480,69 +548,120 @@ public class AutoSettleService extends Service {
} }
private void launchAppWithSettlementResult(String settlementType, private void networkCutOver(PayDetail payDetail) {
PayDetail payDetail, EchoTestProcess.getInstance().enqueueCutOver().startSignOn(new SignOnListener() {
Bundle qrData) { @Override
public void onSuccessSignOn() {
pendingPayDetail = payDetail;
posHasData = true;
posSettlementReady = true;
checkAndLaunch();
checkIfBothSettlementsComplete();
}
@Override
public void onFailureSignOn(Integer resultCode) {
LogUtil.d(TAG,"Failure Cut Over message: "+resultCode);
// POS done but cutover failed — still mark ready
posSettlementReady = true;
posHasData = false;
checkAndLaunch();
checkIfBothSettlementsComplete();
}
@Override
public void onNetworkFailSignOn(String message) {
LogUtil.d(TAG,"Network Fail Cut Over message: "+message);
posSettlementReady = true;
posHasData = false;
checkAndLaunch();
checkIfBothSettlementsComplete();
}
});
}
private void checkAndLaunch() {
// !!!! need to add flag, if don't want both at once
if (!posSettlementReady || !qrSettlementReady) {
LogUtil.d(TAG, "Waiting for both settlements... POS=" + posSettlementReady + " QR=" + qrSettlementReady);
return;
}
LogUtil.d(TAG, "Both settlements ready. POS has data=" + posHasData + ", QR has data=" + qrHasData);
if (!posHasData && !qrHasData) {
LogUtil.d(TAG, "No settlement data to display");
return;
}
launchMainActivity();
}
private void launchMainActivity() {
try { try {
Intent launchIntent = new Intent(this, MainActivity.class); Intent launchIntent = new Intent(this, MainActivity.class);
launchIntent.putExtra(settlementType, true); launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP |
if ("AUTO_SETTLEMENT".equals(settlementType) && payDetail != null) { Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (posHasData && pendingPayDetail != null) {
launchIntent.putExtra("AUTO_SETTLEMENT", true);
launchIntent.putExtra("EXTRA_TRANSACTION_TYPE", TransactionsType.SETTLEMENT.value); launchIntent.putExtra("EXTRA_TRANSACTION_TYPE", TransactionsType.SETTLEMENT.value);
launchIntent.putExtra("EXTRA_PAY_DETAIL", payDetail); launchIntent.putExtra("EXTRA_PAY_DETAIL", pendingPayDetail);
} else if ("AUTO_QR_SETTLEMENT".equals(settlementType) && qrData != null) { }
launchIntent.putExtra("EXTRA_TRANSACTION_TYPE", TransactionsType.MMQR_SETTLEMENT.value);
launchIntent.putExtras(qrData); if (qrHasData && pendingQrData != null) {
launchIntent.putExtra("AUTO_QR_SETTLEMENT", true);
launchIntent.putExtra("EXTRA_QR_TRANSACTION_TYPE", TransactionsType.MMQR_SETTLEMENT.value);
launchIntent.putExtras(pendingQrData);
} }
PendingIntent pendingIntent = PendingIntent.getActivity( PendingIntent pendingIntent = PendingIntent.getActivity(
this, this,
(int) System.currentTimeMillis(), (int) System.currentTimeMillis(),
launchIntent, launchIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
); );
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel( NotificationChannel channel = new NotificationChannel(
"SETTLEMENT_COMPLETE", "SETTLEMENT_COMPLETE", "Settlement Complete", NotificationManager.IMPORTANCE_HIGH);
"Settlement Complete",
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("Auto settlement completion notifications"); channel.setDescription("Auto settlement completion notifications");
notificationManager.createNotificationChannel(channel); notificationManager.createNotificationChannel(channel);
} }
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "SETTLEMENT_COMPLETE") NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "SETTLEMENT_COMPLETE")
.setSmallIcon(R.drawable.ic_launcher_foreground) .setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Auto Settlement Complete") .setContentTitle("Auto Settlement Complete")
.setContentText("Tap to view settlement results and print receipt") .setContentText("Tap to view settlement results and print receipt")
.setPriority(NotificationCompat.PRIORITY_HIGH) .setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true) .setAutoCancel(true)
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setFullScreenIntent(pendingIntent, true); .setFullScreenIntent(pendingIntent, true);
notificationManager.notify(2001, builder.build()); notificationManager.notify(2001, builder.build());
LogUtil.d(TAG, " Settlement complete notification created - will launch app when tapped"); // Reset state
pendingPayDetail = null;
try { pendingQrData = null;
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | posSettlementReady = false;
Intent.FLAG_ACTIVITY_CLEAR_TOP | qrSettlementReady = false;
Intent.FLAG_ACTIVITY_SINGLE_TOP | posHasData = false;
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | qrHasData = false;
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(launchIntent); startActivity(launchIntent);
} catch (Exception directException) {
LogUtil.d(TAG, "Direct launch failed (expected on modern Android), notification approach will handle it");
}
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Error creating settlement notification: " + e.getMessage()); LogUtil.e(TAG, "Error launching MainActivity: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
} }
} }
private void sendEReceipt(EReceiptRequest request) { private void sendEReceipt(EReceiptRequest request) {
try { try {
LogUtil.d(TAG, "Sending e-receipt: " + new Gson().toJson(request)); LogUtil.d(TAG, "Sending e-receipt: " + new Gson().toJson(request));

View File

@ -13,6 +13,7 @@ import androidx.navigation.Navigation;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.stream.MalformedJsonException; import com.google.gson.stream.MalformedJsonException;
import com.utsmm.kbz.MainActivity;
import com.utsmm.kbz.config.Constants; import com.utsmm.kbz.config.Constants;
import com.nexgo.downloadkey.downloadflow.DownloadFEntity; import com.nexgo.downloadkey.downloadflow.DownloadFEntity;
import com.nexgo.downloadkey.downloadflow.DownloadFlow; import com.nexgo.downloadkey.downloadflow.DownloadFlow;
@ -162,6 +163,10 @@ public class SettingsFragment extends DataBindingFragment {
} }
private void updateReversalSettings() { private void updateReversalSettings() {
boolean isVisible = SystemParamsOperation.getInstance().getAutoReversalEnable();
LogUtil.d("SettingsFragment", "isVisible " + isVisible);
binding.reversalCard.setVisibility(isVisible ? View.VISIBLE : View.GONE);
boolean isEnabled = SystemParamsOperation.getInstance().isReversalOn(); boolean isEnabled = SystemParamsOperation.getInstance().isReversalOn();
binding.reversalSwitch.setChecked(isEnabled); binding.reversalSwitch.setChecked(isEnabled);
binding.reversalSummary.setText(isEnabled ? binding.reversalSummary.setText(isEnabled ?
@ -327,6 +332,17 @@ public class SettingsFragment extends DataBindingFragment {
} }
} }
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() { public void onTmsConfigClick() {
try { try {
LogUtil.d(TAG, "TMS Config clicked"); LogUtil.d(TAG, "TMS Config clicked");
@ -393,6 +409,9 @@ public class SettingsFragment extends DataBindingFragment {
private void downloadParams(String lastTransName, String lastTransTime) { private void downloadParams(String lastTransName, String lastTransTime) {
try { try {
LogUtil.d(TAG, "Downloading params for transaction: " + lastTransName); LogUtil.d(TAG, "Downloading params for transaction: " + lastTransName);
((MainActivity) requireActivity()).getLocation();
SiriusRequest siriusReq = TMSUtil.getInstance().generateRequestParams(getContext(), lastTransName, lastTransTime); SiriusRequest siriusReq = TMSUtil.getInstance().generateRequestParams(getContext(), lastTransName, lastTransTime);
mainViewModel.getParams(siriusReq) mainViewModel.getParams(siriusReq)

View File

@ -151,6 +151,12 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
}else if(sharedViewModel.getIsSeePhone().getValue() != null && sharedViewModel.getIsSeePhone().getValue()) { }else if(sharedViewModel.getIsSeePhone().getValue() != null && sharedViewModel.getIsSeePhone().getValue()) {
cardReadViewModel.setCheckCardAlertMsg("Please Tap!",false); cardReadViewModel.setCheckCardAlertMsg("Please Tap!",false);
setupCardReadProcess(true); 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 { } else {
setupCardReadProcess(false); setupCardReadProcess(false);
} }
@ -163,6 +169,7 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
sharedViewModel.setIsFallback(false); sharedViewModel.setIsFallback(false);
sharedViewModel.setIsSeePhone(false); sharedViewModel.setIsSeePhone(false);
sharedViewModel.setIsContactlessRestricted(false);
// cardReadViewModel.cancelCheckCard(); // cardReadViewModel.cancelCheckCard();
@ -256,9 +263,20 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
if(sharedViewModel.getIsSeePhone().getValue() != null && sharedViewModel.getIsSeePhone().getValue()) { if(sharedViewModel.getIsSeePhone().getValue() != null && sharedViewModel.getIsSeePhone().getValue()) {
allType.add(CardSlotTypeEnum.RF); allType.add(CardSlotTypeEnum.RF);
waitTimeout = 20; waitTimeout = 20;
} else { } 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.ICC1);
allType.add(CardSlotTypeEnum.RF); allType.add(CardSlotTypeEnum.RF);
if(SystemParamsOperation.getInstance().isMagStripeEnabled()) {
allType.add(CardSlotTypeEnum.SWIPE);
}
} }
// int allType = AidlConstants.CardType.IC.getValue() | AidlConstants.CardType.MAGNETIC.getValue(); // int allType = AidlConstants.CardType.IC.getValue() | AidlConstants.CardType.MAGNETIC.getValue();
@ -286,7 +304,7 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
} else if (isFallback && cardType == CardTypeX.MAG) { } else if (isFallback && cardType == CardTypeX.MAG) {
/* do fallback transactions */ /* do fallback transactions */
sharedViewModel.isEmv.setValue(false); sharedViewModel.isEmv.postValue(false);
cardReadViewModel.setCardTransactionType(CardTransactionType.FALLBACK); cardReadViewModel.setCardTransactionType(CardTransactionType.FALLBACK);
} else if (cardType == CardTypeX.IC || cardType == CardTypeX.NFC) { } else if (cardType == CardTypeX.IC || cardType == CardTypeX.NFC) {

View File

@ -246,7 +246,6 @@ public class ConfirmTransactionFragment extends DataBindingFragment implements D
public void onConfirm(){ public void onConfirm(){
if (sharedViewModel.transactionsType.getValue() == TransactionsType.TIP_ADJUSTMENT) { if (sharedViewModel.transactionsType.getValue() == TransactionsType.TIP_ADJUSTMENT) {
routeId = R.id.action_confirmTransactionFragment_to_inputTipAmountFragment; routeId = R.id.action_confirmTransactionFragment_to_inputTipAmountFragment;
safeNavigateToRouteId(); safeNavigateToRouteId();

View File

@ -3,6 +3,7 @@ package com.utsmm.kbz.ui.core_ui;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -158,6 +159,7 @@ public class EmvTransactionFragment extends DataBindingFragment {
} }
observeEmvResultStatus(); observeEmvResultStatus();
observePinWarning();
} }
private boolean isNotManualTransaction() { private boolean isNotManualTransaction() {
@ -230,7 +232,19 @@ public class EmvTransactionFragment extends DataBindingFragment {
case ON_NEXT_SCREEN: case ON_NEXT_SCREEN:
navigateToRRNScreen(); navigateToRRNScreen();
break; 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: case READ_CARD_RETRY:
LogUtil.d(TAG,"Card type :"+cardReadViewModel.cardTypeData.getValue());
if(cardReadViewModel.cardTypeData.getValue()!= null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.IC.value) { if(cardReadViewModel.cardTypeData.getValue()!= null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.IC.value) {
isCardInserted(new CardDetectCallback() { isCardInserted(new CardDetectCallback() {
@Override @Override
@ -243,12 +257,30 @@ public class EmvTransactionFragment extends DataBindingFragment {
isCardTaped("Please try again",new CardDetectCallback() { isCardTaped("Please try again",new CardDetectCallback() {
@Override @Override
public void onComplete() { public void onComplete() {
sharedViewModel.setIsSeePhone(true); 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(); navigateToCheckCard();
} }
}); });
} }
// sharedViewModel.set_errorFragmentMsg("Interface not found!"); // sharedViewModel.set_errorFragmentMsg("Interface not found!");
// navigateToError(); // navigateToError();
break; break;
@ -330,6 +362,15 @@ 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() { private void observeEmvErrorCode() {
dismissLoadingDialog(); dismissLoadingDialog();
emvTransactionViewModel.errorCodeMsg.observe(getViewLifecycleOwner(), pair -> { emvTransactionViewModel.errorCodeMsg.observe(getViewLifecycleOwner(), pair -> {

View File

@ -201,7 +201,7 @@ public class InputRRNFragment extends DataBindingFragment {
private void checkRRNPreAuthVoid(boolean isECR) { private void checkRRNPreAuthVoid(boolean isECR) {
rrnViewModel.searchPayDetail(cardNo,rrnNo).observe(getViewLifecycleOwner(), new Observer<PayDetail>() { rrnViewModel.searchPayDetailPreCancel(cardNo,rrnNo).observe(getViewLifecycleOwner(), new Observer<PayDetail>() {
@Override @Override
public void onChanged(PayDetail payDetail) { public void onChanged(PayDetail payDetail) {
if(payDetail != null) { if(payDetail != null) {
@ -245,6 +245,8 @@ public class InputRRNFragment extends DataBindingFragment {
} else { } else {
LogUtil.d(TAG,"PreAuth Cancel RRN not found!");
terminateProcess(isECR); terminateProcess(isECR);
} }
@ -551,16 +553,16 @@ public class InputRRNFragment extends DataBindingFragment {
// } // }
} else { } else {
terminatedTransRefund(isECR); // terminatedTransRefund(isECR);
// PayDetail newPay = transProcessViewModel.getPayDetail(); PayDetail newPay = transProcessViewModel.getPayDetail();
// newPay.setReferNo(rrnNo); newPay.setReferNo(rrnNo);
//
// transProcessViewModel.setPayDetail(newPay); transProcessViewModel.setPayDetail(newPay);
//
// sharedViewModel.rrNNo.setValue(rrnNo); sharedViewModel.rrNNo.setValue(rrnNo);
//
// callNextScreen(); callNextScreen();
} }
} }

View File

@ -173,6 +173,7 @@ public class InputTraceNoFragment extends DataBindingFragment {
} }
sharedViewModel.payDetail.setValue(payDetail); sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount()));
if(sharedViewModel.hostType.getValue() == HostType.MPU) { if(sharedViewModel.hostType.getValue() == HostType.MPU) {
boolean isMpu = "MPU".equals(payDetail.getAccountType()); boolean isMpu = "MPU".equals(payDetail.getAccountType());

View File

@ -131,6 +131,7 @@ public class ProcessingCardFragment extends DataBindingFragment {
} }
private void mockMPUCard() { private void mockMPUCard() {
LogUtil.d(TAG,"initialize mock card data..."); LogUtil.d(TAG,"initialize mock card data...");
sharedViewModel.isEmv.setValue(false);
routeId = R.id.action_processingCardFragment_to_pinPadFragment; routeId = R.id.action_processingCardFragment_to_pinPadFragment;
transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue()); transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
pinPadViewModel.transType.setValue(sharedViewModel.transactionsType.getValue()); pinPadViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
@ -159,6 +160,7 @@ public class ProcessingCardFragment extends DataBindingFragment {
return; return;
} }
} }
sharedViewModel.isEmv.setValue(false);
routeId = R.id.action_processingCardFragment_to_pinPadFragment; routeId = R.id.action_processingCardFragment_to_pinPadFragment;
transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue()); transProcessViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
@ -168,12 +170,29 @@ public class ProcessingCardFragment extends DataBindingFragment {
transProcessViewModel.setTradeData(tradeData); transProcessViewModel.setTradeData(tradeData);
pinPadViewModel.setTradeData(tradeData); pinPadViewModel.setTradeData(tradeData);
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_VOID ) { if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_VOID && SystemParamsOperation.getInstance().getPreAuthVoidManualEnabled() ) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel)); sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment; routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId(); safeNavigateToRouteId();
return; return;
}
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_SALE && SystemParamsOperation.getInstance().getPreAuthManualEnabled()) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId();
return;
}
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_COMPLETE && SystemParamsOperation.getInstance().getPreAuthCompleteManualEnabled()) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId();
return;
} }
// else if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND) { // else if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND) {
// sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_card_not_supported)); // sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_card_not_supported));
@ -183,7 +202,9 @@ public class ProcessingCardFragment extends DataBindingFragment {
sharedViewModel.setCardDataExist(true); sharedViewModel.setCardDataExist(true);
if(sharedViewModel.getAmountExist().getValue() != null && !sharedViewModel.getAmountExist().getValue()) { if(sharedViewModel.getTransMenu().getValue() != TransMenu.PRE_AUTH_FULL_VOID
&& sharedViewModel.getAmountExist().getValue() != null
&& !sharedViewModel.getAmountExist().getValue()) {
routeId = R.id.action_processingCardFragment_to_inputAmountFragment; routeId = R.id.action_processingCardFragment_to_inputAmountFragment;
} }
@ -238,13 +259,28 @@ public class ProcessingCardFragment extends DataBindingFragment {
transProcessViewModel.setTradeData(tradeData); transProcessViewModel.setTradeData(tradeData);
} }
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_VOID && SystemParamsOperation.getInstance().getPreAuthVoidManualEnabled() ) {
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_VOID ) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel)); sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment; routeId = R.id.action_processingCardFragment_to_errorFragment;
} }
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_SALE && SystemParamsOperation.getInstance().getPreAuthManualEnabled()) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment;
}
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_COMPLETE && SystemParamsOperation.getInstance().getPreAuthCompleteManualEnabled()) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment;
}
// else if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND) { // else if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND) {
// routeId = R.id.action_processingCardFragment_to_errorFragment; // routeId = R.id.action_processingCardFragment_to_errorFragment;
// } // }
@ -274,8 +310,39 @@ public class ProcessingCardFragment extends DataBindingFragment {
emvTransactionViewModel.transType.setValue(sharedViewModel.transactionsType.getValue()); emvTransactionViewModel.transType.setValue(sharedViewModel.transactionsType.getValue());
if (SystemParamsOperation.getInstance().isEmvEnabled()) { if (SystemParamsOperation.getInstance().isEmvEnabled()) {
prepareEmvTransaction(); prepareEmvTransaction();
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_VOID && SystemParamsOperation.getInstance().getPreAuthVoidManualEnabled() ) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId();
return;
}
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_SALE && SystemParamsOperation.getInstance().getPreAuthManualEnabled()) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId();
return;
}
if(sharedViewModel.getTransactionsType().getValue() == TransactionsType.PRE_AUTH_COMPLETE && SystemParamsOperation.getInstance().getPreAuthCompleteManualEnabled()) {
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_alert_pre_auth_cancel));
routeId = R.id.action_processingCardFragment_to_errorFragment;
safeNavigateToRouteId();
return;
}
routeId = R.id.action_processingCardFragment_to_emvTransactionFragment; routeId = R.id.action_processingCardFragment_to_emvTransactionFragment;
} else { } else {
routeId = R.id.action_processingCardFragment_to_errorFragment; routeId = R.id.action_processingCardFragment_to_errorFragment;
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_please_enable_emv)); sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_please_enable_emv));
@ -307,9 +374,7 @@ public class ProcessingCardFragment extends DataBindingFragment {
LogUtil.d(TAG,"card type:"+cardType); LogUtil.d(TAG,"card type:"+cardType);
LogUtil.d(TAG,"is MPU:"+isMPU); LogUtil.d(TAG,"is MPU:"+isMPU);
// delayFunctionCall(()->{
//
// });
handlePreEmvProcess(); handlePreEmvProcess();
} }

View File

@ -6,6 +6,8 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDestination; import androidx.navigation.NavDestination;
@ -17,6 +19,11 @@ import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest; import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig; import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TimeoutCallback; 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.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR; import com.utsmm.kbz.BR;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
@ -104,6 +111,17 @@ public class ProcessingFragment extends DataBindingFragment {
setToolBarTitleWithoutBackIcon(getResourceString(R.string.title_processing)); setToolBarTitleWithoutBackIcon(getResourceString(R.string.title_processing));
checkReversal();
// disableNavigationBar();
getNavController(Constants.NAV_HOST_ID).addOnDestinationChangedListener(listener);
}
private void startTransactionProcess() {
if(isEmvTrans()) { if(isEmvTrans()) {
startTransactionProcess(emvTransactionProcessViewModel); startTransactionProcess(emvTransactionProcessViewModel);
} else { } else {
@ -111,13 +129,55 @@ public class ProcessingFragment extends DataBindingFragment {
} }
sharedViewModel.loadingMsg(getResourceString(R.string.txt_sending)); 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() { private boolean isEmvTrans() {
return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue(); return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue();
} }
@ -258,6 +318,18 @@ public class ProcessingFragment extends DataBindingFragment {
safeNavigateToRouteId(); safeNavigateToRouteId();
} }
private void handleAfterTransaction() {
if (SystemParamsOperation.getInstance().getDemoStatus()) {
delayFunctionCall(() -> {
sharedViewModel.dismissLoadingMsg();
callNextScreen();
}, 1500);
} else {
sharedViewModel.dismissLoadingMsg();
callNextScreen();
}
}
private void observeData(ProcessingTransaction processingTransaction) { private void observeData(ProcessingTransaction processingTransaction) {
processingTransaction.getTransStatus().observe(getViewLifecycleOwner(), transResultStatus -> { processingTransaction.getTransStatus().observe(getViewLifecycleOwner(), transResultStatus -> {
@ -269,9 +341,13 @@ public class ProcessingFragment extends DataBindingFragment {
switch (transResultStatus) { switch (transResultStatus) {
case FAIL: case FAIL:
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, false, "FAILED")); sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, false, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
handleAfterTransaction();
break;
case SUCCESS: case SUCCESS:
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, "SUCCESS")); sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, true, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
handleAfterTransaction();
break;
case OFFLINE_SUCCESS: case OFFLINE_SUCCESS:
if(SystemParamsOperation.getInstance().getDemoStatus()) { if(SystemParamsOperation.getInstance().getDemoStatus()) {
delayFunctionCall(()->{ delayFunctionCall(()->{
@ -288,6 +364,7 @@ public class ProcessingFragment extends DataBindingFragment {
break; break;
case OFFLINE_FAILURE: case OFFLINE_FAILURE:
sharedViewModel.pushReceipt(buildEReceiptCardReceipt(payDetail, false, BaseErrorCode.getCode(payDetail.getTradeAnswerCode())));
sharedViewModel.dismissLoadingMsg(); sharedViewModel.dismissLoadingMsg();
sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_offline_failure)); sharedViewModel.set_errorFragmentMsg(getResourceString(R.string.txt_offline_failure));
navigateToError(); navigateToError();
@ -385,20 +462,6 @@ public class ProcessingFragment extends DataBindingFragment {
}); });
} }
private String mapDE3ToShortCode(String de3) {
if (de3 == null) return "UNK";
switch (de3) {
case "000000": return "S"; // Sale
case "020000": return "V"; // Void
case "200000": return "R"; // Refund
case "030000": return "P"; // Preauth
case "310000": return "PC"; // Preauth Complete
}
return "UNK"; // Unknown
}
public static String mapTransactionType(int type) { public static String mapTransactionType(int type) {
switch (type) { switch (type) {
case 1: // SALE case 1: // SALE
@ -450,6 +513,16 @@ public class ProcessingFragment extends DataBindingFragment {
default: return currency; // Already alphabetic? return as-is 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){ private EReceiptCardRequest buildEReceiptCardReceipt(PayDetail payDetail, boolean isSuccess, String reason){
//current timestamp //current timestamp
String currentTimestamp = new java.text.SimpleDateFormat( String currentTimestamp = new java.text.SimpleDateFormat(
@ -467,16 +540,30 @@ public class ProcessingFragment extends DataBindingFragment {
double realAmount = payDetail.getAmount() / 100.0; double realAmount = payDetail.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00"); DecimalFormat df = new DecimalFormat("0.00");
String amount = df.format(realAmount); 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(); EReceiptCardRequest request = new EReceiptCardRequest();
request.setDE2(payDetail.getCardNo()); request.setDE2(PrintUtils.getInstance().maskCardNumberPciDss(payDetail.getCardNo()));
request.setDE3(mapDE3ToShortCode(payDetail.getProcessCode())); request.setDE3(mapTransactionType(payDetail.getTransactionType()));
request.setDE4(amount); request.setDE4(amount);
request.setDE7(currentTimestamp); request.setDE7(currentTimestamp);
request.setDE11(payDetail.getVoucherNo()); request.setDE11(payDetail.getVoucherNo());
request.setDE22(mapTransactionType(payDetail.getTransactionType())); // request.setDE22(mapTransactionType(payDetail.getTransactionType()));
request.setDE22(PrintUtils.getInstance().getEntryType(payDetail.getCardType()));
request.setDE37(payDetail.getReferNo()); request.setDE37(payDetail.getReferNo());
request.setDE38(payDetail.getAuthNo()); request.setDE38(payDetail.getApprovalCode());
request.setDE39(isSuccess ? "A" : "E"); request.setDE39(isSuccess ? "A" : "E");
request.setDE41(terminalId); request.setDE41(terminalId);
request.setDE42(merchantId); request.setDE42(merchantId);
@ -485,6 +572,12 @@ public class ProcessingFragment extends DataBindingFragment {
request.setInvoiceNumber(payDetail.getInvoiceNo()); request.setInvoiceNumber(payDetail.getInvoiceNo());
request.setAppId(appId); request.setAppId(appId);
request.setDescription(reason); 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());
return request; return request;
} }

View File

@ -10,6 +10,8 @@ import androidx.appcompat.app.AppCompatActivity;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.MalformedJsonException; 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.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusError; import com.utsmyanmar.baselib.network.model.sirius.SiriusError;
@ -156,6 +158,8 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
return; return;
} }
((MainActivity) requireActivity()).getLocation();
SiriusRequest siriusReq = TMSUtil.getInstance().generateRequestParams( SiriusRequest siriusReq = TMSUtil.getInstance().generateRequestParams(
getContext(), getContext(),
payDetail.getTransType(), payDetail.getTransType(),
@ -331,6 +335,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
sharedViewModel.startPrintSettlement(new PrintXStatus() { sharedViewModel.startPrintSettlement(new PrintXStatus() {
@Override @Override
public void onSuccess() { public void onSuccess() {
sharedViewModel.onSettlementResultDone.postValue(true);
isCardInside(); isCardInside();
} }

View File

@ -78,13 +78,21 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
break; break;
} }
try { try {
if (mPayDetail.PINCipher != null && !mPayDetail.PINCipher.isEmpty()) { 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");
emvHandler.onSetPinInputResponse(true, false); emvHandler.onSetPinInputResponse(true, false);
} else if (isOfflinePinEntered) { } else if(isOfflinePinEntered){
emvHandler.onSetPinInputResponse(true, false); LogUtil.d("EmvTransactionProcessViewModel", "condition 2");
} else {
emvHandler.onSetPinInputResponse(true, false); emvHandler.onSetPinInputResponse(true, false);
}else {
LogUtil.d("EmvTransactionProcessViewModel", "condition 3");
emvHandler.onSetPinInputResponse(true, true);
} }
if (transType.getValue() == TransactionsType.PRE_AUTH_COMPLETE || transType.getValue() == TransactionsType.PRE_AUTH_VOID || transType.getValue() == TransactionsType.REFUND) { if (transType.getValue() == TransactionsType.PRE_AUTH_COMPLETE || transType.getValue() == TransactionsType.PRE_AUTH_VOID || transType.getValue() == TransactionsType.REFUND) {
emvResultStatus.postValue(EmvResultStatus.ON_NEXT_SCREEN); emvResultStatus.postValue(EmvResultStatus.ON_NEXT_SCREEN);
} }
@ -162,7 +170,13 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
handleTransactionFail(msg.arg1, msg.obj.toString()); handleTransactionFail(msg.arg1, msg.obj.toString());
break; break;
case EMV_TRY_AGAIN: case EMV_TRY_AGAIN:
emvResultStatus.postValue(EmvResultStatus.READ_CARD); 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);
break; break;
case EMV_CONFIRM_CODE_VERIFY: case EMV_CONFIRM_CODE_VERIFY:
emvResultStatus.postValue(EmvResultStatus.CONFIRM_CODE_VERIFY); emvResultStatus.postValue(EmvResultStatus.CONFIRM_CODE_VERIFY);
@ -443,8 +457,8 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
@Override @Override
public void processPreVoidDb(PayDetail payResult) { public void processPreVoidDb(PayDetail payResult) {
mPayDetail.setIsCanceled(true); oldTransPayDetail.setIsCanceled(true);
updatePayDetail(mPayDetail); updatePayDetail(oldTransPayDetail);
repository.insertPayDetail(updateCurrentDateAndTime(payResult)); repository.insertPayDetail(updateCurrentDateAndTime(payResult));
} }
@ -458,9 +472,11 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
if(oldTransPayDetail.getAmount() == payResult.getAmount()) { if(oldTransPayDetail.getAmount() == payResult.getAmount()) {
oldTransPayDetail.setIsCanceled(true); oldTransPayDetail.setIsCanceled(true);
oldTransPayDetail.setAdjust(true);
updatePayDetail(oldTransPayDetail); updatePayDetail(oldTransPayDetail);
} else { } else {
oldTransPayDetail.setIsCanceled(false); oldTransPayDetail.setIsCanceled(false);
oldTransPayDetail.setAdjust(true);
updatePayDetail(oldTransPayDetail); updatePayDetail(oldTransPayDetail);
} }
repository.insertPayDetail(updateCurrentDateAndTime(payResult)); repository.insertPayDetail(updateCurrentDateAndTime(payResult));

View File

@ -13,112 +13,109 @@ import java.util.Objects;
public class InputAmountViewModel extends ViewModel { public class InputAmountViewModel extends ViewModel {
private static final String TAG = InputAmountViewModel.class.getSimpleName();
public MutableLiveData<String> inputAmountView = new MutableLiveData<>(); public MutableLiveData<String> inputAmountView = new MutableLiveData<>();
public SingleLiveEvent<String> invalidAmountMsg = new SingleLiveEvent<>(); public SingleLiveEvent<String> invalidAmountMsg = new SingleLiveEvent<>();
public SingleLiveEvent<String> availableAmount = 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() { public InputAmountViewModel() {
inputAmountView.setValue("0"); inputAmountView.setValue("0");
} }
private int countDecimalDigits(double number) { private String formatInteger(String value) {
String numberStr = Double.toString(number); if (TextUtils.isEmpty(value)) return "0";
int decimalIndex = numberStr.indexOf('.'); double amt = Double.parseDouble(value);
return decimalIndex >= 0 ? numberStr.length() - decimalIndex - 1 : 0; DecimalFormat formatter = new DecimalFormat("#,###");
return formatter.format(amt);
} }
public NumberKeyboard.KeyClickCallback onKeyClick() { public NumberKeyboard.KeyClickCallback onKeyClick() {
return new NumberKeyboard.KeyClickCallback() { return new NumberKeyboard.KeyClickCallback() {
@Override @Override
public void onNumClick(int keyNum) { public void onNumClick(int keyNum) {
if (inputAmountView.getValue().length() == 15) { String current = inputAmountView.getValue();
return; if (current == null) return;
}
if (TextUtils.equals(inputAmountView.getValue(), "0")) { String raw = current.replace(",", "");
inputAmountView.setValue(keyNum + "");
} else if (inputAmountView.getValue().contains(".")) {
StringBuilder inputAmount = new StringBuilder();
inputAmount.append(inputAmountView.getValue());
int dotIndex = inputAmount.indexOf("."); if (raw.contains(".")) {
if(inputAmount.substring(dotIndex).length() > 0 && inputAmount.substring(dotIndex+1).length() == 2) { String[] parts = raw.split("\\.");
String intPart = parts[0];
String decimalPart = parts.length > 1 ? parts[1] : "";
if (decimalPart.length() >= MAX_DECIMAL_DIGITS) {
return; return;
} }
if (inputAmountView.getValue().contains(",")) { raw = raw + keyNum;
inputAmountView.setValue(inputAmountView.getValue().replace(",", ""));
}
double amt = Double.parseDouble(inputAmountView.getValue());
if (countDecimalDigits(amt) < 2) {
inputAmountView.setValue(inputAmountView.getValue() + keyNum);
}
} else { } else {
if (inputAmountView.getValue().contains(",")) {
inputAmountView.setValue(inputAmountView.getValue().replace(",", "")); if (raw.length() >= MAX_INT_DIGITS) {
return;
} }
inputAmountView.setValue(inputAmountView.getValue() + keyNum);
double amt = Double.parseDouble(inputAmountView.getValue()); if (TextUtils.equals(raw, "0")) {
DecimalFormat formatter = new DecimalFormat("#,###"); raw = String.valueOf(keyNum);
inputAmountView.setValue(formatter.format(amt)); } else {
raw = raw + keyNum;
}
}
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));
} }
} }
@Override @Override
public void onDelClick() { public void onDelClick() {
if (Objects.requireNonNull(inputAmountView.getValue()).contains(".")) {
return; String current = inputAmountView.getValue();
} if (current == null) return;
if (inputAmountView.getValue().length() == 15) {
return; if (current.contains(".")) return;
}
if (TextUtils.equals(inputAmountView.getValue(), "0")) { if (TextUtils.equals(current, "0")) {
inputAmountView.setValue("0."); inputAmountView.setValue("0.");
} else { } else {
inputAmountView.setValue(current + ".");
inputAmountView.setValue(inputAmountView.getValue() + ".");
} }
} }
@Override @Override
public void onCleanClick() { 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")) {
String currentValue = inputAmountView.getValue();
String rawNumber = currentValue.replace(",", ""); String current = inputAmountView.getValue();
if (current == null) return;
if (rawNumber.length() > 1) { String raw = current.replace(",", "");
rawNumber = rawNumber.substring(0, rawNumber.length() - 1);
double amt = Double.parseDouble(rawNumber); if (raw.length() <= 1) {
DecimalFormat formatter = new DecimalFormat("#,###"); inputAmountView.setValue("0");
inputAmountView.setValue(formatter.format(amt)); return;
} else { }
inputAmountView.setValue("0");
} 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,6 +41,12 @@ public class InputRRNViewModel extends ViewModel {
return repository.searchPayDetail(cardNo,rrn); return repository.searchPayDetail(cardNo,rrn);
} }
public LiveData<PayDetail> searchPayDetailPreCancel(String cardNo,String rrn) {
return repository.searchPayDetailPreCancel(cardNo,rrn);
}
public NumberKeyboard.KeyClickCallback onKeyClick(){ public NumberKeyboard.KeyClickCallback onKeyClick(){
return new NumberKeyboard.KeyClickCallback() { return new NumberKeyboard.KeyClickCallback() {

View File

@ -1,7 +1,9 @@
package com.utsmm.kbz.ui.core_viewmodel; package com.utsmm.kbz.ui.core_viewmodel;
import android.annotation.SuppressLint;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.util.Log; import android.util.Log;
import android.widget.ListView;
import dagger.hilt.android.lifecycle.HiltViewModel; import dagger.hilt.android.lifecycle.HiltViewModel;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
@ -73,7 +75,8 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent<String> transactionName = new SingleLiveEvent<>(); public SingleLiveEvent<String> transactionName = new SingleLiveEvent<>();
// In SharedViewModel
public MutableLiveData<Boolean> onSettlementResultDone = new MutableLiveData<>(false);
/*May 16 2022*/ /*May 16 2022*/
public SingleLiveEvent<Boolean> isEcr = new SingleLiveEvent<>(); public SingleLiveEvent<Boolean> isEcr = new SingleLiveEvent<>();
@ -161,10 +164,14 @@ public class SharedViewModel extends ViewModel {
public MutableLiveData<Integer> loadingView = new MutableLiveData<>(8); public MutableLiveData<Integer> loadingView = new MutableLiveData<>(8);
public SingleLiveEvent<String> loadingMsg = new SingleLiveEvent<>(); public SingleLiveEvent<String> loadingMsg = new SingleLiveEvent<>();
private final SingleLiveEvent<String> toastMsg = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isFallback = new SingleLiveEvent<>(); private SingleLiveEvent<Boolean> isFallback = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isSeePhone = 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<>(); private SingleLiveEvent<Boolean> _isCardDataExist = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> _isAmountExist = new SingleLiveEvent<>(); private SingleLiveEvent<Boolean> _isAmountExist = new SingleLiveEvent<>();
@ -233,10 +240,18 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent<Boolean> getIsFallback() { return isFallback;} 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 void setIsSeePhone(boolean status) { isSeePhone.setValue(status);}
public SingleLiveEvent<Boolean> getIsSeePhone() { return isSeePhone;} 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 void setCardDataExist(boolean exist) { _isCardDataExist.setValue(exist);}
public SingleLiveEvent<Boolean> getCardDataExist() { return _isCardDataExist; } public SingleLiveEvent<Boolean> getCardDataExist() { return _isCardDataExist; }
@ -288,6 +303,14 @@ public class SharedViewModel extends ViewModel {
loadingMsg.setValue(""); loadingMsg.setValue("");
} }
public SingleLiveEvent<String> getToastMsg() {
return toastMsg;
}
public void postToastMsg(String msg) {
toastMsg.postValue(msg);
}
public Observable<SiriusResponse> getParams(SiriusRequest siriusRequest) { public Observable<SiriusResponse> getParams(SiriusRequest siriusRequest) {
return repository.getParams(siriusRequest); return repository.getParams(siriusRequest);
} }
@ -441,6 +464,14 @@ public class SharedViewModel extends ViewModel {
return repository.getReversalTransaction(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); repository.updatePayDetail(payDetail);
} }
@ -456,13 +487,17 @@ public class SharedViewModel extends ViewModel {
} }
@SuppressLint("CheckResult")
public void pushReceipt(Object body){ public void pushReceipt(Object body){
Log.d("push receipt", new Gson().toJson(body)); Log.d("push receipt", new Gson().toJson(body));
repository.sendReceipt(body) repository.sendReceipt(body)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .subscribe(
response -> Log.d("E-Receipt", "Success =>"+ response.getMessage()), response -> {
Log.d("E-Receipt", "Success =>"+ response.getMessage());
postToastMsg("E-Receipt saved successfully");
},
error -> { error -> {
if (error instanceof HttpException) { if (error instanceof HttpException) {
HttpException httpEx = (HttpException) error; HttpException httpEx = (HttpException) error;
@ -474,11 +509,14 @@ public class SharedViewModel extends ViewModel {
// Parse JSON to model // Parse JSON to model
EReceiptResponse res = new Gson().fromJson(errorJson, EReceiptResponse.class); EReceiptResponse res = new Gson().fromJson(errorJson, EReceiptResponse.class);
Log.e("E-Receipt", "Parsed Error => " + res.getMessage()); Log.e("E-Receipt", "Parsed Error => " + res.getMessage());
postToastMsg("E-Receipt could not save!");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
postToastMsg("E-Receipt could not save!");
} }
} else { } else {
Log.e("E-Receipt", "Unexpected error => " + error.getMessage()); Log.e("E-Receipt", "Unexpected error => " + error.getMessage());
postToastMsg("E-Receipt could not save!");
} }
} }
); );

View File

@ -304,13 +304,16 @@ public class TransProcessViewModel extends ViewModel implements ProcessingTransa
} }
@Override @Override
public void processPreCompDb(PayDetail payResult) { public void processPreCompDb(PayDetail payResult) {
if(oldTransPayDetail.getAmount() == payResult.getAmount()) { if(oldTransPayDetail.getAmount() == payResult.getAmount()) {
oldTransPayDetail.setIsCanceled(true); oldTransPayDetail.setIsCanceled(true);
oldTransPayDetail.setAdjust(true);
updatePayDetail(oldTransPayDetail); updatePayDetail(oldTransPayDetail);
} else { } else {
oldTransPayDetail.setIsCanceled(false); oldTransPayDetail.setIsCanceled(false);
oldTransPayDetail.setAdjust(true);
updatePayDetail(oldTransPayDetail); updatePayDetail(oldTransPayDetail);
} }
repository.insertPayDetail(updateCurrentDateAndTime(payResult)); repository.insertPayDetail(updateCurrentDateAndTime(payResult));

View File

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

View File

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

View File

@ -30,6 +30,7 @@ import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.config.data.model.Features; import com.utsmm.kbz.config.data.model.Features;
import com.utsmm.kbz.ui.adapters.MainAdapter; import com.utsmm.kbz.ui.adapters.MainAdapter;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel; import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.CurrencySelectionHelper;
import com.utsmm.kbz.util.tms.TMSUtil; import com.utsmm.kbz.util.tms.TMSUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -41,6 +42,7 @@ public class DashboardTransFragment extends DataBindingFragment {
private MainViewModel mainViewModel; private MainViewModel mainViewModel;
private SharedViewModel sharedViewModel; private SharedViewModel sharedViewModel;
private CurrencySelectionHelper currencySelectionHelper;
private ArrayList<Features> featuresList = new ArrayList<>(); private ArrayList<Features> featuresList = new ArrayList<>();
@ -76,6 +78,7 @@ public class DashboardTransFragment extends DataBindingFragment {
protected void initViewModel() { protected void initViewModel() {
mainViewModel = getFragmentScopeViewModel(MainViewModel.class); mainViewModel = getFragmentScopeViewModel(MainViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class); sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
currencySelectionHelper = new CurrencySelectionHelper(this, sharedViewModel);
} }
@Override @Override
@ -175,6 +178,9 @@ public class DashboardTransFragment extends DataBindingFragment {
case CASH_ADVANCE: case CASH_ADVANCE:
new DashboardTransFragment.ClickEvent().onClickCashAdvance(); new DashboardTransFragment.ClickEvent().onClickCashAdvance();
break; break;
case CLEAR_REVERSAL:
new DashboardTransFragment.ClickEvent().onClickClearReversal();
break;
case DEVICE_CONFIG: case DEVICE_CONFIG:
new DashboardTransFragment.ClickEvent().onClickDeviceConfig(); new DashboardTransFragment.ClickEvent().onClickDeviceConfig();
break; break;
@ -227,9 +233,11 @@ public class DashboardTransFragment extends DataBindingFragment {
} }
public void onClickRefund() { public void onClickRefund() {
sharedViewModel.setTransactionsType(TransactionsType.REFUND); showCurrencyChooserForCardFlow(() -> {
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment; sharedViewModel.setTransactionsType(TransactionsType.REFUND);
safeRouteTo(currentId,routeId,hostId); routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
} }
public void onClickPreAuth () { public void onClickPreAuth () {
@ -248,19 +256,23 @@ public class DashboardTransFragment extends DataBindingFragment {
} }
public void onClickPreAuthCancel () { public void onClickPreAuthCancel () {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_VOID); showCurrencyChooserForCardFlow(() -> {
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_FULL_VOID); sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.amount.postValue("0"); // null to 0 sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_FULL_VOID);
// sharedViewModel.amount.postValue(null); sharedViewModel.amount.postValue("0"); // null to 0
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment; // sharedViewModel.amount.postValue(null);
safeRouteTo(currentId,routeId,hostId); routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
} }
public void onClickPreAuthComp () { public void onClickPreAuthComp () {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_COMPLETE); showCurrencyChooserForCardFlow(() -> {
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment; sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_COMPLETE);
safeRouteTo(currentId,routeId,hostId); routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId, routeId, hostId);
});
} }
@ -281,6 +293,14 @@ public class DashboardTransFragment extends DataBindingFragment {
}); });
} }
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(){ public void onClickDeviceConfig(){
routeId = R.id.action_dashboardTransFragment_to_deviceConfig; routeId = R.id.action_dashboardTransFragment_to_deviceConfig;
safeRouteTo(currentId, routeId, hostId); safeRouteTo(currentId, routeId, hostId);
@ -471,6 +491,7 @@ public class DashboardTransFragment extends DataBindingFragment {
private interface CurrencySelectCallback { private interface CurrencySelectCallback {
void onSelected(String currency); void onSelected(String currency);
// currencySelectionHelper.showCardCurrencyChooser(onSelected);
} }
} }

View File

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

View File

@ -53,6 +53,7 @@ public class ManagementFunctionFragment extends DataBindingFragment {
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
setToolBarTitleWithBackIcon(getString(R.string.title_select_function)); setToolBarTitleWithBackIcon(getString(R.string.title_select_function));
} }

View File

@ -145,6 +145,18 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
cardViewAdapter.updateList(searchedLists); 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 class ClickEvent {
public void onClickSearch() { public void onClickSearch() {
@ -152,7 +164,7 @@ public class ReprintAnyTransactionFragment extends DataBindingFragment {
String input = managementViewModel.txtRRNTrace.getValue(); String input = managementViewModel.txtRRNTrace.getValue();
if(input != null && !input.isEmpty()) { if(input != null && !input.isEmpty()) {
searchByTrace(input); searchByTraceAndRRN(input);
} else { } else {
searchedLists.addAll(lists); searchedLists.addAll(lists);
} }

View File

@ -210,21 +210,43 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
private void clearReversal() { private void clearReversal() {
checkPointReversal = false; checkPointReversal = false;
sharedViewModel.getReversalTransaction(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), payDetail -> { // sharedViewModel.getReversalTransaction(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), payDetail -> {
if (payDetail != null) { // if (payDetail != null) {
if (!checkPointReversal) { // if (!checkPointReversal) {
payDetail.setIsNeedReversal(false); // payDetail.setIsNeedReversal(false);
sharedViewModel.updatePayDetail(payDetail); // sharedViewModel.updatePayDetail(payDetail);
checkPointReversal = true; // checkPointReversal = true;
//
// showSuccessDialog("Clear reversal success!");
// }
// } else {
// if (!checkPointReversal) {
// showInfoDialog("Clear reversal", "No reversal found!");
// checkPointReversal = true;
// }
//
// }
// });
showSuccessDialog("Clear reversal success!"); sharedViewModel.getAllReversalTransaction().observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
} @Override
} else { public void onChanged(List<PayDetail> payDetails) {
if (!checkPointReversal) { if(payDetails != null && !payDetails.isEmpty()) {
showInfoDialog("Clear reversal", "No reversal found!"); if(!checkPointReversal) {
checkPointReversal = true; 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;
}
}
} }
}); });
} }

View File

@ -51,6 +51,8 @@ public class TransactionSummaryFragment extends DataBindingFragment {
final Calendar myCalendar = Calendar.getInstance(); final Calendar myCalendar = Calendar.getInstance();
final Calendar myCalendar2 = Calendar.getInstance(); final Calendar myCalendar2 = Calendar.getInstance();
ArrayList<PayDetail> filteredLists = new ArrayList<>();
@Override @Override
protected void initViewModel() { protected void initViewModel() {
managementViewModel = getFragmentScopeViewModel(ManagementViewModel.class); managementViewModel = getFragmentScopeViewModel(ManagementViewModel.class);
@ -224,10 +226,15 @@ public class TransactionSummaryFragment extends DataBindingFragment {
} }
} }
private SettleData processTransactionData(List<PayDetail> payDetailList, SimpleDateFormat formatter, private SettleData processTransactionData(List<PayDetail> payDetailList,
Date yesterday, Date start, Date end) { SimpleDateFormat formatter,
Date yesterday,
Date start,
Date end) {
try { try {
// Create a local helper class for readable mutability // ✅ IMPORTANT: clear old data
filteredLists.clear();
class Counter { class Counter {
int count = 0; int count = 0;
long amount = 0L; long amount = 0L;
@ -250,38 +257,32 @@ public class TransactionSummaryFragment extends DataBindingFragment {
Counter preAuthCompVoid = new Counter(); Counter preAuthCompVoid = new Counter();
Counter refund = new Counter(); Counter refund = new Counter();
// ✅ Use ONE consistent format
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm", Locale.getDefault()); SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm", Locale.getDefault());
ArrayList<PayDetail> filteredLists = new ArrayList<>();
// Filter transactions by date
for (PayDetail pay : payDetailList) { for (PayDetail pay : payDetailList) {
try { try {
Date transDate = formatter.parse(pay.getTransDate()); // ✅ Combine date + time correctly
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); Date currentDate = sdf.parse(pay.transDate + " " + pay.transTime);
if ((currentDate.after(start) || currentDate.equals(start)) && if (currentDate == null) continue;
(currentDate.before(end) || currentDate.equals(end))) {
// ✅ Correct inclusive range check
if (!currentDate.before(start) && !currentDate.after(end)) {
// ✅ Keep filtered list for printing
filteredLists.add(pay);
if (sharedViewModel.hostType.getValue() == HostType.QR) { if (sharedViewModel.hostType.getValue() == HostType.QR) {
if (pay.getTransactionType() == TransactionsType.MMQR.value && pay.getQrTransStatus() == 1) { if (pay.getTransactionType() == TransactionsType.MMQR.value && pay.getQrTransStatus() == 1) {
wave.inc(pay.amount); wave.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.MMQR_REFUND.value && pay.getQrTransStatus() == 1) { } else if (pay.getTransactionType() == TransactionsType.MMQR_REFUND.value && pay.getQrTransStatus() == 1) {
waveRefund.inc(pay.amount); waveRefund.inc(pay.amount);
} }
} else if (sharedViewModel.hostType.getValue() == HostType.MPU) { } else if (sharedViewModel.hostType.getValue() == HostType.MPU) {
if (pay.getTransactionType() == TransactionsType.VOID.value) { if (pay.getTransactionType() == TransactionsType.VOID.value) {
voidTran.inc(pay.amount); voidTran.inc(pay.amount);
} else if (pay.getTransactionType() == TransactionsType.SALE.value) { } else if (pay.getTransactionType() == TransactionsType.SALE.value) {
@ -301,11 +302,14 @@ public class TransactionSummaryFragment extends DataBindingFragment {
} }
} }
} }
} catch (ParseException e) { } catch (ParseException e) {
LogUtil.e(TAG, "Error parsing transaction datetime: " + e.getMessage()); LogUtil.e(TAG, "Error parsing transaction datetime: " + e.getMessage());
} }
} }
LogUtil.d(TAG, "Filtered transactions count: " + filteredLists.size());
return new SettleData( return new SettleData(
sale.count, sale.amount, sale.count, sale.amount,
wave.count, wave.amount, wave.count, wave.amount,
@ -318,6 +322,7 @@ public class TransactionSummaryFragment extends DataBindingFragment {
refund.count, refund.amount, refund.count, refund.amount,
waveRefund.count, waveRefund.amount waveRefund.count, waveRefund.amount
); );
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Error processing transaction data: " + e.getMessage()); LogUtil.e(TAG, "Error processing transaction data: " + e.getMessage());
return null; return null;
@ -366,7 +371,7 @@ public class TransactionSummaryFragment extends DataBindingFragment {
private void printReceipt(PayDetail payDetail) { private void printReceipt(PayDetail payDetail) {
try { try {
LogUtil.d(TAG, "Starting receipt print"); LogUtil.d(TAG, "Starting receipt print");
PrintXReceipt.getInstance().printSmileSummaryReport(payDetail, sharedViewModel.hostType.getValue(), new PrintXStatus() { PrintXReceipt.getInstance().printSmileSummaryReport(payDetail, filteredLists, sharedViewModel.hostType.getValue(), new PrintXStatus() {
@Override @Override
public void onSuccess() { public void onSuccess() {
LogUtil.d(TAG, "Receipt printed successfully"); LogUtil.d(TAG, "Receipt printed successfully");

View File

@ -77,7 +77,7 @@ public class ManualEntryFragment extends DataBindingFragment {
} }
private void processEmvCard() { private void processEmvCard() {
if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND || sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_VOID) { if(sharedViewModel.transactionsType.getValue() == TransactionsType.REFUND || sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_VOID || sharedViewModel.transactionsType.getValue() == TransactionsType.PRE_AUTH_COMPLETE) {
routeId = R.id.action_manualEntryFragment_to_inputRRNFragment; routeId = R.id.action_manualEntryFragment_to_inputRRNFragment;
} else { } else {
routeId = R.id.action_manualEntryFragment_to_emvTransactionFragment; routeId = R.id.action_manualEntryFragment_to_emvTransactionFragment;
@ -106,7 +106,7 @@ public class ManualEntryFragment extends DataBindingFragment {
payDetail.setICC55(""); payDetail.setICC55("");
// payDetail.setAuthNo(manualEntryViewModel.cvv.getValue()); // payDetail.setAuthNo(manualEntryViewModel.cvv.getValue());
emvTransactionProcessViewModel.cardNum.setValue(cardNo);
emvTransactionProcessViewModel.setTradeData(tradeData); emvTransactionProcessViewModel.setTradeData(tradeData);
safeNavigateToRouteId(); safeNavigateToRouteId();

View File

@ -4,6 +4,8 @@ import android.content.Context;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import androidx.databinding.ObservableBoolean;
import com.nexgo.oaf.apiv3.APIProxy; import com.nexgo.oaf.apiv3.APIProxy;
import com.nexgo.oaf.apiv3.DeviceEngine; import com.nexgo.oaf.apiv3.DeviceEngine;
import com.nexgo.oaf.apiv3.DeviceInfo; import com.nexgo.oaf.apiv3.DeviceInfo;
@ -12,6 +14,7 @@ import com.nexgo.oaf.apiv3.device.printer.AlignEnum;
import com.nexgo.oaf.apiv3.device.printer.GrayLevelEnum; import com.nexgo.oaf.apiv3.device.printer.GrayLevelEnum;
import com.nexgo.oaf.apiv3.device.printer.LineOptionEntity; import com.nexgo.oaf.apiv3.device.printer.LineOptionEntity;
import com.nexgo.oaf.apiv3.device.printer.Printer; import com.nexgo.oaf.apiv3.device.printer.Printer;
import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusHost; import com.utsmyanmar.baselib.network.model.sirius.SiriusHost;
import com.utsmyanmar.baselib.network.model.sirius.SiriusMerchant; import com.utsmyanmar.baselib.network.model.sirius.SiriusMerchant;
@ -20,12 +23,14 @@ import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.Constant; import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.sign_on.EchoTestProcess; import com.utsmyanmar.paylibs.sign_on.EchoTestProcess;
import com.utsmyanmar.paylibs.sign_on.SignOnListener; import com.utsmyanmar.paylibs.sign_on.SignOnListener;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR; import com.utsmm.kbz.BR;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel; import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import java.util.List; import java.util.List;
import java.util.Observable;
public class NaviMainFragment extends DataBindingFragment { public class NaviMainFragment extends DataBindingFragment {
@ -114,6 +119,36 @@ public class NaviMainFragment extends DataBindingFragment {
} }
public class ClickEvent { 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() { public void onClickEcho() {
showLoadingDialog("Sending Echo!"); showLoadingDialog("Sending Echo!");

View File

@ -359,7 +359,10 @@ public class PinPadViewModel extends ViewModel {
handler.obtainMessage(ON_ERROR_PIN_PAD,retCode).sendToTarget(); handler.obtainMessage(ON_ERROR_PIN_PAD,retCode).sendToTarget();
} }
LogUtil.d(TAG,"RetCode:"+retCode); LogUtil.d(TAG,"RetCode:"+retCode);
payDetail.setPINCipher(ByteUtil.bytes2HexStr(data)); if(retCode != SdkResult.PinPad_No_Pin_Input) {
payDetail.setPINCipher(ByteUtil.bytes2HexStr(data));
}
LogUtil.d(TAG,"data bytes:"+ByteUtil.bytes2HexStr(data)); LogUtil.d(TAG,"data bytes:"+ByteUtil.bytes2HexStr(data));
} }

View File

@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import com.utsmm.kbz.BR; import com.utsmm.kbz.BR;
import com.utsmm.kbz.MainActivity;
import com.utsmm.kbz.MainViewModel; import com.utsmm.kbz.MainViewModel;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants; import com.utsmm.kbz.config.Constants;

View File

@ -42,8 +42,7 @@ public class RefundCertificateManager {
return; return;
}; };
// String downloadBase = tmsAddress.trim() + "/api/v1/file/download?filePath="; //local String downloadBase = tmsAddress.trim() + "/file/download?filePath=";
String downloadBase = tmsAddress.trim() + "/file/download?filePath="; // uat and prod
String certUrl = SystemParamsOperation.getInstance().getCertificateUrl(); String certUrl = SystemParamsOperation.getInstance().getCertificateUrl();
String clientCertUrl = SystemParamsOperation.getInstance().getCertificateClientUrl(); String clientCertUrl = SystemParamsOperation.getInstance().getCertificateClientUrl();

View File

@ -44,6 +44,8 @@ public class HostConfigViewModel extends ViewModel {
// Third Host // Third Host
public MutableLiveData<String> thirdHostName = new MutableLiveData<>(); 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> thirdHostShortCode = new MutableLiveData<>();
public MutableLiveData<String> thirdHostPrimaryIp = new MutableLiveData<>(); public MutableLiveData<String> thirdHostPrimaryIp = new MutableLiveData<>();
public MutableLiveData<String> thirdHostPrimaryPort = new MutableLiveData<>(); public MutableLiveData<String> thirdHostPrimaryPort = new MutableLiveData<>();
@ -96,6 +98,8 @@ public class HostConfigViewModel extends ViewModel {
if (sp.getThirdHostName() != null && !sp.getThirdHostName().isEmpty()) { if (sp.getThirdHostName() != null && !sp.getThirdHostName().isEmpty()) {
thirdHostName.setValue(sp.getThirdHostName()); thirdHostName.setValue(sp.getThirdHostName());
thirdHostTid.setValue(sp.getThirdHostTerminalId());
thirdHostMid.setValue(sp.getThirdHostMerchantId());
thirdHostShortCode.setValue(sp.getThirdHostShortCode()); thirdHostShortCode.setValue(sp.getThirdHostShortCode());
String[] thp = split(sp.getThirdHostIpAddress()); String[] thp = split(sp.getThirdHostIpAddress());

View File

@ -15,7 +15,6 @@ import com.nexgo.downloadkey.downloadflow.DownloadFlowResultEntity;
import com.nexgo.downloadkey.downloadflow.DownloadResult; import com.nexgo.downloadkey.downloadflow.DownloadResult;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig; import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR; import com.utsmm.kbz.BR;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.FragmentInjectKeyBinding; import com.utsmm.kbz.databinding.FragmentInjectKeyBinding;
@ -84,22 +83,11 @@ public class InjectKeyFragment extends DataBindingFragment {
} }
private void updateConfigurationInfo() { private void updateConfigurationInfo() {
binding.serialNumberValue.setText(getDisplayValue(TMSUtil.getInstance().getSerialNumber()));
}
String terminalId = SystemParamsOperation.getInstance().getTerminalId(); private String getDisplayValue(String value) {
binding.terminalIdValue.setText(terminalId != null && !terminalId.isEmpty() ? return !TextUtils.isEmpty(value) ? value : "Not configured";
terminalId : "Not configured");
// Update Merchant ID
String merchantId = SystemParamsOperation.getInstance().getMerchantId();
binding.merchantIdValue.setText(merchantId != null && !merchantId.isEmpty() ?
merchantId : "Not configured");
// Update Serial Number
String serialNo = TMSUtil.getInstance().getSerialNumber();
binding.serialNumberValue.setText(serialNo != null && !serialNo.isEmpty() ?
serialNo : "Not configured");
} }
private void loadKeyFromKeyPOS() { private void loadKeyFromKeyPOS() {
@ -122,21 +110,18 @@ public class InjectKeyFragment extends DataBindingFragment {
mDownloadFlow = DownloadFlow.getInstance(); mDownloadFlow = DownloadFlow.getInstance();
String terminalId = SystemParamsOperation.getInstance().getTerminalId();
String merchantId = SystemParamsOperation.getInstance().getMerchantId();
String serialNo = TMSUtil.getInstance().getSerialNumber(); String serialNo = TMSUtil.getInstance().getSerialNumber();
// Validate configuration if (TextUtils.isEmpty(serialNo)) {
if (TextUtils.isEmpty(terminalId) || TextUtils.isEmpty(merchantId) || TextUtils.isEmpty(serialNo)) {
dismissLoadingDialog(); dismissLoadingDialog();
showDeclineDialog("Please configure Terminal ID, Merchant ID first in TMS Configuration"); showDeclineDialog("Serial number is not configured");
return; return;
} }
final DownloadFEntity downloadFEntity = new DownloadFEntity(); final DownloadFEntity downloadFEntity = new DownloadFEntity();
downloadFEntity.setSn(serialNo.getBytes()); downloadFEntity.setSn(serialNo.getBytes());
downloadFEntity.setMid(merchantId.getBytes()); downloadFEntity.setMid(null);
downloadFEntity.setTid(terminalId.getBytes()); downloadFEntity.setTid(null);
downloadFEntity.setTmkIndex(keyIndexTmp); downloadFEntity.setTmkIndex(keyIndexTmp);
downloadFEntity.setPort(0); downloadFEntity.setPort(0);
downloadFEntity.setTimeOut(10); downloadFEntity.setTimeOut(10);
@ -190,4 +175,4 @@ public class InjectKeyFragment extends DataBindingFragment {
} }
} }
} }
} }

View File

@ -86,6 +86,7 @@ public class QRSettlementTransactionFragment extends DataBindingFragment impleme
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
sharedViewModel.printerDisabled.setValue(!SystemParamsOperation.getInstance().getPrinterEnabled());
setToolBarTitleWithBackIcon(getString(R.string.title_qr_settlement)); setToolBarTitleWithBackIcon(getString(R.string.title_qr_settlement));
String merchantName = SystemParamsOperation.getInstance().getMerchantName(); String merchantName = SystemParamsOperation.getInstance().getMerchantName();
@ -134,7 +135,7 @@ public class QRSettlementTransactionFragment extends DataBindingFragment impleme
managementViewModel.detailReportLayoutLoadingVisibility.setValue(8); managementViewModel.detailReportLayoutLoadingVisibility.setValue(8);
managementViewModel.detailReportLayoutVisibility.setValue(8); managementViewModel.detailReportLayoutVisibility.setValue(8);
managementViewModel.detailReportLayoutViewVisibility.setValue(0); managementViewModel.detailReportLayoutViewVisibility.setValue(0);
managementViewModel.detailReportBottomLayoutVisibility.setValue(0); managementViewModel.detailReportBottomLayoutVisibility.setValue(isLastSettlementPrinterDisabled() ? 8 : 0);
} }
private void showEmptyDataView() { private void showEmptyDataView() {
@ -149,6 +150,13 @@ public class QRSettlementTransactionFragment extends DataBindingFragment impleme
managementViewModel.cardTypeDR.setValue("QR PAY"); managementViewModel.cardTypeDR.setValue("QR PAY");
} }
private boolean isLastSettlementPrinterDisabled() {
Boolean printerDisabled = sharedViewModel.printerDisabled.getValue();
return sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT
&& printerDisabled != null
&& printerDisabled;
}
private void observeQRTransactions() { private void observeQRTransactions() {
managementViewModel.getTransactionHistory().observe(getViewLifecycleOwner(), payDetailList -> { managementViewModel.getTransactionHistory().observe(getViewLifecycleOwner(), payDetailList -> {
if (payDetailList != null) { if (payDetailList != null) {
@ -385,4 +393,4 @@ public class QRSettlementTransactionFragment extends DataBindingFragment impleme
} }
} }
} }

View File

@ -9,10 +9,14 @@ import androidx.annotation.Nullable;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import com.utsmm.kbz.ui.management.ManagementViewModel; import com.utsmm.kbz.ui.management.ManagementViewModel;
import com.utsmm.kbz.ui.settlement.model.CurrencyBucket;
import com.utsmm.kbz.util.CurrencySelectionHelper;
import com.utsmm.kbz.util.EReceiptUtil; import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmm.kbz.util.enums.TransactionStatus;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest; import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig; import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.CardSettleData;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData; import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus; import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
@ -32,6 +36,7 @@ import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.ecr.CoreUtils; import com.utsmm.kbz.util.ecr.CoreUtils;
import java.util.List; import java.util.List;
import java.util.Locale;
public class SettlementTransactionFragment extends DataBindingFragment implements DataBindingFragment.BackPressCallback{ public class SettlementTransactionFragment extends DataBindingFragment implements DataBindingFragment.BackPressCallback{
@ -42,7 +47,7 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
private SharedViewModel sharedViewModel; private SharedViewModel sharedViewModel;
private ManagementViewModel managementViewModel; private ManagementViewModel managementViewModel;
private CurrencySelectionHelper currencySelectionHelper;
private int routeId; private int routeId;
int saleCount = 0; int saleCount = 0;
@ -54,11 +59,16 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
long refundAmount = 0; long refundAmount = 0;
long caAmount = 0; long caAmount = 0;
private final CurrencyBucket mmkBucket = new CurrencyBucket();
private final CurrencyBucket usdBucket = new CurrencyBucket();
@Override @Override
protected void initViewModel() { protected void initViewModel() {
settlementViewModel = getFragmentScopeViewModel(SettlementViewModel.class); settlementViewModel = getFragmentScopeViewModel(SettlementViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class); sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
managementViewModel = getFragmentScopeViewModel(ManagementViewModel.class); managementViewModel = getFragmentScopeViewModel(ManagementViewModel.class);
currencySelectionHelper = new CurrencySelectionHelper(this, sharedViewModel);
} }
@Override @Override
@ -88,6 +98,8 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
boolean printerDisabled = !SystemParamsOperation.getInstance().getPrinterEnabled();
sharedViewModel.printerDisabled.setValue(printerDisabled);
if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT) { if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT) {
setToolBarTitleWithBackIcon(getString(R.string.txt_subtitle_reprint_last_settle_report)); setToolBarTitleWithBackIcon(getString(R.string.txt_subtitle_reprint_last_settle_report));
@ -103,6 +115,8 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH){ if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH){
settlementViewModel.btmLayout.setValue(8); settlementViewModel.btmLayout.setValue(8);
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT && printerDisabled) {
settlementViewModel.btmLayout.setValue(8);
} else { } else {
settlementViewModel.btmLayout.setValue(0); settlementViewModel.btmLayout.setValue(0);
} }
@ -170,6 +184,7 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
caCount = payDetail.getSettleDataObj().getCashAdvanceCount(); caCount = payDetail.getSettleDataObj().getCashAdvanceCount();
caAmount = payDetail.getSettleDataObj().getCashAdvanceAmount(); caAmount = payDetail.getSettleDataObj().getCashAdvanceAmount();
applyStoredCurrencyBreakdown(payDetail);
settlementViewModel.isNoData.setValue(false); settlementViewModel.isNoData.setValue(false);
@ -222,20 +237,24 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
if((transType == TransactionType.SALE || "SALE".equalsIgnoreCase(transName)) && !payDetail.isCanceled){ if((transType == TransactionType.SALE || "SALE".equalsIgnoreCase(transName)) && !payDetail.isCanceled){
saleCount ++; saleCount ++;
saleAmount += payDetail.getAmount(); saleAmount += payDetail.getAmount();
addToCurrencyBucket(payDetail, BucketType.SALE);
} else if((transType == TransactionType.PRE_SALE_COMPLETE } else if((transType == TransactionType.PRE_SALE_COMPLETE
|| "PREAUTH COMPLETION".equalsIgnoreCase(transName) || "PREAUTH COMPLETION".equalsIgnoreCase(transName)
|| "PRE_AUTH_COMPLETE".equalsIgnoreCase(transName)) && !payDetail.isCanceled){ || "PRE_AUTH_COMPLETE".equalsIgnoreCase(transName)) && !payDetail.isCanceled){
preCount ++; preCount ++;
preAmount += payDetail.getAmount(); preAmount += payDetail.getAmount();
addToCurrencyBucket(payDetail, BucketType.PRE_AUTH_COMPLETE);
} }
else if(transType == TransactionType.REFUND || "REFUND".equalsIgnoreCase(transName)){ else if(transType == TransactionType.REFUND || "REFUND".equalsIgnoreCase(transName)){
refundCount ++; refundCount ++;
refundAmount += payDetail.getAmount(); refundAmount += payDetail.getAmount();
addToCurrencyBucket(payDetail, BucketType.REFUND);
}else if(transType == TransactionType.CASH_ADVANCE }else if(transType == TransactionType.CASH_ADVANCE
|| "CASH_OUT".equalsIgnoreCase(transName) || "CASH_OUT".equalsIgnoreCase(transName)
|| "CASH_ADVANCE".equalsIgnoreCase(transName)){ || "CASH_ADVANCE".equalsIgnoreCase(transName)){
caCount ++; caCount ++;
caAmount += payDetail.getAmount(); caAmount += payDetail.getAmount();
addToCurrencyBucket(payDetail, BucketType.CASH_ADVANCE);
} }
} }
long totalAmount = saleAmount + preAmount + caAmount; long totalAmount = saleAmount + preAmount + caAmount;
@ -276,6 +295,8 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
preAmount = 0L; preAmount = 0L;
refundAmount = 0L; refundAmount = 0L;
caAmount = 0L; caAmount = 0L;
resetCurrencyBucket(mmkBucket);
resetCurrencyBucket(usdBucket);
} }
private void setSettlementViewModelData(int saleCount,long saleAmount,int preCount,long preAmount,int refundCount,long refundAmount,int caCount,long caAmount) { private void setSettlementViewModelData(int saleCount,long saleAmount,int preCount,long preAmount,int refundCount,long refundAmount,int caCount,long caAmount) {
@ -287,6 +308,10 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
settlementViewModel.refund_amount.setValue(refundAmount); settlementViewModel.refund_amount.setValue(refundAmount);
settlementViewModel.ca_count.setValue(caCount); settlementViewModel.ca_count.setValue(caCount);
settlementViewModel.ca_amount.setValue(caAmount); settlementViewModel.ca_amount.setValue(caAmount);
settlementViewModel.sale_breakdown.setValue(buildBreakdownText(mmkBucket.saleCount, mmkBucket.saleAmount, usdBucket.saleCount, usdBucket.saleAmount));
settlementViewModel.pre_breakdown.setValue(buildBreakdownText(mmkBucket.preCount, mmkBucket.preAmount, usdBucket.preCount, usdBucket.preAmount));
settlementViewModel.refund_breakdown.setValue(buildBreakdownText(mmkBucket.refundCount, mmkBucket.refundAmount, usdBucket.refundCount, usdBucket.refundAmount));
settlementViewModel.ca_breakdown.setValue(buildBreakdownText(mmkBucket.caCount, mmkBucket.caAmount, usdBucket.caCount, usdBucket.caAmount));
if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH) { if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH) {
SettleData settleData = new SettleData(saleCount,saleAmount,preCount,preAmount,refundCount,refundAmount,caCount,caAmount); SettleData settleData = new SettleData(saleCount,saleAmount,preCount,preAmount,refundCount,refundAmount,caCount,caAmount);
@ -300,6 +325,118 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
} }
private enum BucketType {
SALE,
PRE_AUTH_COMPLETE,
REFUND,
CASH_ADVANCE
}
private void resetCurrencyBucket(CurrencyBucket bucket) {
bucket.saleCount = 0;
bucket.saleAmount = 0L;
bucket.preCount = 0;
bucket.preAmount = 0L;
bucket.refundCount = 0;
bucket.refundAmount = 0L;
bucket.caCount = 0;
bucket.caAmount = 0L;
}
private void addToCurrencyBucket(PayDetail payDetail, BucketType bucketType) {
CurrencyBucket bucket = getCurrencyBucket(payDetail.getCurrencyCode());
long amount = payDetail.getAmount();
switch (bucketType) {
case SALE:
bucket.saleCount++;
bucket.saleAmount += amount;
break;
case PRE_AUTH_COMPLETE:
bucket.preCount++;
bucket.preAmount += amount;
break;
case REFUND:
bucket.refundCount++;
bucket.refundAmount += amount;
break;
case CASH_ADVANCE:
bucket.caCount++;
bucket.caAmount += amount;
break;
}
}
private CurrencyBucket getCurrencyBucket(String currencyCode) {
return "USD".equals(normalizeCurrency(currencyCode)) ? usdBucket : mmkBucket;
}
private void applyStoredCurrencyBreakdown(PayDetail payDetail) {
resetCurrencyBucket(mmkBucket);
resetCurrencyBucket(usdBucket);
List<CardSettleData> cardSettleDataList = payDetail.getCardSettleData();
if (cardSettleDataList != null && !cardSettleDataList.isEmpty()) {
for (CardSettleData item : cardSettleDataList) {
applyStoredCardSettle(item);
}
return;
}
String normalizedCurrency = normalizeCurrency(payDetail.getCurrencyCode());
CurrencyBucket bucket = "USD".equals(normalizedCurrency) ? usdBucket : mmkBucket;
bucket.saleCount = saleCount;
bucket.saleAmount = saleAmount;
bucket.preCount = preCount;
bucket.preAmount = preAmount;
bucket.refundCount = refundCount;
bucket.refundAmount = refundAmount;
bucket.caCount = caCount;
bucket.caAmount = caAmount;
}
private void applyStoredCardSettle(CardSettleData item) {
CurrencyBucket bucket = getCurrencyBucket(item.getCurrencyCode());
String transType = item.getTransType() == null ? "" : item.getTransType().trim().toUpperCase(Locale.getDefault());
if ("SALE".equals(transType)) {
bucket.saleCount++;
bucket.saleAmount += item.getAmount();
} else if ("PREAUTH COMPLETION".equals(transType) || "PRE_AUTH_COMPLETE".equals(transType)) {
bucket.preCount++;
bucket.preAmount += item.getAmount();
} else if ("REFUND".equals(transType)) {
bucket.refundCount++;
bucket.refundAmount += item.getAmount();
} else if ("CASH_OUT".equals(transType) || "CASH_ADVANCE".equals(transType)) {
bucket.caCount++;
bucket.caAmount += item.getAmount();
}
}
private String buildBreakdownText(int mmkCount, long mmkAmount, int usdCount, long usdAmount) {
return "MMK " + mmkCount + " / " + POSUtil.getInstance().getDecimalAmountSeparatorFormat(mmkAmount)
+ " USD " + usdCount + " / " + POSUtil.getInstance().getDecimalAmountSeparatorFormat(usdAmount);
}
private String normalizeCurrency(String currencyCode) {
if (currencyCode == null) {
return "MMK";
}
String value = currencyCode.trim().toUpperCase(Locale.getDefault());
switch (value) {
case "840":
case "USD":
return "USD";
case "104":
case "MMK":
default:
return "MMK";
}
}
private void navigateMainScreen(){ private void navigateMainScreen(){
routeId = R.id.action_settlementTransactionFragment_to_nav_main; routeId = R.id.action_settlementTransactionFragment_to_nav_main;
@ -311,13 +448,22 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
safeNavigateToRouteId(); safeNavigateToRouteId();
} }
private boolean isUSDSettleNeeded() {
return (usdBucket.saleCount != 0 || usdBucket.preCount != 0 || usdBucket.refundCount != 0 || usdBucket.caCount != 0);
}
private void networkCutOver() { private void networkCutOver() {
EchoTestProcess.getInstance().enqueueCutOver().startSignOn(new SignOnListener() { EchoTestProcess.getInstance().enqueueCutOver().startSignOn(new SignOnListener() {
@Override @Override
public void onSuccessSignOn() { public void onSuccessSignOn() {
// showSuccessDialog("Approved!"); if(settlementViewModel.resultString.getValue() != TransactionStatus.ON_FINAL_SUCCESS) {
navigateToNext(); currencySelectionHelper.applyCardCurrencyAndHost("MMK");
settlementViewModel.startSettlementProcess(mmkBucket,true);
} else {
navigateToNext();
}
} }
@Override @Override
@ -345,12 +491,15 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
showLoadingDialog("Sending Batch Upload..."); showLoadingDialog("Sending Batch Upload...");
break; break;
case ON_SUCCESS: case ON_SUCCESS:
updateData();
dismissLoadingDialog();
networkCutOver();
break;
case ON_FINAL_SUCCESS:
dismissLoadingDialog(); dismissLoadingDialog();
updateData(); updateData();
if (!SystemParamsOperation.getInstance().getDemoStatus()) { if (!SystemParamsOperation.getInstance().getDemoStatus()) {
networkCutOver(); // bpc networkCutOver(); // bpc
navigateToNext();
} else { } else {
navigateToNext(); navigateToNext();
} }
@ -415,11 +564,22 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
} }
public void onConfirm(){ public void onConfirm(){
if(sharedViewModel.getTransMenu().getValue() == TransMenu.SETTLEMENT) { if(sharedViewModel.getTransMenu().getValue() == TransMenu.SETTLEMENT) {
/* April 10 , 2024 Smile requested not to send to host even settlement button was clicked */ /* April 10 , 2024 Smile requested not to send to host even settlement button was clicked */
settlementViewModel.startSettlementProcess();
if(isUSDSettleNeeded()) {
currencySelectionHelper.applyCardCurrencyAndHost("USD");
settlementViewModel.startSettlementProcess(usdBucket,false);
} else {
currencySelectionHelper.applyCardCurrencyAndHost("MMK");
settlementViewModel.startSettlementProcess(mmkBucket,true);
}
showLoadingDialog("Sending ..."); showLoadingDialog("Sending ...");
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH) { } else if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH) {
sharedViewModel.startPrintSettlement(new PrintXStatus() { sharedViewModel.startPrintSettlement(new PrintXStatus() {

View File

@ -7,6 +7,7 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
import com.utsmm.kbz.ui.settlement.model.CurrencyBucket;
import com.utsmm.kbz.util.EReceiptUtil; import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest; import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.repo.Repository; import com.utsmyanmar.baselib.repo.Repository;
@ -75,15 +76,19 @@ public class SettlementViewModel extends ViewModel {
public SingleLiveEvent<Integer> sale_count = new SingleLiveEvent<>(); public SingleLiveEvent<Integer> sale_count = new SingleLiveEvent<>();
public SingleLiveEvent<Long> sale_amount = new SingleLiveEvent<>(); public SingleLiveEvent<Long> sale_amount = new SingleLiveEvent<>();
public SingleLiveEvent<String> sale_breakdown = new SingleLiveEvent<>();
public SingleLiveEvent<Integer> pre_count = new SingleLiveEvent<>(); public SingleLiveEvent<Integer> pre_count = new SingleLiveEvent<>();
public SingleLiveEvent<Long> pre_amount = new SingleLiveEvent<>(); public SingleLiveEvent<Long> pre_amount = new SingleLiveEvent<>();
public SingleLiveEvent<String> pre_breakdown = new SingleLiveEvent<>();
public SingleLiveEvent<Integer> refund_count = new SingleLiveEvent<>(); public SingleLiveEvent<Integer> refund_count = new SingleLiveEvent<>();
public SingleLiveEvent<Long> refund_amount = new SingleLiveEvent<>(); public SingleLiveEvent<Long> refund_amount = new SingleLiveEvent<>();
public SingleLiveEvent<String> refund_breakdown = new SingleLiveEvent<>();
public SingleLiveEvent<Integer> ca_count = new SingleLiveEvent<>(); public SingleLiveEvent<Integer> ca_count = new SingleLiveEvent<>();
public SingleLiveEvent<Long> ca_amount = new SingleLiveEvent<>(); public SingleLiveEvent<Long> ca_amount = new SingleLiveEvent<>();
public SingleLiveEvent<String> ca_breakdown = new SingleLiveEvent<>();
public SingleLiveEvent<SettlementType> settlementType = new SingleLiveEvent<>(); public SingleLiveEvent<SettlementType> settlementType = new SingleLiveEvent<>();
@ -111,18 +116,26 @@ public class SettlementViewModel extends ViewModel {
private ISOMsgX isoMsgX; private ISOMsgX isoMsgX;
public CurrencyBucket currentBucket= new CurrencyBucket();
private boolean isLast = true;
@Inject @Inject
public SettlementViewModel(Repository repository) { public SettlementViewModel(Repository repository) {
this.repository = repository; this.repository = repository;
sale_count.setValue(0); sale_count.setValue(0);
sale_amount.setValue(0L); sale_amount.setValue(0L);
sale_breakdown.setValue("");
pre_count.setValue(0); pre_count.setValue(0);
pre_amount.setValue(0L); pre_amount.setValue(0L);
pre_breakdown.setValue("");
refund_count.setValue(0); refund_count.setValue(0);
refund_amount.setValue(0L); refund_amount.setValue(0L);
refund_breakdown.setValue("");
ca_count.setValue(0); ca_count.setValue(0);
ca_amount.setValue(0L); ca_amount.setValue(0L);
ca_breakdown.setValue("");
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU,HostName.BPC) isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU,HostName.BPC)
.build(); .build();
@ -221,14 +234,7 @@ public class SettlementViewModel extends ViewModel {
if(payDetails != null && payDetails.size() > 0) { if(payDetails != null && payDetails.size() > 0) {
for (PayDetail pay:payDetails) { for (PayDetail pay:payDetails) {
// if(paydetail.getTransactionType() == TransactionsType.SALE.value) {
// paydetail.setIsSettle(true);
// updatePayDetail(paydetail);
// } else {
deletePayDetail(pay); deletePayDetail(pay);
// repository.deletePayDetail(paydetail);
// }
} }
} }
@ -257,22 +263,14 @@ public class SettlementViewModel extends ViewModel {
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
public void startSettlementProcess() { public void startSettlementProcess(CurrencyBucket currencyBucket,boolean isLast) {
saleCount = sale_count.getValue(); this.isLast = isLast;
saleAmount = sale_amount.getValue();
preAuthCount = pre_count.getValue();
preAuthAmount = pre_amount.getValue();
refundCount = refund_count.getValue();
refundAmount = refund_amount.getValue();
caCount = ca_count.getValue();
caAmount = ca_amount.getValue();
SystemParamsOperation.getInstance().getIncrementBatchNo(); SystemParamsOperation.getInstance().getIncrementBatchNo();
if(SystemParamsOperation.getInstance().getDemoStatus()) { if(SystemParamsOperation.getInstance().getDemoStatus()) {
requestDemoProcessSettlement(); requestDemoProcessSettlement(currencyBucket);
} else { } else {
requestOnlineProcessSettlement(); requestOnlineProcessSettlement(currencyBucket);
} }
} }
@ -291,7 +289,7 @@ public class SettlementViewModel extends ViewModel {
private void requestDemoProcessSettlement() { private void requestDemoProcessSettlement(CurrencyBucket currencyBucket) {
TradeData tradeData = Params.newTrade(true); TradeData tradeData = Params.newTrade(true);
@ -313,18 +311,18 @@ public class SettlementViewModel extends ViewModel {
payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum()); //for print receipt payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum()); //for print receipt
/*POS*/ /*POS*/
payDetail.setSettleList(sale_count.getValue() + ":" + sale_amount.getValue() + "-" + ca_count.getValue() + ":" + ca_amount.getValue() + "-" + refund_count.getValue() + ":" + refund_amount.getValue() + "-" + pre_count.getValue() + ":" + pre_amount.getValue()); // for print receipt payDetail.setSettleList(currencyBucket.saleCount+ ":" + currencyBucket.saleAmount + "-" + currencyBucket.caCount + ":" + currencyBucket.caAmount + "-" + currencyBucket.refundCount + ":" + currencyBucket.refundAmount + "-" + currencyBucket.preCount + ":" + currencyBucket.preAmount); // for print receipt
/*POS*/ /*POS*/
SettleData settleData = new SettleData(saleCount,saleAmount,preAuthCount,preAuthAmount,refundCount,refundAmount,caCount,caAmount); SettleData settleData = new SettleData(currencyBucket.saleCount, currencyBucket.saleAmount, currencyBucket.preCount, currencyBucket.preAmount, currencyBucket.refundCount, currencyBucket.refundAmount, currencyBucket.caCount, currencyBucket.caAmount);
payDetail.setSettleDataObj(settleData); payDetail.setSettleDataObj(settleData);
long totalAmount = saleAmount + preAuthAmount + refundAmount + caAmount; long totalAmount = currencyBucket.saleAmount + currencyBucket.preAmount + currencyBucket.refundAmount + currencyBucket.caAmount;
String settlementData = ""; String settlementData = "";
if(refundAmount != 0L) { if(currencyBucket.refundAmount != 0L) {
long creditTotal = saleAmount + preAuthAmount + caAmount; long creditTotal = currencyBucket.saleAmount + currencyBucket.preAmount + currencyBucket.caAmount;
long subTotal = creditTotal - refundAmount; long subTotal = creditTotal - currencyBucket.refundAmount;
if(subTotal < 0L) { if(subTotal < 0L) {
settlementData = "D"+ String.format(Locale.getDefault(), "%012d", Math.abs(subTotal)); settlementData = "D"+ String.format(Locale.getDefault(), "%012d", Math.abs(subTotal));
@ -343,27 +341,27 @@ public class SettlementViewModel extends ViewModel {
updateDB(); updateDB();
insertPayDetail(payDetail); insertPayDetail(payDetail);
resultString.postValue(TransactionStatus.ON_SUCCESS); resultString.postValue(TransactionStatus.ON_FINAL_SUCCESS);
} }
private void requestOnlineProcessSettlement() { private void requestOnlineProcessSettlement(CurrencyBucket currencyBucket) {
currentBucket = currencyBucket;
HostName hostName = HostName.BPC; HostName hostName = HostName.BPC;
String field60 = SystemParamsOperation.getInstance().getCurrentBatchNum(); String field60 = SystemParamsOperation.getInstance().getCurrentBatchNum();
int sale2Count = saleCount + preAuthCount; int sale2Count = currencyBucket.saleCount + currencyBucket.preCount;
long sale2Amount = saleAmount + preAuthAmount; long sale2Amount = currencyBucket.saleAmount + currencyBucket.preAmount;
String totalSaleCount = String.format(Locale.getDefault(), "%03d", sale2Count); String totalSaleCount = String.format(Locale.getDefault(), "%03d", sale2Count);
String totalSaleAmount = String.format(Locale.getDefault(), "%010d00", sale2Amount); String totalSaleAmount = String.format(Locale.getDefault(), "%010d00", sale2Amount);
String totalRefundCount = String.format(Locale.getDefault(), "%03d", refundCount); String totalRefundCount = String.format(Locale.getDefault(), "%03d", currencyBucket.refundCount);
String totalRefundAmount = String.format(Locale.getDefault(), "%010d00", refundAmount == 0L ? 0 : refundAmount); String totalRefundAmount = String.format(Locale.getDefault(), "%010d00", currencyBucket.refundAmount == 0L ? 0 : currencyBucket.refundAmount);
String totalDebitSaleCount = String.format(Locale.getDefault(), "%03d", caCount); String totalDebitSaleCount = String.format(Locale.getDefault(), "%03d", currencyBucket.caCount);
String totalDebitSaleAmount = String.format(Locale.getDefault(), "%010d00", caAmount == 0L ? 0 : caAmount); String totalDebitSaleAmount = String.format(Locale.getDefault(), "%010d00", currencyBucket.caAmount == 0L ? 0 : currencyBucket.caAmount);
String totalERefundCount = String.format(Locale.getDefault(), "%03d", 0); String totalERefundCount = String.format(Locale.getDefault(), "%03d", 0);
String totalERefundAmount = String.format(Locale.getDefault(), "%010d00", 0); String totalERefundAmount = String.format(Locale.getDefault(), "%010d00", 0);
@ -394,26 +392,32 @@ public class SettlementViewModel extends ViewModel {
} }
if(isLast) {
payDetail.setCurrencyCode("104");
} else {
payDetail.setCurrencyCode("840");
}
// CA:CA - CD - FT // CA:CA - CD - FT
payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum()); //for print receipt payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum()); //for print receipt
/*POS*/ /*POS*/
payDetail.setSettleList(sale_count.getValue() + ":" + sale_amount.getValue() + "-" + ca_count.getValue() + ":" + ca_amount.getValue() + "-" + refund_count.getValue() + ":" + refund_amount.getValue() + "-" + pre_count.getValue() + ":" + pre_amount.getValue()); // for print receipt payDetail.setSettleList(currencyBucket.saleCount+ ":" + currencyBucket.saleAmount + "-" + currencyBucket.caCount + ":" + currencyBucket.caAmount + "-" + currencyBucket.refundCount + ":" + currencyBucket.refundAmount + "-" + currencyBucket.preCount + ":" + currencyBucket.preAmount); // for print receipt
/*POS*/ /*POS*/
SettleData settleData = new SettleData(saleCount,saleAmount,preAuthCount,preAuthAmount,refundCount,refundAmount,caCount,caAmount); SettleData settleData = new SettleData(currencyBucket.saleCount, currencyBucket.saleAmount, currencyBucket.preCount, currencyBucket.preAmount, currencyBucket.refundCount, currencyBucket.refundAmount, currencyBucket.caCount, currencyBucket.caAmount);
payDetail.setSettleDataObj(settleData); payDetail.setSettleDataObj(settleData);
if(payDetails != null) if(payDetails != null)
payDetail.setCardSettleData(CardSettleData.convertFromPayDetail(payDetails)); payDetail.setCardSettleData(CardSettleData.convertFromPayDetail(payDetails));
if(hostName == HostName.BPC) { if(hostName == HostName.BPC) {
long totalAmount = saleAmount + preAuthAmount + refundAmount + caAmount; long totalAmount = currencyBucket.saleAmount + currencyBucket.preAmount + currencyBucket.refundAmount + currencyBucket.caAmount;
String settlementData = ""; String settlementData = "";
if(refundAmount != 0L) { if(currencyBucket.refundAmount != 0L) {
long creditTotal = saleAmount + preAuthAmount + caAmount; long creditTotal = currencyBucket.saleAmount + currencyBucket.preAmount + currencyBucket.caAmount;
long subTotal = creditTotal - refundAmount; long subTotal = creditTotal - currencyBucket.refundAmount;
if(subTotal < 0L) { if(subTotal < 0L) {
settlementData = "D"+ String.format(Locale.getDefault(), "%012d", Math.abs(subTotal)); settlementData = "D"+ String.format(Locale.getDefault(), "%012d", Math.abs(subTotal));
@ -462,11 +466,7 @@ public class SettlementViewModel extends ViewModel {
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) { } else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
//reversal //reversal
// if (!flag && isNoData.getValue()) { // if (!flag && isNoData.getValue()) {
if (!flag ) { payDetail.setIsNeedReversal(!flag);
payDetail.setIsNeedReversal(true);
} else {
payDetail.setIsNeedReversal(false);
}
} }
} else { } else {
@ -480,7 +480,7 @@ public class SettlementViewModel extends ViewModel {
if (!isSecondCall) { if (!isSecondCall) {
ISOSocket.getInstance().switchIp(); ISOSocket.getInstance().switchIp();
resultString.postValue(TransactionStatus.ON_SECONDARY); resultString.postValue(TransactionStatus.ON_SECONDARY);
requestOnlineProcessSettlement(); requestOnlineProcessSettlement(currencyBucket);
isSecondCall = true; isSecondCall = true;
} else { } else {
resultString.postValue(TransactionStatus.ON_ERROR); resultString.postValue(TransactionStatus.ON_ERROR);
@ -501,7 +501,7 @@ public class SettlementViewModel extends ViewModel {
/* Batch Upload Start Here*/ /* Batch Upload Start Here*/
flag = true; flag = true;
batchUploadProcess(); batchUploadProcess(isLast);
} else { } else {
/* this flag is to send batch upload again when host response 95 next time */ /* this flag is to send batch upload again when host response 95 next time */
@ -512,19 +512,21 @@ public class SettlementViewModel extends ViewModel {
// to leave data for testing // to leave data for testing
// if (settlementType.getValue() == SettlementType.NORMAL) { // if (settlementType.getValue() == SettlementType.NORMAL) {
updateDB(); if(isLast) {
updateDB();
}
// }
insertPayDetail(payDetail); insertPayDetail(payDetail);
if (errorFlag) { if (errorFlag) {
resultString.postValue(TransactionStatus.ON_ERROR); resultString.postValue(TransactionStatus.ON_ERROR);
} else { } else {
resultString.postValue(TransactionStatus.ON_SUCCESS); if(isLast) {
resultString.postValue(TransactionStatus.ON_FINAL_SUCCESS);
} else {
resultString.postValue(TransactionStatus.ON_SUCCESS);
}
} }
@ -533,31 +535,56 @@ public class SettlementViewModel extends ViewModel {
}); });
} }
private void batchUploadProcess() { private void batchUploadProcess(boolean isLast) {
resultString.postValue(TransactionStatus.ON_BATCH_UPLOAD); resultString.postValue(TransactionStatus.ON_BATCH_UPLOAD);
if(payDetails == null || payDetails.size() == 0){ if (payDetails == null || payDetails.isEmpty()) {
requestOnlineProcessSettlement(); requestOnlineProcessSettlement(currentBucket);
return;
}
// Advance index, skipping entries that don't belong to this pass
while (i < payDetails.size()) {
PayDetail payDetail = payDetails.get(i);
boolean isMMK = payDetail.getCurrencyCode().equals("104");
if (isLast && !isMMK) {
// isLast = true → MMK pass, skip USD
LogUtil.d(TAG, "Skipping USD transaction at index: " + i);
i++;
continue;
} else if (!isLast && isMMK) {
// isLast = false → USD pass, skip MMK
LogUtil.d(TAG, "Skipping MMK transaction at index: " + i);
i++;
continue;
}
break;
}
if (i >= payDetails.size()) {
requestOnlineProcessSettlement(currentBucket);
return; return;
} }
PayDetail payDetail = payDetails.get(i); PayDetail payDetail = payDetails.get(i);
TradeData tradeData = new TradeData(); TradeData tradeData = new TradeData();
tradeData.setPayDetail(payDetail); tradeData.setPayDetail(payDetail);
BatchUploadProcess.getInstance().enqueue(tradeData).startBatchUpload(new BatchListener() { BatchUploadProcess.getInstance().enqueue(tradeData).startBatchUpload(new BatchListener() {
@Override @Override
public void onSuccessBatch() { public void onSuccessBatch() {
LogUtil.e(TAG, "Batch Upload Success");
LogUtil.d(TAG, "Pay detail Size: " + payDetails.size());
LogUtil.d(TAG, "Count value: " + i);
if (i < payDetails.size() - 1) { if (i < payDetails.size() - 1) {
LogUtil.d(TAG, "Pay detail Size:" + payDetails.size());
LogUtil.d(TAG, "Count value:" + i);
i++; i++;
batchUploadProcess(); batchUploadProcess(isLast);
} else { } else {
requestOnlineProcessSettlement(); requestOnlineProcessSettlement(currentBucket);
} }
LogUtil.e(TAG, "Batch Upload Success");
} }
@Override @Override

View File

@ -0,0 +1,89 @@
package com.utsmm.kbz.ui.settlement.model;
public class CurrencyBucket {
public int saleCount;
public long saleAmount;
public int preCount;
public long preAmount;
public int refundCount;
public long refundAmount;
public int caCount;
public long caAmount;
public CurrencyBucket(){}
public CurrencyBucket(int saleCount, long saleAmount, int preCount, long preAmount, int refundCount, long refundAmount, int caCount, long caAmount) {
this.saleCount = saleCount;
this.saleAmount = saleAmount;
this.preCount = preCount;
this.preAmount = preAmount;
this.refundCount = refundCount;
this.refundAmount = refundAmount;
this.caCount = caCount;
this.caAmount = caAmount;
}
public void setSaleCount(int saleCount) {
this.saleCount = saleCount;
}
public void setSaleAmount(long saleAmount) {
this.saleAmount = saleAmount;
}
public void setPreCount(int preCount) {
this.preCount = preCount;
}
public void setPreAmount(long preAmount) {
this.preAmount = preAmount;
}
public void setRefundCount(int refundCount) {
this.refundCount = refundCount;
}
public void setRefundAmount(long refundAmount) {
this.refundAmount = refundAmount;
}
public void setCaCount(int caCount) {
this.caCount = caCount;
}
public void setCaAmount(long caAmount) {
this.caAmount = caAmount;
}
public int getSaleCount() {
return saleCount;
}
public long getSaleAmount() {
return saleAmount;
}
public int getPreCount() {
return preCount;
}
public long getPreAmount() {
return preAmount;
}
public int getRefundCount() {
return refundCount;
}
public long getRefundAmount() {
return refundAmount;
}
public int getCaCount() {
return caCount;
}
public long getCaAmount() {
return caAmount;
}
}

View File

@ -13,7 +13,6 @@ import com.utsmm.kbz.BR;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants; import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.util.enums.ResponseStatus; import com.utsmm.kbz.util.enums.ResponseStatus;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
/* /*
* This file is not using in this project cuz IPEK is used instead of TMK. * This file is not using in this project cuz IPEK is used instead of TMK.
@ -56,7 +55,6 @@ public class SignOnFragment extends DataBindingFragment {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
signOnViewModel.startSignOnProcess(); signOnViewModel.startSignOnProcess();
observeData(); observeData();
} }

View File

@ -15,6 +15,7 @@ import androidx.annotation.Nullable;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.stream.MalformedJsonException; import com.google.gson.stream.MalformedJsonException;
import com.utsmm.kbz.MainActivity;
import com.utsmm.kbz.service.AutoAlarmReceiver; import com.utsmm.kbz.service.AutoAlarmReceiver;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusError; import com.utsmyanmar.baselib.network.model.sirius.SiriusError;
@ -139,6 +140,8 @@ public class TMSProcessFragment extends DataBindingFragment {
private void downloadParams(String lastTransName,String lastTransTime,TMSUpdate tmsUpdate) { private void downloadParams(String lastTransName,String lastTransTime,TMSUpdate tmsUpdate) {
((MainActivity) requireActivity()).getLocation();
tmsProcessViewModel.setTmsDownloadStatus(TMSDownloadStatus.DOWNLOADING); tmsProcessViewModel.setTmsDownloadStatus(TMSDownloadStatus.DOWNLOADING);
tmsProcessViewModel.setTmsDownloadMsg("Downloading..."); tmsProcessViewModel.setTmsDownloadMsg("Downloading...");

View File

@ -0,0 +1,269 @@
package com.utsmm.kbz.util;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatButton;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.utsmm.kbz.R;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
public class CurrencySelectionHelper {
private static boolean globalPrimaryHostCached = false;
private static String globalPrimaryHostName = "";
private static String globalPrimaryTid = "";
private static String globalPrimaryMid = "";
private static String globalPrimaryIp = "";
private static String globalPrimarySecIp = "";
private static CurrencyType globalPrimaryCurrency = CurrencyType.MMK;
private final Fragment fragment;
private final SharedViewModel sharedViewModel;
private String primaryHostName = "";
private String primaryTid = "";
private String primaryMid = "";
private String primaryIp = "";
private String primarySecIp = "";
private CurrencyType primaryCurrency = CurrencyType.MMK;
public CurrencySelectionHelper(Fragment fragment, SharedViewModel sharedViewModel) {
this.fragment = fragment;
this.sharedViewModel = sharedViewModel;
}
public void showCardCurrencyChooser(Runnable onSelected) {
showCardCurrencyChooser(onSelected, null);
}
public void showCardCurrencyChooser(Runnable onSelected, Runnable onCancelled) {
List<String> currencies = getAvailableCardCurrencies();
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();
}, onCancelled);
}
private List<String> getAvailableCardCurrencies() {
cachePrimaryCardHostIfNeeded();
LinkedHashSet<String> values = new LinkedHashSet<>();
if (primaryCurrency != null && !TextUtils.isEmpty(primaryCurrency.name)) {
values.add(normalizeCurrency(primaryCurrency.name));
}
if (!SystemParamsOperation.getInstance().getDuelCurrencyStatus()) {
return new ArrayList<>(values);
}
String secondaryCurrency = normalizeCurrency(SystemParamsOperation.getInstance().getThirdHostCurrency());
if (!TextUtils.isEmpty(SystemParamsOperation.getInstance().getThirdHostName()) && !TextUtils.isEmpty(secondaryCurrency)) {
values.add(secondaryCurrency);
}
return new ArrayList<>(values);
}
public void applyCardCurrencyAndHost(String selectedCurrency) {
cachePrimaryCardHostIfNeeded();
String selected = normalizeCurrency(selectedCurrency);
String secondaryCurrency = normalizeCurrency(SystemParamsOperation.getInstance().getThirdHostCurrency());
boolean dualCurrencyEnabled = SystemParamsOperation.getInstance().getDuelCurrencyStatus();
boolean useSecondaryCardHost = dualCurrencyEnabled
&& !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(primaryHostName);
SystemParamsOperation.getInstance().setTerminalId(primaryTid);
SystemParamsOperation.getInstance().setMerchantId(primaryMid);
SystemParamsOperation.getInstance().setIpAddress(primaryIp);
SystemParamsOperation.getInstance().setSecIpAddress(primarySecIp);
}
CurrencyType currencyType = useSecondaryCardHost ? toCurrencyType(selected) : primaryCurrency;
SystemParamsOperation.getInstance().setCurrencyType(currencyType);
if (sharedViewModel != null) {
sharedViewModel.set_currencyText(currencyType.name);
}
}
private void cachePrimaryCardHostIfNeeded() {
SystemParamsOperation sp = SystemParamsOperation.getInstance();
String currentHostName = sp.getHostName();
String secondaryHostName = sp.getThirdHostName();
boolean currentIsSecondary = !TextUtils.isEmpty(secondaryHostName)
&& secondaryHostName.equals(currentHostName);
if (!currentIsSecondary) {
globalPrimaryHostName = currentHostName;
globalPrimaryTid = sp.getTerminalId();
globalPrimaryMid = sp.getMerchantId();
globalPrimaryIp = sp.getIpAddress();
globalPrimarySecIp = sp.getSecIpAddress();
CurrencyType activeCurrency = sp.getCurrencyType();
globalPrimaryCurrency = activeCurrency == null ? CurrencyType.MMK : activeCurrency;
globalPrimaryHostCached = true;
}
if (!globalPrimaryHostCached) {
CurrencyType activeCurrency = sp.getCurrencyType();
globalPrimaryCurrency = activeCurrency == null ? CurrencyType.MMK : activeCurrency;
globalPrimaryHostCached = true;
}
primaryHostName = globalPrimaryHostName;
primaryTid = globalPrimaryTid;
primaryMid = globalPrimaryMid;
primaryIp = globalPrimaryIp;
primarySecIp = globalPrimarySecIp;
primaryCurrency = globalPrimaryCurrency;
}
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,
Runnable onCancelled
) {
LinearLayout root = new LinearLayout(fragment.requireContext());
root.setOrientation(LinearLayout.VERTICAL);
root.setPadding(dp(20), dp(20), dp(20), dp(12));
TextView tvTitle = new TextView(fragment.requireContext());
tvTitle.setText(title);
tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
tvTitle.setTextColor(ContextCompat.getColor(fragment.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(fragment.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(fragment.requireContext(), R.color.white));
button.setOnClickListener(v -> {
if (dialogHolder[0] != null) {
dialogHolder[0].dismiss();
}
callback.onSelected(currency);
});
root.addView(button);
}
AppCompatButton cancel = new AppCompatButton(fragment.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(fragment.requireContext(), R.color.colorPrimary));
cancel.setOnClickListener(v -> {
if (dialogHolder[0] != null) {
dialogHolder[0].dismiss();
}
if (onCancelled != null) {
onCancelled.run();
}
});
root.addView(cancel);
AlertDialog dialog = new AlertDialog.Builder(fragment.requireContext())
.setView(root)
.create();
dialogHolder[0] = dialog;
dialog.show();
}
private int dp(int value) {
return Math.round(value * fragment.requireContext().getResources().getDisplayMetrics().density);
}
private interface CurrencySelectCallback {
void onSelected(String currency);
}
}

View File

@ -160,11 +160,16 @@ public class EReceiptUtil {
return request; return request;
} }
private String getDecimalAmount(long amount) {
double realAmount = amount / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
return df.format(realAmount);
}
public EReceiptRequest generateMPUReceipt(PayDetail payDetail) { public EReceiptRequest generateMPUReceipt(PayDetail payDetail) {
double realAmount = payDetail.getAmount() / 100.0;
DecimalFormat df = new DecimalFormat("0.00"); String amount = getDecimalAmount(payDetail.getAmount());
String amount = df.format(realAmount);
String currentTimeStamp = new java.text.SimpleDateFormat("MMddHHmmss", java.util.Locale.getDefault()) String currentTimeStamp = new java.text.SimpleDateFormat("MMddHHmmss", java.util.Locale.getDefault())
.format(new java.util.Date()); .format(new java.util.Date());
@ -178,26 +183,27 @@ public class EReceiptUtil {
SettleData settleData = payDetail.getSettleDataObj(); SettleData settleData = payDetail.getSettleDataObj();
long totalAmt = settleData.getSaleAmount() + settleData.getRefundAmount() + settleData.getPreAuthCompAmount() + settleData.getCashAdvanceAmount(); long totalAmt = settleData.getSaleAmount() + settleData.getRefundAmount() + settleData.getPreAuthCompAmount() + settleData.getCashAdvanceAmount();
double realTotalAmount = totalAmt / 100.0;
String totalAmount = df.format(realTotalAmount); request.setDE4(getDecimalAmount(totalAmt));
request.setDE4(totalAmount);
request.setDE63_01(settleData.getSaleCount() + ""); request.setDE63_01(settleData.getSaleCount() + "");
request.setDE63_02(settleData.getSaleAmount() + ""); request.setDE63_02(getDecimalAmount(settleData.getSaleAmount()));
request.setDE63_03(settleData.getRefundCount() + ""); request.setDE63_03(settleData.getRefundCount() + "");
request.setDE63_04(settleData.getRefundAmount() + ""); request.setDE63_04(getDecimalAmount(settleData.getRefundAmount()));
request.setDE63_05(settleData.getPreAuthCompCount() + ""); request.setDE63_05(settleData.getPreAuthCompCount() + "");
request.setDE63_06(settleData.getPreAuthCompAmount() + ""); request.setDE63_06(getDecimalAmount(settleData.getPreAuthCompAmount()));
request.setDE63_07(settleData.getCashAdvanceCount() + ""); request.setDE63_07(settleData.getCashAdvanceCount() + "");
request.setDE63_08(settleData.getCashAdvanceAmount() + ""); request.setDE63_08(getDecimalAmount(settleData.getCashAdvanceAmount()));
invoiceNo = SystemParamsOperation.getInstance().getIncrementInvoiceNum(); invoiceNo = SystemParamsOperation.getInstance().getIncrementInvoiceNum();
request.setBatchNumber(batchNumber); request.setBatchNumber(batchNumber);
request.setInvoiceNumber(invoiceNo); request.setInvoiceNumber(invoiceNo);
request.setDescription("success"); request.setDescription("success");
request.setDE39("A"); request.setDE39("A");
request.setDE37("0000"); request.setDE37("0000");
request.setDE49("MMK"); request.setDE49(currencyCodeToText(payDetail.getCurrencyCode()));
} else { } else {
request.setDE2(POSUtil.getInstance().getCardNumMasking(payDetail.getCardNo())); request.setDE2(POSUtil.getInstance().getCardNumMasking(payDetail.getCardNo()));
@ -207,9 +213,9 @@ public class EReceiptUtil {
request.setDE37(payDetail.getReferNo()); request.setDE37(payDetail.getReferNo());
request.setDE38(payDetail.getApprovalCode()); request.setDE38(payDetail.getApprovalCode());
// will check it later for currency code // will check it later for currency code
request.setDE49("MMK"); request.setDE49(currencyCodeToText(payDetail.getCurrencyCode()));
request.setInvoiceNumber(payDetail.getInvoiceNo()); request.setInvoiceNumber(payDetail.getInvoiceNo());
request.setCardLabel("MPU"); request.setCardLabel(payDetail.getAccountType());
if (payDetail.getTradeAnswerCode().equals("000") || payDetail.getTradeAnswerCode().equals("00")) { if (payDetail.getTradeAnswerCode().equals("000") || payDetail.getTradeAnswerCode().equals("00")) {
@ -279,6 +285,28 @@ public class EReceiptUtil {
return request; return request;
} }
private String currencyCodeToText(String currencyCode) {
String currencyText = "MMK";
switch (currencyCode) {
case "840":
currencyCode = "USD";
break;
case "156":
currencyCode = "RMB";
break;
case "764":
currencyCode = "THB";
break;
case "643":
currencyCode = "RUB";
break;
default:
currencyCode = "MMK";
break;
}
return currencyCode;
}
private static List<Transaction> buildTransactions(List<QRSettleData> qrSettleData) { private static List<Transaction> buildTransactions(List<QRSettleData> qrSettleData) {
List<Transaction> list = new ArrayList<>(); List<Transaction> list = new ArrayList<>();

View File

@ -0,0 +1,111 @@
package com.utsmm.kbz.util;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
public class LocationUtil {
public interface LocationCallback {
void onSuccess(double lat, double lng);
void onError(String reason);
}
private static LocationListener listener;
private static double lat = 0.00;
private static double lng = 0.00;
public static void getCurrentLocation(
@NonNull Activity activity,
@NonNull LocationCallback callback) {
LocationManager lm =
(LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
if (lm == null) {
callback.onError("LocationManager is null");
return;
}
if (ActivityCompat.checkSelfPermission(activity,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
activity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
201
);
callback.onError("Permission not granted");
return;
}
boolean gpsEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean netEnabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!gpsEnabled && !netEnabled) {
callback.onError("No location provider enabled");
return;
}
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location == null) {
location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if (location != null) {
callback.onSuccess(location.getLatitude(), location.getLongitude());
return;
}
listener = new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
callback.onSuccess(
location.getLatitude(),
location.getLongitude()
);
lm.removeUpdates(this); // 🔥 stop GPS
}
};
lm.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
2000,
1,
listener
);
}
public static void stop(Context context) {
if (listener != null) {
LocationManager lm =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (lm != null) lm.removeUpdates(listener);
listener = null;
}
}
public static double getLat() {
return lat;
}
public static double getLng() {
return lng;
}
public static void setLat(double lat) {
LocationUtil.lat = lat;
}
public static void setLng(double lng) {
LocationUtil.lng = lng;
}
}

View File

@ -6,6 +6,7 @@ import com.utsmyanmar.paylibs.model.CardInfo;
import com.utsmyanmar.paylibs.model.MAGCardInfo; import com.utsmyanmar.paylibs.model.MAGCardInfo;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData; import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.model.enums.TransCVM;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType; import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.params.Params; import com.utsmyanmar.paylibs.utils.params.Params;
@ -98,7 +99,8 @@ public class TransactionUtil {
PayDetail payDetail = tradeData.getPayDetail(); PayDetail payDetail = tradeData.getPayDetail();
payDetail.setCardNo(cardDataX.getPan()); payDetail.setCardNo(cardDataX.getPan());
payDetail.setEXPDate(cardDataX.getExp()); payDetail.setEXPDate(cardDataX.getExp());
payDetail.setTransCVM(TransCVM.SIGNATURE);
if(cardDataX.getPan().startsWith("4")) { if(cardDataX.getPan().startsWith("4")) {
payDetail.setAccountType(VISA_CARD_SCHEME); payDetail.setAccountType(VISA_CARD_SCHEME);
} else if(cardDataX.getPan().startsWith("5")) { } else if(cardDataX.getPan().startsWith("5")) {

View File

@ -22,5 +22,6 @@ public enum FeaturesType {
QR_INQUIRY, QR_INQUIRY,
QR_REFUND, QR_REFUND,
LOG_OUT, LOG_OUT,
DEVICE_CONFIG DEVICE_CONFIG,
} CLEAR_REVERSAL
}

View File

@ -3,6 +3,8 @@ package com.utsmm.kbz.util.enums;
public enum TransactionStatus { public enum TransactionStatus {
ON_SUCCESS, ON_SUCCESS,
ON_FINAL_SUCCESS,
ON_REVERSAL, ON_REVERSAL,
ON_BATCH_UPLOAD, ON_BATCH_UPLOAD,
ON_FAIL, ON_FAIL,

View File

@ -149,6 +149,9 @@ public class TMSSetupsImpl implements TMSSetups{
List<SiriusHost> siriusHosts = siriusResponse.getHosts(); List<SiriusHost> siriusHosts = siriusResponse.getHosts();
List<SiriusProperty> siriusProperties = siriusResponse.getProperties(); List<SiriusProperty> siriusProperties = siriusResponse.getProperties();
boolean isDualCurrencyEnabled = isDualCurrencyEnabled(siriusProperties);
SystemParamsOperation.getInstance().setDuelCurrencyStatus(isDualCurrencyEnabled);
ArrayList<String> imgUrls = new ArrayList<>(); ArrayList<String> imgUrls = new ArrayList<>();
@ -579,12 +582,23 @@ public class TMSSetupsImpl implements TMSSetups{
emvParamOperation.updatePayPassCurrencyCode(data); emvParamOperation.updatePayPassCurrencyCode(data);
} else if (TextUtils.equals(name,"terminal_capability")) { } else if (TextUtils.equals(name, "visa_terminal_capability")) {
if(!data.isEmpty()){
if(!data.isEmpty()) { SystemParamsOperation.getInstance().setVisaTerminalCapability(data);
SystemParamsOperation.getInstance().setTerminalCapability(data); }
}else if (TextUtils.equals(name, "master_terminal_capability")) {
if(!data.isEmpty()){
SystemParamsOperation.getInstance().setMasterTerminalCapability(data);
}
}
else if (TextUtils.equals(name, "upi_terminal_capability")) {
if(!data.isEmpty()){
SystemParamsOperation.getInstance().setUpiTerminalCapability(data);
}
} else if (TextUtils.equals(name, "jcb_terminal_capability")) {
if(!data.isEmpty()){
SystemParamsOperation.getInstance().setJcbTerminalCapability(data);
} }
} else if (TextUtils.equals(name,"upi_ttq")) { } else if (TextUtils.equals(name,"upi_ttq")) {
emvParamOperation.updateQuickPassTTQ(data); emvParamOperation.updateQuickPassTTQ(data);
} else if (TextUtils.equals(name, "upi_tc_enabled")) { } else if (TextUtils.equals(name, "upi_tc_enabled")) {
@ -631,8 +645,24 @@ public class TMSSetupsImpl implements TMSSetups{
else if(TextUtils.equals(name,"bin_list")) { else if(TextUtils.equals(name,"bin_list")) {
SystemParamsOperation.getInstance().setBinValue(data); SystemParamsOperation.getInstance().setBinValue(data);
} }
else if (TextUtils.equals(name, "restricted_bin_list")) {
SystemParamsOperation.getInstance().setRestrictedBinValue(data);
}
else if(TextUtils.equals(name, "printer_enabled")){ else if(TextUtils.equals(name, "printer_enabled")){
SystemParamsOperation.getInstance().setPrinterEnabled(parseBoolean(data)); SystemParamsOperation.getInstance().setPrinterEnabled(parseBoolean(data));
}else if(TextUtils.equals(name, "is_duel_currency")){
SystemParamsOperation.getInstance().setDuelCurrencyStatus(parseBoolean(data));
}
else if(TextUtils.equals(name, "pre_auth_cancel_manual_enabled")) {
SystemParamsOperation.getInstance().setPreAuthVoidManualEnabled(parseBoolean(data));
}
else if(TextUtils.equals(name, "pre_auth_complete_manual_enabled")) {
SystemParamsOperation.getInstance().setPreAuthCompleteManualEnabled(parseBoolean(data));
}
else if(TextUtils.equals(name, "pre_auth_manual_enabled")) {
SystemParamsOperation.getInstance().setPreAuthManualEnabled(parseBoolean(data));
}else if(TextUtils.equals(name, "auto_reversal_enable")) {
SystemParamsOperation.getInstance().setAutoReversalEnable(parseBoolean(data));
} }
} }
@ -645,6 +675,24 @@ public class TMSSetupsImpl implements TMSSetups{
return EReceiptHelper.sha256(dataToHash); return EReceiptHelper.sha256(dataToHash);
} }
private boolean isDualCurrencyEnabled(List<SiriusProperty> siriusProperties) {
if (siriusProperties == null) {
return false;
}
for (SiriusProperty siriusProperty : siriusProperties) {
if (siriusProperty == null) {
continue;
}
if (TextUtils.equals("is_duel_currency", siriusProperty.getName())) {
return parseBoolean(siriusProperty.getProperty());
}
}
return false;
}
private String convertToString(ArrayList<String> list) { private String convertToString(ArrayList<String> list) {

View File

@ -7,6 +7,7 @@ import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.kizzy.xpay.XPay; import com.kizzy.xpay.XPay;
import com.utsmm.kbz.util.LocationUtil;
import com.utsmyanmar.baselib.emv.EmvParamOperation; import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest; import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest;
import com.utsmyanmar.baselib.network.model.sirius.SiriusResponse; import com.utsmyanmar.baselib.network.model.sirius.SiriusResponse;
@ -139,6 +140,7 @@ public class TMSUtil {
public SiriusRequest generateRequestParams(Context context,String lastTransName,String lastTransTime) { public SiriusRequest generateRequestParams(Context context,String lastTransName,String lastTransTime) {
SiriusRequest siriusRequest = new SiriusRequest(); SiriusRequest siriusRequest = new SiriusRequest();
siriusRequest.setSerial(getSerialNumber()); siriusRequest.setSerial(getSerialNumber());
siriusRequest.setAppPackage(BuildConfig.APPLICATION_ID); siriusRequest.setAppPackage(BuildConfig.APPLICATION_ID);
@ -148,6 +150,8 @@ public class TMSUtil {
siriusRequest.setCurrentNetwork(getNetworkType(context)); siriusRequest.setCurrentNetwork(getNetworkType(context));
siriusRequest.setLastTransaction(lastTransName); siriusRequest.setLastTransaction(lastTransName);
siriusRequest.setLastTranTime(Long.parseLong(lastTransTime)); siriusRequest.setLastTranTime(Long.parseLong(lastTransTime));
siriusRequest.setLatitude(LocationUtil.getLat());
siriusRequest.setLongitude(LocationUtil.getLng());
siriusRequest.setValue("YourValueHere"); siriusRequest.setValue("YourValueHere");
return siriusRequest; return siriusRequest;
@ -219,6 +223,7 @@ public class TMSUtil {
// featuresList.add(new Features(5, fragmentActivity.getString(R.string.menu_wavepay_inquiry), R.drawable.ic_wave_status_dash, FeaturesType.WAVE_PAY_INQUIRY, wavePayInquiryStatus)); // featuresList.add(new Features(5, fragmentActivity.getString(R.string.menu_wavepay_inquiry), R.drawable.ic_wave_status_dash, FeaturesType.WAVE_PAY_INQUIRY, wavePayInquiryStatus));
featuresList.add(new Features(1, fragmentActivity.getString(R.string.menu_cash_advance), R.drawable.ic_cash_advance, FeaturesType.CASH_ADVANCE, cashAdvanceStatus)); featuresList.add(new Features(1, fragmentActivity.getString(R.string.menu_cash_advance), R.drawable.ic_cash_advance, FeaturesType.CASH_ADVANCE, cashAdvanceStatus));
// featuresList.add(new Features(9, fragmentActivity.getString(R.string.menu_history), R.drawable.ic_history, FeaturesType.HISTORY, true)); // featuresList.add(new Features(9, fragmentActivity.getString(R.string.menu_history), R.drawable.ic_history, FeaturesType.HISTORY, true));
featuresList.add(new Features(11, "Clear Reversal", R.drawable.ic_clear_all, FeaturesType.CLEAR_REVERSAL, true));
featuresList.add(new Features(10, "Configs", R.drawable.ic_host, FeaturesType.DEVICE_CONFIG, true)); featuresList.add(new Features(10, "Configs", R.drawable.ic_host, FeaturesType.DEVICE_CONFIG, true));
} }

View File

@ -39,6 +39,7 @@
app:layout_constraintEnd_toEndOf="parent"> app:layout_constraintEnd_toEndOf="parent">
<LinearLayout <LinearLayout
android:visibility="@{sharedVM.amount.equals(`0`) || sharedVM.amount.equals(`0.00`) ? View.GONE : View.VISIBLE}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
@ -141,6 +142,7 @@
android:weightSum="3"> android:weightSum="3">
<!-- Tap Card --> <!-- Tap Card -->
<!-- android:onClick="@{()->click.onClickTap()}"-->
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="96dp" android:layout_height="96dp"
@ -149,7 +151,6 @@
android:layout_weight="1" android:layout_weight="1"
app:cardCornerRadius="12dp" app:cardCornerRadius="12dp"
app:cardElevation="2dp" app:cardElevation="2dp"
android:onClick="@{()->click.onClickTap()}"
android:backgroundTint="#fff" android:backgroundTint="#fff"
android:foreground="?android:attr/selectableItemBackground" android:foreground="?android:attr/selectableItemBackground"
android:focusable="true" android:focusable="true"

View File

@ -120,16 +120,17 @@
<TextView <TextView
android:id="@+id/txt_emv_remaining_count" android:id="@+id/txt_emv_remaining_count"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_button" android:layout_marginTop="@dimen/margin_button"
android:fontFamily="@font/rubik_regular" android:fontFamily="@font/rubik_regular"
android:gravity="center"
android:text="@{emv.pinRemainingCount}" android:text="@{emv.pinRemainingCount}"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="@dimen/pan_size" android:textSize="@dimen/pan_size"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/textView3" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView20" app:layout_constraintTop_toBottomOf="@+id/txt_emv_pin_mode"
app:layout_goneMarginTop="@dimen/margin_button" app:layout_goneMarginTop="@dimen/margin_button"
tools:text="3 LEFT" /> tools:text="3 LEFT" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -100,6 +100,7 @@
android:textColor="@color/colorTextContent" android:textColor="@color/colorTextContent"
android:textSize="14sp" android:textSize="14sp"
tools:fontFamily="sans-serif" /> tools:fontFamily="sans-serif" />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -155,69 +156,11 @@
android:textStyle="bold" android:textStyle="bold"
tools:fontFamily="sans-serif-medium" /> tools:fontFamily="sans-serif-medium" />
<!-- Terminal ID -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="@font/rubik_regular"
android:text="Terminal ID:"
android:textColor="@color/colorTextContent"
android:textSize="14sp"
tools:fontFamily="sans-serif" />
<TextView
android:id="@+id/terminalIdValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/rubik_medium"
android:text="Not configured"
android:textColor="@color/colorTextTitle"
android:textSize="14sp"
tools:fontFamily="sans-serif-medium" />
</LinearLayout>
<!-- Merchant ID -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="@font/rubik_regular"
android:text="Merchant ID:"
android:textColor="@color/colorTextContent"
android:textSize="14sp"
tools:fontFamily="sans-serif" />
<TextView
android:id="@+id/merchantIdValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/rubik_medium"
android:text="Not configured"
android:textColor="@color/colorTextTitle"
android:textSize="14sp"
tools:fontFamily="sans-serif-medium" />
</LinearLayout>
<!-- Serial Number --> <!-- Serial Number -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="12dp"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView

View File

@ -53,7 +53,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/enter_trace_text" android:text="Enter Invoice Number"
android:textAlignment="center" android:textAlignment="center"
android:textColor="@color/colorPrimary" android:textColor="@color/colorPrimary"
android:textSize="17sp" android:textSize="17sp"
@ -65,7 +65,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Enter the transaction trace number" android:text="Enter the transaction invoice number"
android:textAlignment="center" android:textAlignment="center"
android:textColor="@color/colorPrimary" android:textColor="@color/colorPrimary"
android:textSize="12sp" android:textSize="12sp"

View File

@ -3,6 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<data> <data>
<import type="android.view.View" />
<variable <variable
name="sharedViewModel" name="sharedViewModel"
type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" /> type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" />
@ -93,6 +94,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="12dp" android:layout_marginBottom="12dp"
android:visibility="@{sharedViewModel.printerDisabled ? View.GONE : View.VISIBLE}"
app:cardCornerRadius="12dp" app:cardCornerRadius="12dp"
app:cardElevation="0dp" app:cardElevation="0dp"
app:cardBackgroundColor="@color/white" app:cardBackgroundColor="@color/white"

View File

@ -187,7 +187,7 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{sharedViewModel._currencyText+` `+sharedViewModel.amount}" android:text="@{sharedViewModel.payDetail != null ? POSUtil.getInstance().currencyCodeToText(sharedViewModel.payDetail.currencyCode)+` `+POSUtil.getInstance().getDecimalAmountVoidFormat(sharedViewModel.payDetail) : sharedViewModel._currencyText+` `+sharedViewModel.amount}"
android:textColor="@color/colorTextTitle" android:textColor="@color/colorTextTitle"
android:textSize="14sp" android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"

View File

@ -729,7 +729,9 @@
android:onClick="@{()->click.onReversalClick()}" android:onClick="@{()->click.onReversalClick()}"
app:cardBackgroundColor="@color/white" app:cardBackgroundColor="@color/white"
app:cardCornerRadius="16dp" app:cardCornerRadius="16dp"
app:cardElevation="2dp"> app:cardElevation="2dp"
>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -969,6 +971,81 @@
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
<!-- Clear Reversal Card -->
<androidx.cardview.widget.CardView
android:id="@+id/clearReversalCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
android:onClick="@{()->click.onClearReversalClick()}"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="20dp">
<androidx.cardview.widget.CardView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="16dp"
app:cardBackgroundColor="@color/colorPrimary"
app:cardCornerRadius="24dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:src="@drawable/ic_clear_all"
app:tint="@color/white" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/rubik_medium"
android:text="@string/title_clear_reversal"
android:textColor="@color/colorTextTitle"
android:textSize="18sp"
android:textStyle="bold"
tools:fontFamily="sans-serif-medium" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:fontFamily="@font/rubik_regular"
android:text="@string/clear_reversal_description"
android:textColor="@color/colorTextContent"
android:textSize="14sp"
tools:fontFamily="sans-serif" />
</LinearLayout>
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_right_arrow"
app:tint="@color/colorPrimary" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- TMS Server URL Card --> <!-- TMS Server URL Card -->
<!-- android:onClick="@{()->click.onTmsAddressClick()}"--> <!-- android:onClick="@{()->click.onTmsAddressClick()}"-->
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView

View File

@ -279,7 +279,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="@{sharedViewModel.payDetail.invoiceNo}" android:text="@{sharedViewModel.payDetail.voucherNo}"
android:textAlignment="textEnd" android:textAlignment="textEnd"
android:textColor="@color/colorPrimary" android:textColor="@color/colorPrimary"
android:textSize="15sp" android:textSize="15sp"
@ -355,7 +355,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="@{sharedViewModel.payDetail.voucherNo}" android:text="@{sharedViewModel.payDetail.invoiceNo}"
android:textAlignment="textEnd" android:textAlignment="textEnd"
android:textColor="@color/colorPrimary" android:textColor="@color/colorPrimary"
android:textSize="15sp" android:textSize="15sp"

View File

@ -118,7 +118,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:background="@null" android:background="@null"
android:hint="@string/txt_search_by_trace" android:hint="Search By Invoice/RRN"
android:textColorHint="@color/colorPrimary" android:textColorHint="@color/colorPrimary"
android:alpha="0.6" android:alpha="0.6"
android:text="@={manageViewModel.txtRRNTrace}" android:text="@={manageViewModel.txtRRNTrace}"

View File

@ -74,41 +74,56 @@
android:layout_marginTop="19dp" android:layout_marginTop="19dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<TextView <LinearLayout
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:orientation="horizontal">
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular" <TextView
android:text="@string/txt_subtitle_sale" android:layout_width="0dp"
android:textSize="16sp" /> android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@string/txt_subtitle_sale"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@={settleViewModel.sale_count+``}"
tools:text="5"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@{POSUtil.getInstance().getDecimalAmountSeparatorFormat(settleViewModel.sale_amount)}"
tools:text="65.00"
android:textAlignment="textEnd"
android:textSize="16sp" />
</LinearLayout>
<TextView <TextView
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_marginTop="6dp"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular" android:fontFamily="@font/rubik_regular"
android:text="@={settleViewModel.sale_count+``}" android:text="@{settleViewModel.sale_breakdown}"
tools:text="5" android:textColor="@color/colorTextContent"
android:textSize="12sp"
android:textSize="16sp" /> tools:text="MMK 2 / 10,000.00 USD 1 / 25.00" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@{POSUtil.getInstance().getDecimalAmountSeparatorFormat(settleViewModel.sale_amount)}"
tools:text="65.00"
android:textAlignment="textEnd"
android:textSize="16sp" />
</LinearLayout> </LinearLayout>
@ -122,41 +137,56 @@
android:layout_marginTop="19dp" android:layout_marginTop="19dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<TextView <LinearLayout
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:orientation="horizontal">
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular" <TextView
android:text="@string/txt_subtitle_sale_completion" android:layout_width="0dp"
android:textSize="16sp" /> android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@string/txt_subtitle_sale_completion"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@={settleViewModel.pre_count+``}"
tools:text="0"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@{POSUtil.getInstance().getDecimalAmountSeparatorFormat(settleViewModel.pre_amount)}"
tools:text="0.00"
android:textAlignment="textEnd"
android:textSize="16sp" />
</LinearLayout>
<TextView <TextView
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_marginTop="6dp"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular" android:fontFamily="@font/rubik_regular"
android:text="@={settleViewModel.pre_count+``}" android:text="@{settleViewModel.pre_breakdown}"
tools:text="0" android:textColor="@color/colorTextContent"
android:textSize="12sp"
android:textSize="16sp" /> tools:text="MMK 1 / 8,000.00 USD 1 / 15.00" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@{POSUtil.getInstance().getDecimalAmountSeparatorFormat(settleViewModel.pre_amount)}"
tools:text="0.00"
android:textAlignment="textEnd"
android:textSize="16sp" />
</LinearLayout> </LinearLayout>
@ -170,42 +200,56 @@
android:layout_marginTop="19dp" android:layout_marginTop="19dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<TextView <LinearLayout
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:orientation="horizontal">
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular" <TextView
android:text="@string/txt_subtitle_refund" android:layout_width="0dp"
android:textSize="16sp" /> android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@string/txt_subtitle_refund"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:textColor="@color/black"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="@font/rubik_regular"
android:text="@={settleViewModel.refund_count+``}"
tools:text="0"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@{POSUtil.getInstance().getDecimalAmountSeparatorFormat(settleViewModel.refund_amount)}"
tools:text="0.00"
android:textAlignment="textEnd"
android:textSize="16sp" />
</LinearLayout>
<TextView <TextView
android:layout_width="0dp" android:layout_width="match_parent"
android:textColor="@color/black"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_marginTop="6dp"
android:fontFamily="@font/rubik_regular" android:fontFamily="@font/rubik_regular"
android:text="@{settleViewModel.refund_breakdown}"
android:text="@={settleViewModel.refund_count+``}" android:textColor="@color/colorTextContent"
tools:text="0" android:textSize="12sp"
tools:text="MMK 0 / 0.00 USD 1 / 10.00" />
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@{POSUtil.getInstance().getDecimalAmountSeparatorFormat(settleViewModel.refund_amount)}"
tools:text="0.00"
android:textAlignment="textEnd"
android:textSize="16sp" />
</LinearLayout> </LinearLayout>
@ -219,43 +263,57 @@
android:layout_marginTop="19dp" android:layout_marginTop="19dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="vertical"
android:visibility="@{settleViewModel.ca_count > 0 ? 0 : 8}" android:visibility="@{settleViewModel.ca_count > 0 ? 0 : 8}"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<TextView <LinearLayout
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="2" android:orientation="horizontal">
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular" <TextView
android:text="@string/text_cash_advance" android:layout_width="0dp"
android:textSize="16sp" /> android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@string/text_cash_advance"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:textColor="@color/black"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fontFamily="@font/rubik_regular"
android:text="@={settleViewModel.ca_count+``}"
tools:text="0"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@{POSUtil.getInstance().getDecimalAmountSeparatorFormat(settleViewModel.ca_amount)}"
tools:text="0.00"
android:textAlignment="textEnd"
android:textSize="16sp" />
</LinearLayout>
<TextView <TextView
android:layout_width="0dp" android:layout_width="match_parent"
android:textColor="@color/black"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_marginTop="6dp"
android:fontFamily="@font/rubik_regular" android:fontFamily="@font/rubik_regular"
android:text="@{settleViewModel.ca_breakdown}"
android:text="@={settleViewModel.ca_count+``}" android:textColor="@color/colorTextContent"
tools:text="0" android:textSize="12sp"
tools:text="MMK 1 / 5,000.00 USD 0 / 0.00" />
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textColor="@color/black"
android:fontFamily="@font/rubik_regular"
android:text="@{POSUtil.getInstance().getDecimalAmountSeparatorFormat(settleViewModel.ca_amount)}"
tools:text="0.00"
android:textAlignment="textEnd"
android:textSize="16sp" />
</LinearLayout> </LinearLayout>

View File

@ -77,6 +77,35 @@
tools:text="000045" /> tools:text="000045" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingVertical="4dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Currency"
android:textColor="@color/colorPrimary"
android:textSize="13sp"
android:fontFamily="monospace"
android:textAlignment="center"
tools:text="Currency" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{POSUtil.getInstance().currencyCodeToText(payDetail.currencyCode)}"
android:textColor="@color/colorPrimary"
android:textSize="13sp"
android:fontFamily="monospace"
android:textAlignment="center"
tools:text="MMK" />
</LinearLayout>
<!-- Data Row 3: Transaction Type and Amount --> <!-- Data Row 3: Transaction Type and Amount -->
<LinearLayout <LinearLayout

View File

@ -5,6 +5,7 @@
<data> <data>
<import type="androidx.databinding.ObservableBoolean"/>
<variable <variable
name="sharedViewModel" name="sharedViewModel"
type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" /> type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" />
@ -376,6 +377,84 @@
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
tools:fontFamily="sans-serif-medium" /> tools:fontFamily="sans-serif-medium" />
<!-- Pinpad Sound Card -->
<androidx.cardview.widget.CardView
android:id="@+id/pinpadSoundCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
android:onClick="@{()->click.onClickPinpadSound()}"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="20dp">
<androidx.cardview.widget.CardView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="16dp"
app:cardBackgroundColor="@color/colorPrimary"
app:cardCornerRadius="24dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:src="@drawable/ic_audio"
app:tint="@color/white" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/rubik_medium"
android:text="Enable Pinpad Sound"
android:textColor="@color/colorTextTitle"
android:textSize="18sp"
android:textStyle="bold"
tools:fontFamily="sans-serif-medium" />
<TextView
android:id="@+id/pinpadSoundSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:fontFamily="@font/rubik_regular"
android:text="Pinpad key press sound disabled"
android:textColor="@color/colorTextContent"
android:textSize="14sp"
tools:fontFamily="sans-serif" />
</LinearLayout>
<Switch
android:id="@+id/pinpadSoundSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:checked="@{click.pinpadSoundEnabled}"
android:clickable="false"
android:focusable="false" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Function Card --> <!-- Function Card -->
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView

View File

@ -615,7 +615,7 @@
<string name="txt_total_qr_transactions">Total QR Transactions</string> <string name="txt_total_qr_transactions">Total QR Transactions</string>
<string name="txt_no_qr_transactions_to_settle">No QR transactions to settle</string> <string name="txt_no_qr_transactions_to_settle">No QR transactions to settle</string>
<string name="txt_settle_qr_transactions">Confirm</string> <string name="txt_settle_qr_transactions">Confirm</string>
<string name="txt_search_by_trace">Search By Trace No</string> <string name="txt_search_by_trace">Search By Inv No</string>
<string name="txt_continue">Continue</string> <string name="txt_continue">Continue</string>
</resources> </resources>

View File

@ -4,6 +4,7 @@ import com.utsmyanmar.baselib.util.EReceiptHelper;
import org.junit.Test; import org.junit.Test;
import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -21,6 +22,19 @@ public class GeneralTest {
} }
@Test
public void testDecimalAmount() {
long amount = 0L;
String decimalAmount = getDecimalAmount(amount);
System.out.println("amount :"+decimalAmount);
}
private String getDecimalAmount(long amount) {
double realAmount = amount / 100.0;
DecimalFormat df = new DecimalFormat("0.00");
return df.format(realAmount);
}
private static String generateSignature(String timestamp) { private static String generateSignature(String timestamp) {
String secret = "y812J21lhha11OS"; String secret = "y812J21lhha11OS";
String bodyString = "{}"; String bodyString = "{}";

View File

@ -11,8 +11,8 @@
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 1, "versionCode": 33,
"versionName": "1.00-uat", "versionName": "2.13-uat",
"outputFile": "app-uat-release.apk" "outputFile": "app-uat-release.apk"
} }
], ],

View File

@ -21,12 +21,8 @@ import com.utsmyanmar.paylibs.utils.LogUtil;
public final class TerminalKeyUtil { public final class TerminalKeyUtil {
public static final String TAG = TerminalKeyUtil.class.getSimpleName(); public static final String TAG = TerminalKeyUtil.class.getSimpleName();
private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("".toUpperCase()); // KBZ PROD
// private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("875f63741753d18811a3449090d1777b".toUpperCase()); // KBZ UAT
private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("e121249099a677e8b7d4f6a9d49fe8d1".toUpperCase()); // MPU
private static final byte[] work_key_data = new byte[16]; private static final byte[] work_key_data = new byte[16];
public static void initNexKey() { public static void initNexKey() {
byte[] IPEKByte = ByteUtil.hexStr2Bytes("5A4CFF6DE93F0488926166F3317EFD2F"); // IPEK byte[] IPEKByte = ByteUtil.hexStr2Bytes("5A4CFF6DE93F0488926166F3317EFD2F"); // IPEK
byte[] IPEKKCVByte = ByteUtil.hexStr2Bytes("1F0C18"); byte[] IPEKKCVByte = ByteUtil.hexStr2Bytes("1F0C18");
@ -38,6 +34,7 @@ public final class TerminalKeyUtil {
PinPad pinPad = BaseApplication.getInstance().deviceEngine.getPinPad(); PinPad pinPad = BaseApplication.getInstance().deviceEngine.getPinPad();
int result = pinPad.writeMKey(9, main_key_data, main_key_data.length); int result = pinPad.writeMKey(9, main_key_data, main_key_data.length);
byte[] kcv = pinPad.calcWKeyKCV(9,WorkKeyTypeEnum.ENCRYPTIONKEY);
// //
// int resultPINKEY = pinPad.writeWKey(0, WorkKeyTypeEnum.PINKEY, work_key_data, work_key_data.length); // int resultPINKEY = pinPad.writeWKey(0, WorkKeyTypeEnum.PINKEY, work_key_data, work_key_data.length);
@ -49,7 +46,8 @@ public final class TerminalKeyUtil {
// int result = pinPad.dukptKeyInject(9, DukptKeyTypeEnum.IPEK,IPEKByte,16,KSNByte); // int result = pinPad.dukptKeyInject(9, DukptKeyTypeEnum.IPEK,IPEKByte,16,KSNByte);
// int result = pinPad.dukptKeyInject(9, DukptKeyTypeEnum.BDK,IPEKByte,16,ksn); // int result = pinPad.dukptKeyInject(9, DukptKeyTypeEnum.BDK,IPEKByte,16,ksn);
LogUtil.d(TAG, "save tmk key result: "+result); // LogUtil.d(TAG, "save tmk key result: "+result);
// LogUtil.d(TAG, "save tmk kcv: "+ByteUtil.bytes2HexStr(kcv));
// byte[] encryptedPIK = SystemParamsOperation.getInstance().getKeyPIK().get(0); // byte[] encryptedPIK = SystemParamsOperation.getInstance().getKeyPIK().get(0);
// //

View File

@ -97,6 +97,12 @@ public interface PayDetailDao {
@Query("SELECT * FROM paydetail WHERE transactionType = 10 AND isNeedReversal = 1 AND voucherNo IN(:voucherNo)") @Query("SELECT * FROM paydetail WHERE transactionType = 10 AND isNeedReversal = 1 AND voucherNo IN(:voucherNo)")
LiveData<PayDetail> getReversalTransaction(String voucherNo); LiveData<PayDetail> getReversalTransaction(String voucherNo);
@Query("SELECT * FROM PayDetail WHERE isNeedReversal = 1 ORDER BY PID DESC LIMIT 1")
LiveData<PayDetail> getLastReversalTransactionLive();
@Query("SELECT * FROM PayDetail WHERE isNeedReversal = 1 ORDER BY PID DESC")
LiveData<List<PayDetail>> getAllReversalTransactionsLive();
// @Query("SELECT * FROM paydetail WHERE transactionType != 10 ORDER BY PID DESC") // @Query("SELECT * FROM paydetail WHERE transactionType != 10 ORDER BY PID DESC")
@Query("SELECT * FROM paydetail ORDER BY PID DESC") @Query("SELECT * FROM paydetail ORDER BY PID DESC")
LiveData<List<PayDetail>> getTransactionHistory(); LiveData<List<PayDetail>> getTransactionHistory();
@ -137,6 +143,10 @@ public interface PayDetailDao {
@Query(("SELECT * FROM paydetail WHERE isCanceled = 0 AND CardNo IN(:cardNo) AND referNo IN(:referNo)")) @Query(("SELECT * FROM paydetail WHERE isCanceled = 0 AND CardNo IN(:cardNo) AND referNo IN(:referNo)"))
LiveData<PayDetail> searchPayDetail(String cardNo,String referNo); LiveData<PayDetail> searchPayDetail(String cardNo,String referNo);
@Query(("SELECT * FROM paydetail WHERE isCanceled = 0 AND isAdjust = 0 AND CardNo IN(:cardNo) AND referNo IN(:referNo)"))
LiveData<PayDetail> searchPayDetailPreCancel(String cardNo,String referNo);
@Query("SELECT * FROM paydetail WHERE isCanceled = 0 AND transactionType = 5") @Query("SELECT * FROM paydetail WHERE isCanceled = 0 AND transactionType = 5")
LiveData<List<PayDetail>> getPreAuthCompData(); LiveData<List<PayDetail>> getPreAuthCompData();

View File

@ -254,7 +254,8 @@ public class NetworkModule {
} }
if (baseUrl.isEmpty()) { if (baseUrl.isEmpty()) {
baseUrl = "http://api-uat.kbzpay.com/payment/gateway/uat/"; // baseUrl = "http://api-uat.kbzpay.com/payment/gateway/uat/"; //UAT
baseUrl = "https://api.kbzpay.com/payment/gateway/"; //Prod
} }
return new Retrofit.Builder() return new Retrofit.Builder()
.baseUrl(baseUrl) .baseUrl(baseUrl)
@ -310,8 +311,8 @@ public Retrofit provideKPayRefundRetrofit(@ApplicationContext Context context) {
// char[] password = "test123".toCharArray(); // char[] password = "test123".toCharArray();
// String refundBaseUrl = "https://api.kbzpay.com:8008/payment/gateway/"; String refundBaseUrl = "https://api.kbzpay.com:8008/payment/gateway/";
String refundBaseUrl = "https://api-uat.kbzpay.com:18008/payment/gateway/uat/"; // String refundBaseUrl = "https://api-uat.kbzpay.com:18008/payment/gateway/uat/";
// String IpAddress = SystemParamsOperation.getInstance().getSecHostIpAddress(); // String IpAddress = SystemParamsOperation.getInstance().getSecHostIpAddress();
@ -325,7 +326,7 @@ public Retrofit provideKPayRefundRetrofit(@ApplicationContext Context context) {
String pass = SystemParamsOperation.getInstance().getCertificatePassword(); String pass = SystemParamsOperation.getInstance().getCertificatePassword();
if (TextUtils.isEmpty(pass)) { if (TextUtils.isEmpty(pass)) {
pass = "test123"; pass = "";
} }
char[] password = pass.toCharArray(); char[] password = pass.toCharArray();

View File

@ -349,7 +349,7 @@ public class EmvParamHelper {
private AidEntity convertContactlessAIDNex(ContactlessAid contactlessAid) { private AidEntity convertContactlessAIDNex(ContactlessAid contactlessAid) {
AidEntity aidV2 = new AidEntity(); AidEntity aidV2 = new AidEntity();
aidV2.setTransType("FF"); aidV2.setTransType("FF"); // FF
aidV2.setOnlinePinCap(1); aidV2.setOnlinePinCap(1);
aidV2.setAsi(0); aidV2.setAsi(0);
aidV2.setThreshold(0); aidV2.setThreshold(0);
@ -412,7 +412,8 @@ public class EmvParamHelper {
aidV2.setTransType("FF"); aidV2.setTransType("FF");
aidV2.setOnlinePinCap(1); aidV2.setOnlinePinCap(1);
aidV2.setAsi(1); aidV2.setAsi(1); //1
// aidV2.setThreshold(99);
if (!(contactAid.getCvmLimit() < 0)) { if (!(contactAid.getCvmLimit() < 0)) {
aidV2.setContactlessCvmLimit(contactAid.getCvmLimit()); aidV2.setContactlessCvmLimit(contactAid.getCvmLimit());
@ -464,12 +465,17 @@ public class EmvParamHelper {
aidV2.setAppVerNum(contactAid.getApplicationVersion()); aidV2.setAppVerNum(contactAid.getApplicationVersion());
} }
if (contactAid.getThreshold() != null && !contactAid.getThreshold().isEmpty()) {
aidV2.setThreshold(Long.parseLong(contactAid.getThreshold()));
}
return aidV2; return aidV2;
} }
private CapkEntity convertRidNex(RidEntity ridEntity) { private CapkEntity convertRidNex(RidEntity ridEntity) {
CapkEntity capkV2 = new CapkEntity(); CapkEntity capkV2 = new CapkEntity();
if (ridEntity.getRid() != null && !ridEntity.getRid().isEmpty()) { if (ridEntity.getRid() != null && !ridEntity.getRid().isEmpty()) {
capkV2.setRid(ridEntity.getRid()); capkV2.setRid(ridEntity.getRid());
} }

View File

@ -116,7 +116,7 @@ public class EmvParamOperation extends ParamOperation{
processPayWave(); processPayWave();
processPayPass(); processPayPass();
processQuickPass(); processQuickPass();
processJSpeedy(); // processJSpeedy();
processMPUCtls(); processMPUCtls();
processChips(); processChips();
processRids(); processRids();

View File

@ -3,15 +3,10 @@ package com.utsmyanmar.baselib.network;
import com.utsmyanmar.baselib.network.model.KPayQRQueryRequest; import com.utsmyanmar.baselib.network.model.KPayQRQueryRequest;
import com.utsmyanmar.baselib.network.model.KPayQRRequest; import com.utsmyanmar.baselib.network.model.KPayQRRequest;
import com.utsmyanmar.baselib.network.model.KPayQRResponse; import com.utsmyanmar.baselib.network.model.KPayQRResponse;
import com.utsmyanmar.baselib.network.model.MMQRStatusResponse;
import com.utsmyanmar.baselib.network.model.WaveQRRequest;
import com.utsmyanmar.baselib.network.model.WaveQRResponse;
import com.utsmyanmar.baselib.network.model.WaveStatusRequest;
import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Observable;
import retrofit2.http.Body; import retrofit2.http.Body;
import retrofit2.http.POST; import retrofit2.http.POST;
import retrofit2.http.Url;
public interface KPayApiService { public interface KPayApiService {
@ -23,13 +18,13 @@ public interface KPayApiService {
Observable<KPayQRQueryRequest.QRQueryResponse> checkStatus(@Body KPayQRQueryRequest.QRQueryRequest waveStatusRequest); Observable<KPayQRQueryRequest.QRQueryResponse> checkStatus(@Body KPayQRQueryRequest.QRQueryRequest waveStatusRequest);
//this accept "url" bez this api start with https and other are http in uat //this accepts "url" bez this api start with https and other are http in uat
@POST // @POST
Observable<KPayQRRequest.CloseOrderResponse> closeOrder(@Url String url, @Body KPayQRRequest.CloseOrderRequest closeOrderRequest); // Observable<KPayQRRequest.CloseOrderResponse> closeOrder(@Url String url, @Body KPayQRRequest.CloseOrderRequest closeOrderRequest);
//this 2 is for production //this 2 is for production
// @POST("closeorder") @POST("closeorder")
// Observable<KPayQRRequest.CloseOrderResponse> closeOrder(@Body KPayQRRequest.CloseOrderRequest closeOrderRequest); Observable<KPayQRRequest.CloseOrderResponse> closeOrder(@Body KPayQRRequest.CloseOrderRequest closeOrderRequest);
} }

View File

@ -18,10 +18,19 @@ public class EReceiptCardRequest {
private String DE11; private String DE11;
private String description; private String description;
private String DE38; private String DE38;
private String batchNumber;
private String DE55;
private String DE14;
private String cardLabel;
private String DE43;
private String DE48;
public EReceiptCardRequest() {} public EReceiptCardRequest() {}
// GETTERS // GETTERS
public String getDE14(){ return DE14;}
public String getCardLabel(){ return cardLabel;}
public String getDE43(){return DE43;}
public String getDE3() { public String getDE3() {
return DE3; return DE3;
} }
@ -61,6 +70,8 @@ public class EReceiptCardRequest {
public String getAppId(){ public String getAppId(){
return appId; return appId;
} }
public String getDE55(){return DE55;}
public String getInvoiceNumber(){ public String getInvoiceNumber(){
return invoiceNumber; return invoiceNumber;
@ -75,6 +86,7 @@ public class EReceiptCardRequest {
public String getDE2(){ return DE2; } public String getDE2(){ return DE2; }
public String getDE38(){ return DE38; } public String getDE38(){ return DE38; }
public String getDE22(){ return DE22; } public String getDE22(){ return DE22; }
public String getBatchNumber(){ return batchNumber; }
// SETTERS // SETTERS
public void setDE3(String DE3) { public void setDE3(String DE3) {
this.DE3 = DE3; this.DE3 = DE3;
@ -132,4 +144,23 @@ public class EReceiptCardRequest {
public void setDE38(String DE38){ this.DE38 = DE38; } public void setDE38(String DE38){ this.DE38 = DE38; }
public void setDE22(String DE22){ this.DE22 = DE22; } public void setDE22(String DE22){ this.DE22 = DE22; }
public void setBatchNumber(String batchNumber) {
this.batchNumber = batchNumber;
}
public void setDE55(String DE55){
this.DE55 = DE55;
}
public void setDE14(String DE14){
this.DE14 = DE14;
}
public void setCardLabel(String cardLabel){
this.cardLabel = cardLabel;
}
public void setDE43(String DE43){
this.DE43 = DE43;
}
public void setDE48(String DE48){
this.DE48 = DE48;
}
} }

View File

@ -18,9 +18,23 @@ public class SiriusRequest {
private Long lastTranTime; private Long lastTranTime;
private String value; private String value;
private double latitude;
private double longitude;
public SiriusRequest() {} public SiriusRequest() {}
public SiriusRequest(String serial, String appPackage, String androidVersion, String firmwareVersion, String applicationVersion, String currentNetwork, String lastTransaction, Long lastTranTime, String value) { public SiriusRequest(
String serial,
String appPackage,
String androidVersion,
String firmwareVersion,
String applicationVersion,
String currentNetwork,
String lastTransaction,
Long lastTranTime,
double latitude,
double longitude,
String value
) {
this.serial = serial; this.serial = serial;
this.appPackage = appPackage; this.appPackage = appPackage;
this.androidVersion = androidVersion; this.androidVersion = androidVersion;
@ -29,6 +43,8 @@ public class SiriusRequest {
this.currentNetwork = currentNetwork; this.currentNetwork = currentNetwork;
this.lastTransaction = lastTransaction; this.lastTransaction = lastTransaction;
this.lastTranTime = lastTranTime; this.lastTranTime = lastTranTime;
this.latitude = latitude;
this.longitude = longitude;
this.value = value; this.value = value;
} }
@ -100,6 +116,22 @@ public class SiriusRequest {
return value; return value;
} }
public double getLatitude(){
return latitude;
}
public double getLongitude(){
return longitude;
}
public void setLatitude(double latitude){
this.latitude = latitude;
}
public void setLongitude(double longitude){
this.longitude = longitude;
}
public void setValue(String value) { public void setValue(String value) {
this.value = value; this.value = value;
} }

View File

@ -86,9 +86,9 @@ public class Repository {
} }
public Observable<KPayQRRequest.CloseOrderResponse> qrCloseOrder(KPayQRRequest.CloseOrderRequest request){ public Observable<KPayQRRequest.CloseOrderResponse> qrCloseOrder(KPayQRRequest.CloseOrderRequest request){
String url = "https://api-uat.kbzpay.com/payment/gateway/uat/closeorder"; //close this in prod // String url = "https://api-uat.kbzpay.com/payment/gateway/uat/closeorder"; //close this in prod
return kPayApiService.closeOrder(url, request); // this is for local // return kPayApiService.closeOrder(url, request); // this is for uat
// return kPayApiService.closeOrder(request); //this is for prod return kPayApiService.closeOrder(request); //this is for prod
} }
public Observable<KPayQRQueryRequest.QRQueryResponse> qrStatusCheck(KPayQRQueryRequest.QRQueryRequest request) { public Observable<KPayQRQueryRequest.QRQueryResponse> qrStatusCheck(KPayQRQueryRequest.QRQueryRequest request) {
@ -146,6 +146,8 @@ public class Repository {
public void updatePayDetail(PayDetail payDetail){payDetailDao.update(payDetail);} public void updatePayDetail(PayDetail payDetail){payDetailDao.update(payDetail);}
public LiveData<PayDetail> getReversalTransaction(String voucherNo) { return payDetailDao.getReversalTransaction(voucherNo);} public LiveData<PayDetail> getReversalTransaction(String voucherNo) { return payDetailDao.getReversalTransaction(voucherNo);}
public LiveData<PayDetail> getLastReversalTransaction() { return payDetailDao.getLastReversalTransactionLive();}
public LiveData<List<PayDetail>> getAllReversalTransactions() { return payDetailDao.getAllReversalTransactionsLive();}
public LiveData<List<PayDetail>> getTransactionHistory(){ return payDetailDao.getTransactionHistory();} public LiveData<List<PayDetail>> getTransactionHistory(){ return payDetailDao.getTransactionHistory();}
@ -196,6 +198,10 @@ public class Repository {
return payDetailDao.searchPayDetail(cardNo,referNo); return payDetailDao.searchPayDetail(cardNo,referNo);
} }
public LiveData<PayDetail> searchPayDetailPreCancel(String cardNo,String referNo) {
return payDetailDao.searchPayDetailPreCancel(cardNo,referNo);
}
public Flowable<PayDetail> searchPayDetailByRefNum(String refNum) { public Flowable<PayDetail> searchPayDetailByRefNum(String refNum) {
return payDetailDao.searchPayDetailByRefNum(refNum); return payDetailDao.searchPayDetailByRefNum(refNum);
} }

View File

@ -75,4 +75,13 @@ public class TerminalUtil {
else else
return binParser(SystemParamsOperation.getInstance().getBinValues()); return binParser(SystemParamsOperation.getInstance().getBinValues());
} }
public List<String> getRestrictedBinList() {
if (SystemParamsOperation.getInstance().getRestrictedBinValues() == null
|| SystemParamsOperation.getInstance().getRestrictedBinValues().isEmpty()) {
return new ArrayList<>();
} else {
return binParser(SystemParamsOperation.getInstance().getRestrictedBinValues());
}
}
} }

View File

@ -30,5 +30,7 @@ public enum EmvResultStatus {
CONFIRM_CODE_VERIFY, CONFIRM_CODE_VERIFY,
MPU_CARD, MPU_CARD,
SEE_PHONE, SEE_PHONE,
OTHER_INTERFACE OTHER_INTERFACE,
CARD_APP_BLOCKED,
INSERT_OR_MANUAL
} }

View File

@ -1,12 +1,15 @@
package com.utsmyanmar.baselib.viewModel; package com.utsmyanmar.baselib.viewModel;
import android.app.AlertDialog;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
@ -23,6 +26,7 @@ import com.nexgo.oaf.apiv3.device.pinpad.PinPad;
import com.nexgo.oaf.apiv3.device.pinpad.PinPadKeyCode; import com.nexgo.oaf.apiv3.device.pinpad.PinPadKeyCode;
import com.nexgo.oaf.apiv3.device.pinpad.PinpadLayoutEntity; import com.nexgo.oaf.apiv3.device.pinpad.PinpadLayoutEntity;
import com.nexgo.oaf.apiv3.device.reader.CardInfoEntity; import com.nexgo.oaf.apiv3.device.reader.CardInfoEntity;
import com.nexgo.oaf.apiv3.emv.AidEntity;
import com.nexgo.oaf.apiv3.emv.CandidateAppInfoEntity; import com.nexgo.oaf.apiv3.emv.CandidateAppInfoEntity;
import com.nexgo.oaf.apiv3.emv.EmvCardBrandEnum; import com.nexgo.oaf.apiv3.emv.EmvCardBrandEnum;
import com.nexgo.oaf.apiv3.emv.EmvCvmResultEnum; import com.nexgo.oaf.apiv3.emv.EmvCvmResultEnum;
@ -74,7 +78,7 @@ import java.util.Locale;
import com.utsmyanmar.paylibs.utils.LogUtil; import com.utsmyanmar.paylibs.utils.LogUtil;
public abstract class EmvBaseViewModel extends BaseViewModel { public abstract class EmvBaseViewModel extends BaseViewModel {
private static final String TAG = EmvBaseViewModel.class.getSimpleName(); private static final String TAG = EmvBaseViewModel.class.getSimpleName();
@ -105,6 +109,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
public MutableLiveData<Integer> pinPadVisibility = new MutableLiveData<>(8); public MutableLiveData<Integer> pinPadVisibility = new MutableLiveData<>(8);
protected int pinEnterCount; protected int pinEnterCount;
private int offlinePinIncorrectPromptCount;
public CustomPinPadKeyboard customPinPadKeyboard; public CustomPinPadKeyboard customPinPadKeyboard;
private int mWidth = 239; // Single item width of password keyboard private int mWidth = 239; // Single item width of password keyboard
@ -154,6 +159,10 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
protected static final int EMV_ERROR = 12; protected static final int EMV_ERROR = 12;
protected static final int EMV_TRY_AGAIN = 13; protected static final int EMV_TRY_AGAIN = 13;
protected static final int EMV_INSERT_OR_MANUAL = 24;
protected static final int EMV_CARD_APP_BLOCK = 23;
protected static final int EMV_CTLS_TRY_AGAIN = 13;
protected static final int EMV_CONFIRM_CODE_VERIFY = 14; protected static final int EMV_CONFIRM_CODE_VERIFY = 14;
protected static final int EMV_SUCCESS_ONLINE = 15; protected static final int EMV_SUCCESS_ONLINE = 15;
protected static final int EMV_FAILURE_ONLINE = 16; protected static final int EMV_FAILURE_ONLINE = 16;
@ -170,8 +179,21 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
protected boolean isSecondCall = false; protected boolean isSecondCall = false;
protected int mProcessStep; protected int mProcessStep;
protected int mAppSelect = 0; protected int mAppSelect = 0;
private static final String[] RESTRICTED_BINS = {
"624430",
"624431",
"624445",
"626220",
"623476",
"629214",
"623466",
"623433",
"62911028",
"62441900",
"62441901"
};
private boolean isMPU_UPIContactless = false;
private boolean mMPUContactlessConfigured = false;
private Looper mLooper = Looper.getMainLooper(); private Looper mLooper = Looper.getMainLooper();
private final Handler mHandler = new Handler(mLooper) { private final Handler mHandler = new Handler(mLooper) {
@Override @Override
@ -205,6 +227,9 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
} }
public void startProcess() { public void startProcess() {
isOfflinePinEntered = false;
mMPUContactlessConfigured = false;
isMPU_UPIContactless = false;
initData(); initData();
// Check if initialization was successful // Check if initialization was successful
@ -242,6 +267,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
transData.setTransTime(new SimpleDateFormat("hhmmss", Locale.getDefault()).format(new Date())); transData.setTransTime(new SimpleDateFormat("hhmmss", Locale.getDefault()).format(new Date()));
transData.setTraceNo(mPayDetail.getVoucherNo()); transData.setTraceNo(mPayDetail.getVoucherNo());
transData.setEmvProcessFlowEnum(EmvProcessFlowEnum.EMV_PROCESS_FLOW_STANDARD); transData.setEmvProcessFlowEnum(EmvProcessFlowEnum.EMV_PROCESS_FLOW_STANDARD);
if (mPayDetail.getCardType() == CardTypeX.NFC.value) { if (mPayDetail.getCardType() == CardTypeX.NFC.value) {
transData.setEmvEntryModeEnum(EmvEntryModeEnum.EMV_ENTRY_MODE_CONTACTLESS); transData.setEmvEntryModeEnum(EmvEntryModeEnum.EMV_ENTRY_MODE_CONTACTLESS);
@ -251,21 +277,28 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
//for UPI //for UPI
UnionPayTransDataEntity unionPayTransDataEntity = new UnionPayTransDataEntity(); UnionPayTransDataEntity unionPayTransDataEntity = new UnionPayTransDataEntity();
unionPayTransDataEntity.setQpbocForGlobal(true); unionPayTransDataEntity.setQpbocForGlobal(true);
unionPayTransDataEntity.setSupportCDCVM(true); unionPayTransDataEntity.setSupportCDCVM(true);
//if support QPS, please enable below lines //if support QPS, please enable below lines
unionPayTransDataEntity.setSupportContactlessQps(true); unionPayTransDataEntity.setSupportContactlessQps(true);
unionPayTransDataEntity.setContactlessQpsLimit("000090000000"); unionPayTransDataEntity.setContactlessQpsLimit("000000030000");
transData.setUnionPayTransDataEntity(unionPayTransDataEntity); transData.setUnionPayTransDataEntity(unionPayTransDataEntity);
setTransactionLimitForMPUCtls(false);
// emvHandler.contactlessConfigKernelId(EmvCardBrandEnum.EMV_CARD_BRAND_JCB,(byte) 0x01,ByteUtils.hexString2ByteArray("06"));
emvHandler.contactlessAppendAidIntoKernel(EmvCardBrandEnum.EMV_CARD_BRAND_MASTER, (byte) 0x08, ByteUtils.hexString2ByteArray("A000000732100123")); emvHandler.contactlessConfigKernelId(EmvCardBrandEnum.EMV_CARD_BRAND_JCB,(byte) 0x01,ByteUtils.hexString2ByteArray("06"));
emvHandler.contactlessAppendAidIntoKernel(EmvCardBrandEnum.EMV_CARD_BRAND_MASTER, (byte) 0x07, ByteUtils.hexString2ByteArray("A0000008890101"));
// emvHandler.contactlessAppendAidIntoKernelFirst(true);
LogUtil.d(TAG, "TransData :" + transData.getTransAmount()); LogUtil.d(TAG, "TransData :" + transData.getTransAmount());
LogUtil.d(TAG, "start emv "); LogUtil.d(TAG, "start emv ");
// emvHandler.emvDebugLog(true);
emvHandler.emvProcess(transData, emvProcessListener); emvHandler.emvProcess(transData, emvProcessListener);
@ -273,7 +306,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
private void initData() { private void initData() {
try { try {
emvHandler = BaseApplication.getInstance().deviceEngine.getEmvHandler2("app2"); emvHandler = BaseApplication.getInstance().deviceEngine.getEmvHandler2("app2");
if (emvHandler == null) { if (emvHandler == null) {
LogUtil.e(TAG, "Failed to initialize EMV handler - emvHandler is null"); LogUtil.e(TAG, "Failed to initialize EMV handler - emvHandler is null");
// Post error status to inform UI // Post error status to inform UI
@ -305,8 +338,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
return; return;
} }
try { try {
LogUtil.d(TAG, "Selected :" + position); LogUtil.d(TAG, "Selected :" + position + 1);
emvHandler.onSetSelAppResponse(position); emvHandler.onSetSelAppResponse(position + 1);
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Exception during app selection: " + e.getMessage()); LogUtil.e(TAG, "Exception during app selection: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
@ -315,76 +348,6 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
} }
} }
private void initPayPassTlv() {
emvParamOperation.retrievePayPassData(new ProcessSingleDataResult<PayPassEntity>() {
@Override
public void onSuccess(PayPassEntity data) {
String DF8117Value = "E0";
String DF8118Value = "F8";
String DF8119Value = "28";
if (!data.getTerminalCapability().isEmpty()) {
DF8117Value = data.getTerminalCapability().substring(0, 2);
DF8118Value = data.getTerminalCapability().substring(2, 4);
DF8119Value = data.getTerminalCapability().substring(4, 6);
}
String DF8123Value = data.getFloorLimit();
String DF8124Value = data.getTransLimitCDV();
String DF8125Value = data.getTransLimit();
String DF8126Value = ParamHelper.getInstance().convertPaddedString(data.getCvmLimit());
String DF8120Value = data.getTacDefault();
String DF8121Value = data.getTacDenial();
String DF8122Value = data.getTacOnline();
String[] tagsPayPass = {"DF8117", "DF8118", "DF8119", "DF811F", "DF811E", "DF812C",
"DF8123", "DF8124", "DF8125", "DF8126",
"DF811B", "DF811D", "DF8120", "DF8121", "DF8122"};
String[] valuesPayPass = {DF8117Value, DF8118Value, DF8119Value, "C8", "00", "00",
DF8123Value, DF8124Value, DF8125Value, DF8126Value,
"30", "02", DF8120Value, DF8121Value, DF8122Value};
// try {
// mEMVOptV2.setTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYPASS, tagsPayPass, valuesPayPass);
//
// LogUtil.d(TAG,"<<<<< PayPass TLV data are successfully setup >>>>>");
// } catch (RemoteException e) {
// throw new RuntimeException(e);
// }
}
@Override
public void onDataNotFound() {
LogUtil.d(TAG, "PayPass Data not found!");
}
});
}
protected void increasedKSN() {
pinPad.dukptKsnIncrease(pinIndex); //3
LogUtil.d(TAG,"DUKPT KSN Increased!");
}
private void getKSN() {
try {
byte[] result = pinPad.dukptCurrentKsn(pinIndex);
if (result != null) {
String ksnStr = ByteUtil.bytes2HexStr(result);
LogUtil.d(TAG, "ksnStr: " + ksnStr);
mPayDetail.setReference(ksnStr);
mPayDetail.tempKSN = ksnStr;
LogUtil.d(TAG, "final ksnStr: " + ksnStr);
} else {
LogUtil.e(TAG, "Result code for current KSN:" + result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private String getTransactionType() { private String getTransactionType() {
String trnxType = "00"; String trnxType = "00";
@ -422,219 +385,168 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
initKeyboard(isOnlinePin == 1); initKeyboard(isOnlinePin == 1);
} }
private void initKeyboard(boolean isOnlinePin) { private void initKeyboard(boolean isOnlinePin) {
LogUtil.d(TAG, "init keyboard!");
LogUtil.d(TAG,"init keyboard!");
pinPadVisibility.setValue(0); pinPadVisibility.setValue(0);
LogUtil.d(TAG,"pin pad is visible now!"); LogUtil.d(TAG, "pin pad is visible now!");
customPinPadKeyboard.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
customPinPadKeyboard.getViewTreeObserver().removeOnGlobalLayoutListener(this);
LogUtil.d(TAG,"inside the global layout!"); // Check if the view is already laid out
PinpadLayoutEntity pinpadLayout = new PinpadLayoutEntity(); if (customPinPadKeyboard.getWidth() > 0 && customPinPadKeyboard.getHeight() > 0) {
int[] location = new int[2]; // View already laid out — call setup directly
Rect r; setupPinPadLayout(isOnlinePin);
customPinPadKeyboard.getKey_1().getLocationOnScreen(location); } else {
r = new Rect(); // View not yet laid out — wait for layout
r.left = location[0]; customPinPadKeyboard.getViewTreeObserver().addOnGlobalLayoutListener(
r.top = location[1]; new ViewTreeObserver.OnGlobalLayoutListener() {
r.right = customPinPadKeyboard.getKey_1().getWidth() + r.left; @Override
r.bottom = customPinPadKeyboard.getKey_1().getHeight() + r.top; public void onGlobalLayout() {
pinpadLayout.setKey1(r); if (customPinPadKeyboard.getWidth() > 0 && customPinPadKeyboard.getHeight() > 0) {
customPinPadKeyboard.getViewTreeObserver().removeOnGlobalLayoutListener(this);
customPinPadKeyboard.getKey_2().getLocationOnScreen(location); setupPinPadLayout(isOnlinePin);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_2().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_2().getHeight() + r.top;
pinpadLayout.setKey2(r);
customPinPadKeyboard.getKey_3().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_3().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_3().getHeight() + r.top;
pinpadLayout.setKey3(r);
customPinPadKeyboard.getKey_4().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_4().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_4().getHeight() + r.top;
pinpadLayout.setKey4(r);
customPinPadKeyboard.getKey_5().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_5().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_5().getHeight() + r.top;
pinpadLayout.setKey5(r);
customPinPadKeyboard.getKey_6().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_6().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_6().getHeight() + r.top;
pinpadLayout.setKey6(r);
customPinPadKeyboard.getKey_7().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_7().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_7().getHeight() + r.top;
pinpadLayout.setKey7(r);
customPinPadKeyboard.getKey_8().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_8().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_8().getHeight() + r.top;
pinpadLayout.setKey8(r);
customPinPadKeyboard.getKey_9().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_9().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_9().getHeight() + r.top;
pinpadLayout.setKey9(r);
customPinPadKeyboard.getKey_0().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_0().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_0().getHeight() + r.top;
pinpadLayout.setKey10(r);
customPinPadKeyboard.getKey_cancel().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_cancel().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_cancel().getHeight() + r.top;
pinpadLayout.setKeyCancel(r);
customPinPadKeyboard.getKey_clear().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_clear().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_clear().getHeight() + r.top;
pinpadLayout.setKeyClear(r);
customPinPadKeyboard.getKey_ok().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_ok().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_ok().getHeight() + r.top;
pinpadLayout.setKeyConfirm(r);
byte[] number = pinPad.setPinpadLayout(pinpadLayout);
OnPinPadInputListener pinPadInputListener = new OnPinPadInputListener() {
@Override
public void onInputResult(final int retCode, final byte[] data) {
if (retCode == SdkResult.Success) {
LogUtil.d(TAG, "Success");
if(isOnlinePin) {
mPayDetail.setPINCipher(ByteUtil.bytes2HexStr(data));
}
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else if (retCode == SdkResult.Fail) {
LogUtil.d(TAG, "Failure");
} else if (retCode == SdkResult.PinPad_Input_Cancel) {
LogUtil.d(TAG, "Cancel");
mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
} else if (retCode == SdkResult.PinPad_Input_Timeout) {
mHandler.obtainMessage(PIN_TIME_OUT,-7009).sendToTarget();
} else if (retCode == SdkResult.PinPad_No_Pin_Input) {
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else {
mHandler.obtainMessage(PIN_ERROR).sendToTarget();
}
LogUtil.d(TAG, "RetCode:" + retCode);
LogUtil.d(TAG, "data bytes:" + ByteUtil.bytes2HexStr(data));
}
@Override
public void onSendKey(byte keyCode) {
increaseCount();
if (keyCode == PinPadKeyCode.KEYCODE_CLEAR) {
LogUtil.d(TAG, "on clear");
mHandler.obtainMessage(PIN_CLICK_CLEAR).sendToTarget();
} else if (keyCode == PinPadKeyCode.KEYCODE_CANCEL) {
LogUtil.d(TAG, "on click cancel");
mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
} else if (keyCode == PinPadKeyCode.KEYCODE_CONFIRM) {
LogUtil.d(TAG, "on click confirm");
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else {
LogUtil.d(TAG, "on click number");
mHandler.obtainMessage(PIN_CLICK_NUMBER, pinEnterCount, 0).sendToTarget();
}
LogUtil.d(TAG, "SendKey: " + ByteUtil.byte2HexStr(keyCode));
}
};
if (number != null) {
customPinPadKeyboard.setKeyBoard(number);
// customPinPadKeyboard.setKeyBoard(ByteUtil.bytes2HexStr(number));
LogUtil.d(TAG, "PinPad: " + ByteUtil.bytes2HexStr(number));
int[] supperLen = new int[]{0x00, 0x04, 0x06};
pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT);
pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED);
// pinPad.setAlgorithmMode(AlgorithmModeEnum.DES);
if(cardNo == null){
cardNo = emvHandler.getEmvCardDataInfo().getCardNo();
}
int length = cardNo.length();
byte[] panBytes = cardNo.substring( length- 13).getBytes(StandardCharsets.US_ASCII);
LogUtil.d(TAG,"card num :"+cardNo);
LogUtil.d(TAG,"Is Online Pin:"+isOnlinePin);
// pinPad.inputOnlinePin(supperLen, 60, pan, 0, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener);
if (isOnlinePin) {
pinPad.inputOnlinePin(supperLen, 60, panBytes, pinIndex, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener);
} else {
mPayDetail.transCVM = TransCVM.OFFLINE_PIN;
pinPad.inputOfflinePin(supperLen, 60, pinPadInputListener);
} }
} }
} }
);
}
}
private void setupPinPadLayout(boolean isOnlinePin) {
LogUtil.d(TAG, "inside the global layout!");
PinpadLayoutEntity pinpadLayout = new PinpadLayoutEntity();
// Helper to avoid repetition
pinpadLayout.setKey1(getRectForView(customPinPadKeyboard.getKey_1()));
pinpadLayout.setKey2(getRectForView(customPinPadKeyboard.getKey_2()));
pinpadLayout.setKey3(getRectForView(customPinPadKeyboard.getKey_3()));
pinpadLayout.setKey4(getRectForView(customPinPadKeyboard.getKey_4()));
pinpadLayout.setKey5(getRectForView(customPinPadKeyboard.getKey_5()));
pinpadLayout.setKey6(getRectForView(customPinPadKeyboard.getKey_6()));
pinpadLayout.setKey7(getRectForView(customPinPadKeyboard.getKey_7()));
pinpadLayout.setKey8(getRectForView(customPinPadKeyboard.getKey_8()));
pinpadLayout.setKey9(getRectForView(customPinPadKeyboard.getKey_9()));
pinpadLayout.setKey10(getRectForView(customPinPadKeyboard.getKey_0()));
pinpadLayout.setKeyCancel(getRectForView(customPinPadKeyboard.getKey_cancel()));
pinpadLayout.setKeyClear(getRectForView(customPinPadKeyboard.getKey_clear()));
pinpadLayout.setKeyConfirm(getRectForView(customPinPadKeyboard.getKey_ok()));
byte[] number = pinPad.setPinpadLayout(pinpadLayout);
OnPinPadInputListener pinPadInputListener = new OnPinPadInputListener() {
@Override
public void onInputResult(final int retCode, final byte[] data) {
if (retCode == SdkResult.Success) {
LogUtil.d(TAG, "Success");
if(isOnlinePin) {
if(ByteUtil.bytes2HexStr(data).equals("0000000000000000")) {
mPayDetail.setPINCipher("");
} else {
mPayDetail.setPINCipher(ByteUtil.bytes2HexStr(data));
}
// mPayDetail.setPINCipher(ByteUtil.bytes2HexStr(data));
} else {
isOfflinePinEntered = true;
}
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else if (retCode == SdkResult.Fail) {
LogUtil.d(TAG, "Failure");
} else if (retCode == SdkResult.PinPad_Input_Cancel) {
LogUtil.d(TAG, "Cancel");
mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
} else if (retCode == SdkResult.PinPad_Input_Timeout) {
mHandler.obtainMessage(PIN_TIME_OUT,-7009).sendToTarget();
} else if (retCode == SdkResult.PinPad_No_Pin_Input) {
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else {
mHandler.obtainMessage(PIN_ERROR).sendToTarget();
} }
);
LogUtil.d(TAG, "RetCode:" + retCode);
LogUtil.d(TAG, "data bytes:" + ByteUtil.bytes2HexStr(data));
}
@Override
public void onSendKey(byte keyCode) {
increaseCount();
if (keyCode == PinPadKeyCode.KEYCODE_CLEAR) {
LogUtil.d(TAG, "on clear");
mHandler.obtainMessage(PIN_CLICK_CLEAR).sendToTarget();
} else if (keyCode == PinPadKeyCode.KEYCODE_CANCEL) {
LogUtil.d(TAG, "on click cancel");
mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
} else if (keyCode == PinPadKeyCode.KEYCODE_CONFIRM) {
// Wait for onInputResult() so the PIN cipher / offline PIN state is ready
// before EmvTransactionProcessViewModel handles PIN confirmation.
LogUtil.d(TAG, "on click confirm - waiting for input result");
} else {
LogUtil.d(TAG, "on click number");
mHandler.obtainMessage(PIN_CLICK_NUMBER, pinEnterCount, 0).sendToTarget();
}
LogUtil.d(TAG, "SendKey: " + ByteUtil.byte2HexStr(keyCode));
}
};
if (number != null) {
customPinPadKeyboard.setKeyBoard(number);
// customPinPadKeyboard.setKeyBoard(ByteUtil.bytes2HexStr(number));
LogUtil.d(TAG, "PinPad: " + ByteUtil.bytes2HexStr(number));
int[] supperLen = new int[]{0x00, 0x04, 0x06, 0x0c};
pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT);
pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED);
// pinPad.setAlgorithmMode(AlgorithmModeEnum.DES);
if(cardNo == null){
cardNo = emvHandler.getEmvCardDataInfo().getCardNo();
}
int length = cardNo.length();
byte[] panBytes = cardNo.substring( length- 13).getBytes(StandardCharsets.US_ASCII);
LogUtil.d(TAG,"card num :"+cardNo);
LogUtil.d(TAG,"Is Online Pin:"+isOnlinePin);
// pinPad.inputOnlinePin(supperLen, 60, pan, 0, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener);
if (isOnlinePin) {
pinPad.inputOnlinePin(supperLen, 60, panBytes, pinIndex, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener);
} else {
mPayDetail.transCVM = TransCVM.OFFLINE_PIN;
pinPad.inputOfflinePin(supperLen, 60, pinPadInputListener);
}
}
}
// Reusable rect helper
private Rect getRectForView(View view) {
int[] location = new int[2];
view.getLocationOnScreen(location);
Rect r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = view.getWidth() + r.left;
r.bottom = view.getHeight() + r.top;
return r;
} }
private void increaseCount() { private void increaseCount() {
++pinEnterCount; ++pinEnterCount;
} }
private boolean isRestrictedBin(String cardNo) {
if (cardNo == null || cardNo.isEmpty()) return false;
List<String> restrictedBins = TerminalUtil.getInstance().getRestrictedBinList();
for (String bin : restrictedBins) {
if (cardNo.startsWith(bin)) {
LogUtil.d(TAG, "isRestrictedBin: matched BIN " + bin);
return true;
}
}
return false;
}
private OnEmvProcessListener2 emvProcessListener = new OnEmvProcessListener2() { private OnEmvProcessListener2 emvProcessListener = new OnEmvProcessListener2() {
@Override @Override
@ -648,40 +560,116 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
@Override @Override
public void onTransInitBeforeGPO() { public void onTransInitBeforeGPO() {
if (mMPUContactlessConfigured) {
LogUtil.d(TAG, "onTransInitBeforeGPO: skipping — MPU contactless already configured");
emvHandler.onSetTransInitBeforeGPOResponse(true);
return;
}
byte[] aid = emvHandler.getTlv(new byte[]{0x4F}, EmvDataSourceEnum.FROM_KERNEL); byte[] aid = emvHandler.getTlv(new byte[]{0x4F}, EmvDataSourceEnum.FROM_KERNEL);
LogUtil.d(TAG, "onTransInitBeforeGPO :"); LogUtil.d(TAG, "onTransInitBeforeGPO :"+ByteUtil.bytes2HexStr(aid));
String terminalCapability = SystemParamsOperation.getInstance().getTerminalCapability();
// emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, new byte[]{(byte) 0xE0, (byte) 0x28, (byte) 0xC8}); String visaTerminalCapability = SystemParamsOperation.getInstance().getVisaTerminalCapability();
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, ByteUtil.hexStr2Bytes(terminalCapability)); String masterTerminalCapability = SystemParamsOperation.getInstance().getMasterTerminalCapability();
String upiTerminalCapability = SystemParamsOperation.getInstance().getUpiTerminalCapability();
String jcbTerminalCapability = SystemParamsOperation.getInstance().getJcbTerminalCapability();
String selectedTerminalCapability = "";
if (aid != null) {
String aidStr = ByteUtils.byteArray2HexString(aid).toUpperCase();
if (aidStr.contains("A000000003")) {
// VISA
selectedTerminalCapability = visaTerminalCapability;
} else if (aidStr.contains("A000000004")) {
// MasterCard
selectedTerminalCapability = masterTerminalCapability;
} else if (aidStr.contains("A000000333") || aidStr.contains("A000000025")) {
// UPI
selectedTerminalCapability = upiTerminalCapability;
} else if (aidStr.contains("A00000006510") || aidStr.contains("A0000001570040")) {
// UPI (maybe JCB)
selectedTerminalCapability = jcbTerminalCapability;
} else if (aidStr.contains("A000000065")){
selectedTerminalCapability = jcbTerminalCapability;
}
}
//9F33
emvHandler.setTlv(
new byte[]{(byte) 0x9F, (byte) 0x33},
ByteUtil.hexStr2Bytes(selectedTerminalCapability)
);
// -------- Contactless --------
if (mPayDetail.getCardType() == CardTypeX.NFC.value) { if (mPayDetail.getCardType() == CardTypeX.NFC.value) {
if (aid != null) { if (aid != null) {
if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000004")) { String aidStr = ByteUtils.byteArray2HexString(aid).toUpperCase();
//Paypass
configPaypassParameter(aid);
} else if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000003")) {
//Paywave
configPaywaveParameters();
} else if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000025")) {
//ExpressPay
// configExpressPayParameter();
} else if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000541")) {
configPureContactlessParameter();
} else if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000065")) {
configJcbContactlessParameter();
}
}
} else {
//contact terminal capability ; if different card brand(depend on aid) have different terminal capability
if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000004")) {
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, new byte[]{(byte) 0xE0, (byte) 0x28, (byte) 0xC8});
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x1D}, ByteUtils.hexString2ByteArray("6C00800000000000"));//terminal risk
if (aidStr.contains("A000000004")) {
configPaypassParameter(aid);
} else if (aidStr.contains("A000000003")) {
configPaywaveParameters();
} else if (aidStr.contains("A000000333")) {
// configureQuickPassParamerter();
} else if (aidStr.contains("A000000541")) {
configPureContactlessParameter();
} else if (aidStr.contains("A000000065")) {
configJcbContactlessParameter();
} else if (aidStr.contains("A000000889")) {
configMPUContactlessParameter();
mMPUContactlessConfigured = true;
}
} }
} }
emvHandler.onSetTransInitBeforeGPOResponse(true); emvHandler.onSetTransInitBeforeGPOResponse(true);
} }
// @Override
// public void onTransInitBeforeGPO() {
// byte[] aid = emvHandler.getTlv(new byte[]{0x4F}, EmvDataSourceEnum.FROM_KERNEL);
// LogUtil.d(TAG, "onTransInitBeforeGPO :");
//// String terminalCapability = SystemParamsOperation.getInstance().getTerminalCapability();
// String visaTerminalCapability = SystemParamsOperation.getInstance().getVisaTerminalCapability();
// String masterTerminalCapability = SystemParamsOperation.getInstance().getMasterTerminalCapability();
// String upiTerminalCapability = SystemParamsOperation.getInstance().getUpiTerminalCapability();
//// LogUtil.d(TAG,"Terminal capability :"+terminalCapability);
//// emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, new byte[]{(byte) 0xE0, (byte) 0x28, (byte) 0xC8});
// emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, ByteUtil.hexStr2Bytes(terminalCapability));
// if (mPayDetail.getCardType() == CardTypeX.NFC.value) {
// if (aid != null) {
// if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000004")) {
// //Paypass
// configPaypassParameter(aid);
// } else if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000003")) {
// //Paywave
// configPaywaveParameters();
// } else if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000025")) {
// //ExpressPay
//// configExpressPayParameter();
// } else if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000541")) {
// configPureContactlessParameter();
// } else if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000065")) {
// configJcbContactlessParameter();
// }
// }
// } else {
// //contact terminal capability ; if different card brand(depend on aid) have different terminal capability
//// if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000004")) {
//// emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, ByteUtil.hexStr2Bytes(terminalCapability));
//// emvHandler.setTlv(new byte[]{(byte) 0xE0, (byte) 0x1D}, ByteUtils.hexString2ByteArray("6C00800000000000"));//terminal risk
////
//// }
// }
//
// emvHandler.onSetTransInitBeforeGPOResponse(true);
// }
@Override @Override
public void onConfirmCardNo(CardInfoEntity cardInfoEntity) { public void onConfirmCardNo(CardInfoEntity cardInfoEntity) {
LogUtil.d(TAG, "onConfirmCardNo"); LogUtil.d(TAG, "onConfirmCardNo");
@ -690,6 +678,17 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
cardNo = cardInfoEntity.getCardNo(); cardNo = cardInfoEntity.getCardNo();
if (mPayDetail.getCardType() == CardTypeX.NFC.value) {
if (isRestrictedBin(cardNo)) {
isMPU_UPIContactless = true;
LogUtil.d(TAG, "onConfirmCardNo: restricted BIN detected — " + cardNo);
emvHandler.onSetConfirmCardNoResponse(false);
emvHandler.emvProcessCancel();
}
}
if (mPayDetail.getCardType() == CardTypeX.NFC.value) { if (mPayDetail.getCardType() == CardTypeX.NFC.value) {
cardNum.postValue(cardInfoEntity.getCardNo()); cardNum.postValue(cardInfoEntity.getCardNo());
mPayDetail.setCardNo(cardInfoEntity.getCardNo()); mPayDetail.setCardNo(cardInfoEntity.getCardNo());
@ -701,6 +700,9 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
public void onCardHolderInputPin(boolean isOnlinePin, int leftTimes) { public void onCardHolderInputPin(boolean isOnlinePin, int leftTimes) {
LogUtil.d(TAG, "onCardHolderInputPin isOnlinePin = " + isOnlinePin); LogUtil.d(TAG, "onCardHolderInputPin isOnlinePin = " + isOnlinePin);
LogUtil.d(TAG, "onCardHolderInputPin leftTimes = " + leftTimes); LogUtil.d(TAG, "onCardHolderInputPin leftTimes = " + leftTimes);
if (isOnlinePin) {
pinRemainingCount.postValue("");
}
// startPinProcess(isOnlinePin ? 1 : 0); // startPinProcess(isOnlinePin ? 1 : 0);
mProcessStep = EMV_SHOW_PIN_PAD; mProcessStep = EMV_SHOW_PIN_PAD;
// mHandler.obtainMessage(EMV_SHOW_PIN_PAD, isOnlinePin ? 1 : 0).sendToTarget(); // mHandler.obtainMessage(EMV_SHOW_PIN_PAD, isOnlinePin ? 1 : 0).sendToTarget();
@ -739,7 +741,17 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
@Override @Override
public void onPrompt(PromptEnum promptEnum) { public void onPrompt(PromptEnum promptEnum) {
LogUtil.d(TAG, "onPrompt->" + promptEnum); LogUtil.d(TAG, "onPrompt->" + promptEnum);
emvHandler.onSetPromptResponse(true); if( promptEnum == PromptEnum.OFFLINE_PIN_INCORRECT_TRY_AGAIN) {
offlinePinIncorrectPromptCount++;
pinEnterCount = 0;
pinText.postValue("");
int attemptLeft = Math.max(0, 3 - offlinePinIncorrectPromptCount);
pinRemainingCount.postValue("Please try again!\n" + attemptLeft + " attempt left!");
emvHandler.onSetPromptResponse(false);
} else {
emvHandler.onSetPromptResponse(true);
}
} }
@Override @Override
@ -797,6 +809,9 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
byte[] tlv_50 = emvHandler.getTlv(new byte[]{(byte) 0x50}, EmvDataSourceEnum.FROM_KERNEL); byte[] tlv_50 = emvHandler.getTlv(new byte[]{(byte) 0x50}, EmvDataSourceEnum.FROM_KERNEL);
LogUtil.d(TAG, "tlv_50--" + ByteUtils.byteArray2HexString(tlv_50)); LogUtil.d(TAG, "tlv_50--" + ByteUtils.byteArray2HexString(tlv_50));
byte[] tlv_9B = emvHandler.getTlv(new byte[]{(byte) 0x9B}, EmvDataSourceEnum.FROM_KERNEL);
LogUtil.d(TAG, "tlv_9B--" + ByteUtils.byteArray2HexString(tlv_9B));
switch (retCode) { switch (retCode) {
case SdkResult.Emv_Success_Arpc_Fail: case SdkResult.Emv_Success_Arpc_Fail:
case SdkResult.Success: case SdkResult.Success:
@ -824,20 +839,38 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
//union pay online contactless--application should go online //union pay online contactless--application should go online
break; break;
case SdkResult.Emv_App_Block:
case SdkResult.Emv_Card_Block:
mHandler.sendEmptyMessage(EMV_CARD_APP_BLOCK);
break;
case SdkResult.Emv_Candidatelist_Empty:// Application have no aid list case SdkResult.Emv_Candidatelist_Empty:// Application have no aid list
case SdkResult.Emv_FallBack:// FallBack ,chip card reset failed case SdkResult.Emv_FallBack:// FallBack ,chip card reset failed
//fallback process //fallback process
emvResultStatus.postValue(EmvResultStatus.READ_CARD_RETRY); if(mMPUContactlessConfigured) {
mHandler.sendEmptyMessage(EMV_INSERT_OR_MANUAL);
} else {
mHandler.sendEmptyMessage(EMV_TRY_AGAIN);
}
break; break;
case SdkResult.Emv_Declined: case SdkResult.Emv_Declined:
case SdkResult.Emv_Arpc_Fail: // case SdkResult.Emv_Arpc_Fail: //
offlineDenial();
// mHandler.obtainMessage(EMV_ERROR, retCode, retCode, "Emv Declined!").sendToTarget();
//// case SdkResult.Emv_Declined: //// case SdkResult.Emv_Declined:
// //online decline ,if it is in second gac, application should decide if it is need reversal the transaction // //online decline ,if it is in second gac, application should decide if it is need reversal the transaction
break; break;
// //
case SdkResult.Emv_Cancel:// Transaction Cancel case SdkResult.Emv_Cancel:// Transaction Cancel
// //user cancel // //user cancel
mHandler.obtainMessage(EMV_ERROR, retCode, retCode, "Canceled").sendToTarget(); if(isMPU_UPIContactless) {
mHandler.sendEmptyMessage(EMV_INSERT_OR_MANUAL);
} else {
mHandler.obtainMessage(EMV_ERROR, retCode, retCode, "Canceled").sendToTarget();
}
break; break;
// //
// case SdkResult.Emv_Offline_Declined: // // case SdkResult.Emv_Offline_Declined: //
@ -955,6 +988,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
emvCardType.postValue(""); emvCardType.postValue("");
pinText.setValue(""); pinText.setValue("");
pinEnterCount = 0; pinEnterCount = 0;
offlinePinIncorrectPromptCount = 0;
} }
protected void getCardInfo() { protected void getCardInfo() {
@ -1210,11 +1244,11 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x1B}, new byte[]{(byte) 0x30}); emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x1B}, new byte[]{(byte) 0x30});
//EMV MODE :amount >contactless cvm limit, set 60 = online pin and signature , set 20 = signature //EMV MODE :amount >contactless cvm limit, set 60 = online pin and signature , set 20 = signature
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x18}, new byte[]{(byte) 0x28}); emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x18}, new byte[]{(byte) 0xF0}); //F8 //F0
//EMV mode :amount < contactless cvm limit, set 08 = no cvm //EMV mode :amount < contactless cvm limit, set 08 = no cvm
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x19}, new byte[]{(byte) 0x08}); //08 emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x19}, new byte[]{(byte) 0x08}); //08
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x25}, ByteUtils.hexString2ByteArray("000999999999")); emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x25}, ByteUtils.hexString2ByteArray("999999999999"));
if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A0000000043060")) { if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A0000000043060")) {
Log.d("nexgo", "======maestro===== "); Log.d("nexgo", "======maestro===== ");
@ -1231,6 +1265,75 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
} }
}
private void configMPUContactlessParameter() {
LogUtil.d(TAG,"MPU Contactless Parameter configurations....");
//kernel configuration, enable RRP and cdcvm
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x1B}, new byte[]{(byte) 0x30});
//EMV MODE :amount >contactless cvm limit, set 60 = online pin and signature , set 20 = signature
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x18}, new byte[]{(byte) 0xF0}); //F8
//EMV mode :amount < contactless cvm limit, set 08 = no cvm
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x19}, new byte[]{(byte) 0x28}); //08
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x24}, ByteUtils.hexString2ByteArray("000010000000"));
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x25}, ByteUtils.hexString2ByteArray("000010000000"));
emvHandler.setTlv(new byte[]{(byte) 0xDF, (byte) 0x81, (byte) 0x26}, ByteUtils.hexString2ByteArray("000010000000"));
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x1d}, ByteUtils.hexString2ByteArray("6C00800000000000"));
setTransactionLimitForMPUCtls(true);
byte[] getTLVofDF8124 = emvHandler.getTlv(ByteUtil.hexStr2Bytes("DF8124"),EmvDataSourceEnum.FROM_KERNEL);
LogUtil.d(TAG,"DF8124: "+ByteUtil.bytes2HexStr(getTLVofDF8124));
}
private void setTransactionLimitForMPUCtls(boolean flag){
if(emvHandler.getAidList() != null) {
for (AidEntity aidEntity:emvHandler.getAidList()
) {
if(aidEntity.getAid() != null) {
if(aidEntity.getAid().equals("A00000000410") || aidEntity.getAid().equals("A0000000041010")){
if(flag) {
aidEntity.setTransLimit(Long.parseLong("000010000000"));
aidEntity.setContactlessTransLimit(Long.parseLong("000010000000"));
} else {
aidEntity.setTransLimit(Long.parseLong("999999999999"));
aidEntity.setContactlessTransLimit(Long.parseLong("999999999999"));
}
emvHandler.delOneAid(ByteUtil.hexStr2Bytes(aidEntity.getAid()));
emvHandler.setAidParaList(List.of(aidEntity));
LogUtil.d(TAG,"added AID+"+aidEntity.getAid());
}
}
}
for (AidEntity aidEntity1:emvHandler.getAidList()
) {
if (aidEntity1.getAid() != null) {
if (aidEntity1.getAid().equals("A00000000410") || aidEntity1.getAid().equals("A0000000041010")) {
LogUtil.d(TAG, " AID+" + aidEntity1.getAid());
LogUtil.d(TAG, " transactionLimit+" + aidEntity1.getContactlessTransLimit());
LogUtil.d(TAG, " transactionLimit+" + aidEntity1.getTransLimit());
}
}
}
}
} }
private void configPaywaveParameters() { private void configPaywaveParameters() {
@ -1239,13 +1342,12 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
LogUtil.d(TAG, "configPaywaveParameters, TTQ" + ByteUtils.byteArray2HexString(kernelTTQ)); LogUtil.d(TAG, "configPaywaveParameters, TTQ" + ByteUtils.byteArray2HexString(kernelTTQ));
//default TTQ value //default TTQ value
TTQ = ByteUtils.hexString2ByteArray("36A04000"); TTQ = ByteUtils.hexString2ByteArray("32A04000"); // 36A04000
kernelTTQ[0] = TTQ[0]; kernelTTQ[0] = TTQ[0];
kernelTTQ[1] = TTQ[1]; kernelTTQ[1] = TTQ[1];
kernelTTQ[2] = TTQ[2]; kernelTTQ[2] = TTQ[2];
kernelTTQ[3] = TTQ[3]; kernelTTQ[3] = TTQ[3];
// FIXME: 2019/3/20
//If there is no special requirements, do not change TTQ byte1 //If there is no special requirements, do not change TTQ byte1
//if online force required , can set byte2 bit 8 = 1 //if online force required , can set byte2 bit 8 = 1
emvHandler.setTlv(ByteUtils.hexString2ByteArray("9F66"), kernelTTQ); emvHandler.setTlv(ByteUtils.hexString2ByteArray("9F66"), kernelTTQ);
@ -1278,6 +1380,11 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
} }
private void configPureQuickPassParameter() {
LogUtil.d(TAG, "configQuickPassParameter");
}
private void configJcbContactlessParameter() { private void configJcbContactlessParameter() {
LogUtil.d(TAG, "configJcbContactlessParameter"); LogUtil.d(TAG, "configJcbContactlessParameter");

View File

@ -1,9 +1,10 @@
[ [
{ {
"aidEnable": true, "aidEnable": true,
"aid": "A0000000031010", "aid": "A0000000031010",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -26,7 +27,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A0000000032010", "aid": "A0000000032010",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -49,7 +50,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A000000003101001", "aid": "A000000003101001",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -72,7 +73,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A000000003101002", "aid": "A000000003101002",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -95,7 +96,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A000000003101003", "aid": "A000000003101003",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -118,7 +119,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A000000003101004", "aid": "A000000003101004",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -141,7 +142,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A000000003101005", "aid": "A000000003101005",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -164,7 +165,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A0000000033010", "aid": "A0000000033010",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -187,7 +188,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A0000000038010", "aid": "A0000000038010",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -210,7 +211,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A000000003101008", "aid": "A000000003101008",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -233,7 +234,7 @@
"aidEnable": true, "aidEnable": true,
"aid": "A000000003101009", "aid": "A000000003101009",
"cardScheme": "VISA", "cardScheme": "VISA",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -529,33 +530,10 @@
"currencyCode": "0104" "currencyCode": "0104"
}, },
{ {
"aidEnable": true, "aidEnable": false,
"aid": "A0000000651010",
"cardScheme": "JCB",
"applicationVersion": "0020",
"emvDDOL": "9F3704",
"emvTDOL": "9F3704",
"partialAidSelection": false,
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000000",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 75000,
"transLimit": "999999999999",
"transLimitCDV": "999999999999",
"terminalCapability": "0000000000000000",
"riskManageData": "01",
"cateCode": "2701",
"currencyCode": "0104"
},
{
"aidEnable": true,
"aid": "A00000006510", "aid": "A00000006510",
"cardScheme": "JCB", "cardScheme": "JCB",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -575,10 +553,33 @@
"currencyCode": "0104" "currencyCode": "0104"
}, },
{ {
"aidEnable": true, "aidEnable": false,
"aid": "A0000000651010",
"cardScheme": "JCB",
"applicationVersion": "0030",
"emvDDOL": "9F3704",
"emvTDOL": "9F3704",
"partialAidSelection": false,
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000000",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 75000,
"transLimit": "999999999999",
"transLimitCDV": "999999999999",
"terminalCapability": "0000000000000000",
"riskManageData": "01",
"cateCode": "2701",
"currencyCode": "0104"
},
{
"aidEnable": false,
"aid": "A0000001570040", "aid": "A0000001570040",
"cardScheme": "JCB", "cardScheme": "JCB",
"applicationVersion": "0020", "applicationVersion": "0030",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,

View File

@ -14,7 +14,7 @@
"tacOnline": "DC4004F800", "tacOnline": "DC4004F800",
"tacDenial": "0000000000", "tacDenial": "0000000000",
"floorLimit": "000000000000", "floorLimit": "000000000000",
"cvmLimit": 100000, "cvmLimit": 10000000,
"transLimit": "000010000000", "transLimit": "000010000000",
"transLimitCDV": "999999999999", "transLimitCDV": "999999999999",
"terminalCapability": "0000000000000000", "terminalCapability": "0000000000000000",

View File

@ -1,35 +1,9 @@
[ [
{ {
"aidEnable": true, "aidEnable": true,
"aid": "A0000000041010", "aid": "A00000000410",
"cardLabel": "MASTERCARD", "cardLabel": "MASTERCARD",
"applicationVersion": "0020", "applicationVersion": "0002",
"emvDDOL": "9F3704",
"emvTDOL": "9F3704",
"partialAidSelection": false,
"targetPercent": "00",
"maxTargetPercent": "00",
"threshold": "00000040",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 75000,
"transLimit": "999999999999",
"transLimitCDV": "999999999999",
"terminalCapability": "E0F8F8",
"riskManageData": "6C7A800000000000",
"kernelType": "02",
"ttq": "36804000",
"cateCode": "2701",
"currencyCode": "0104"
},
{
"aidEnable": true,
"aid": "A0000000041010C123456789",
"cardLabel": "MASTERCARD",
"applicationVersion": "0020",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,
@ -43,7 +17,7 @@
"cvmLimit": 75000, "cvmLimit": 75000,
"transLimit": "999999999999", "transLimit": "999999999999",
"transLimitCDV": "999999999999", "transLimitCDV": "999999999999",
"terminalCapability": "E0F8F8", "terminalCapability": "E0F8C8",
"riskManageData": "6C7A800000000000", "riskManageData": "6C7A800000000000",
"kernelType": "02", "kernelType": "02",
"ttq": "36804000", "ttq": "36804000",
@ -52,9 +26,34 @@
}, },
{ {
"aidEnable": true, "aidEnable": true,
"aid": "A0000000043060", "aid": "A0000000041010",
"cardLabel": "MASTERCARD", "cardLabel": "MASTERCARD",
"applicationVersion": "0020", "applicationVersion": "0002",
"emvDDOL": "9F3704",
"emvTDOL": "9F3704",
"partialAidSelection": false,
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000040",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 75000,
"transLimit": "999999999999",
"transLimitCDV": "999999999999",
"terminalCapability": "E0F8C8",
"riskManageData": "6C7A800000000000",
"kernelType": "02",
"ttq": "36804000",
"cateCode": "2701",
"currencyCode": "0104"
},
{
"aidEnable": true,
"aid": "A0000000041010C123456789",
"cardLabel": "MASTERCARD",
"applicationVersion": "0002",
"emvDDOL": "9F3704", "emvDDOL": "9F3704",
"emvTDOL": "9F3704", "emvTDOL": "9F3704",
"partialAidSelection": false, "partialAidSelection": false,

View File

@ -173,30 +173,5 @@
"ttq": "32A04000", "ttq": "32A04000",
"cateCode": "2701", "cateCode": "2701",
"currencyCode": "0104" "currencyCode": "0104"
},
{
"aidEnable": true,
"aid": "325041592E5359532E4444463031",
"cardLabel": "VISA",
"applicationVersion": "0030",
"emvDDOL": "9F3704",
"emvTDOL": "9F3704",
"partialAidSelection": false,
"targetPercent": "00",
"maxTargetPercent": "00",
"threshold": "00000000",
"tacDefault": "DC4000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0010000000",
"floorLimit": "000000000000",
"cvmLimit": 70000,
"transLimit": "999999999999",
"transLimitCDV": "999999999999",
"terminalCapability": "0000000000000000",
"riskManageData": "01",
"kernelType": "03",
"ttq": "32A04000",
"cateCode": "2701",
"currencyCode": "0104"
} }
] ]

View File

@ -14,7 +14,7 @@
"tacOnline": "DC4004F800", "tacOnline": "DC4004F800",
"tacDenial": "0000000000", "tacDenial": "0000000000",
"floorLimit": "000000000000", "floorLimit": "000000000000",
"cvmLimit": 75000, "cvmLimit": 30000,
"transLimit": "9999999999", "transLimit": "9999999999",
"transLimitCDV": "9999999999", "transLimitCDV": "9999999999",
"terminalCapability": "0000000000000000", "terminalCapability": "0000000000000000",
@ -39,7 +39,57 @@
"tacOnline": "DC4004F800", "tacOnline": "DC4004F800",
"tacDenial": "0000000000", "tacDenial": "0000000000",
"floorLimit": "000000000000", "floorLimit": "000000000000",
"cvmLimit": 75000, "cvmLimit": 30000,
"transLimit": "9999999999",
"transLimitCDV": "9999999999",
"terminalCapability": "0000000000000000",
"riskManageData": "01",
"kernelType": "01",
"ttq": "36800000",
"cateCode": "2701",
"currencyCode": "0104"
},
{
"aidEnable": true,
"aid": "A000000333010105",
"cardLabel": "UPI",
"applicationVersion": "0002",
"emvDDOL": "9F3704",
"emvTDOL": "9F3704",
"partialAidSelection": false,
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000000",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 30000,
"transLimit": "9999999999",
"transLimitCDV": "9999999999",
"terminalCapability": "0000000000000000",
"riskManageData": "01",
"kernelType": "01",
"ttq": "36800000",
"cateCode": "2701",
"currencyCode": "0104"
},
{
"aidEnable": true,
"aid": "A000000333010106",
"cardLabel": "UPI",
"applicationVersion": "0002",
"emvDDOL": "9F3704",
"emvTDOL": "9F3704",
"partialAidSelection": false,
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000000",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 30000,
"transLimit": "9999999999", "transLimit": "9999999999",
"transLimitCDV": "9999999999", "transLimitCDV": "9999999999",
"terminalCapability": "0000000000000000", "terminalCapability": "0000000000000000",

View File

@ -51,15 +51,175 @@
"checkSum": "1FF80A40173F52D7D27E0F26A146A1C8CCB29046" "checkSum": "1FF80A40173F52D7D27E0F26A146A1C8CCB29046"
}, },
{ {
"rid": "A000000333", "rid": "A000000004",
"indx": "0A", "indx": "00",
"hashInd": "01", "hashInd": "01",
"arithInd": "01", "arithInd": "01",
"modul": "B2AB1B6E9AC55A75ADFD5BBC34490E53C4C3381F34E60E7FAC21CC2B26DD34462B64A6FAE2495ED1DD383B8138BEA100FF9B7A111817E7B9869A9742B19E5C9DAC56F8B8827F11B05A08ECCF9E8D5E85B0F7CFA644EFF3E9B796688F38E006DEB21E101C01028903A06023AC5AAB8635F8E307A53AC742BDCE6A283F585F48EF", "modul": "9c6be5adb10b4be3dce2099b4b210672b89656eba091204f613ecc623bedc9c6d77b660e8baeea7f7ce30f1b153879a4e36459343d1fe47acdbd41fcd710030c2ba1d9461597982c6e1bdd08554b726f5eff7913ce59e79e357295c321e26d0b8be270a9442345c753e2aa2acfc9d30850602fe6cac00c6ddf6b8d9d9b4879b2826b042a07f0e5ae526a3d3c4d22c72b9eaa52eed8893866f866387ac05a1399",
"exponent": "03", "exponent": "03",
"expDate": "3230333031323331", "expDate": "20201231",
"checkSum": "C88BE6B2417C4F941C9371EA35A377158767E4E3" "checkSum": "ec0a59d35d19f031e9e8cbec56db80e22b1de130"
}, },
{
"rid": "A000000004",
"indx": "01",
"hashInd": "01",
"arithInd": "01",
"modul": "C696034213D7D8546984579D1D0F0EA519CFF8DEFFC429354CF3A871A6F7183F1228DA5C7470C055387100CB935A712C4E2864DF5D64BA93FE7E63E71F25B1E5F5298575EBE1C63AA617706917911DC2A75AC28B251C7EF40F2365912490B939BCA2124A30A28F54402C34AECA331AB67E1E79B285DD5771B5D9FF79EA630B75",
"exponent": "03",
"expDate": "20201231",
"checkSum": "8C05A64127485B923C94B63D264AF0BF85CB45D9"
},
{
"rid": "A000000004",
"indx": "03",
"hashInd": "01",
"arithInd": "01",
"modul": "c2490747fe17eb0584c88d47b1602704150adc88c5b998bd59ce043edebf0ffee3093ac7956ad3b6ad4554c6de19a178d6da295be15d5220645e3c8131666fa4be5b84fe131ea44b039307638b9e74a8c42564f892a64df1cb15712b736e3374f1bbb6819371602d8970e97b900793c7c2a89a4a1649a59be680574dd0b60145",
"exponent": "03",
"expDate": "20201231",
"checkSum": "5addf21d09278661141179cbeff272ea384b13bb"
},
{
"rid": "A000000004",
"indx": "04",
"hashInd": "01",
"arithInd": "01",
"modul": "a6da428387a502d7ddfb7a74d3f412be762627197b25435b7a81716a700157ddd06f7cc99d6ca28c2470527e2c03616b9c59217357c2674f583b3ba5c7dcf2838692d023e3562420b4615c439ca97c44dc9a249cfce7b3bfb22f68228c3af13329aa4a613cf8dd853502373d62e49ab256d2bc17120e54aedced6d96a4287acc5c04677d4a5a320db8bee2f775e5fec5",
"exponent": "03",
"expDate": "20201231",
"checkSum": "381a035da58b482ee2af75f4c3f2ca469ba4aa6c"
},
{
"rid": "A000000004",
"indx": "05",
"hashInd": "01",
"arithInd": "01",
"modul": "b8048abc30c90d976336543e3fd7091c8fe4800df820ed55e7e94813ed00555b573feca3d84af6131a651d66cff4284fb13b635edd0ee40176d8bf04b7fd1c7bacf9ac7327dfaa8aa72d10db3b8e70b2ddd811cb4196525ea386acc33c0d9d4575916469c4e4f53e8e1c912cc618cb22dde7c3568e90022e6bba770202e4522a2dd623d180e215bd1d1507fe3dc90ca310d27b3efccd8f83de3052cad1e48938c68d095aac91b5f37e28bb49ec7ed597",
"exponent": "03",
"expDate": "20201231",
"checkSum": "ebfa0d5d06d8ce702da3eae890701d45e274c845"
},
{
"rid": "A000000004",
"indx": "06",
"hashInd": "01",
"arithInd": "01",
"modul": "cb26fc830b43785b2bce37c81ed334622f9622f4c89aae641046b2353433883f307fb7c974162da72f7a4ec75d9d657336865b8d3023d3d645667625c9a07a6b7a137cf0c64198ae38fc238006fb2603f41f4f3bb9da1347270f2f5d8c606e420958c5f7d50a71de30142f70de468889b5e3a08695b938a50fc980393a9cbce44ad2d64f630bb33ad3f5f5fd495d31f37818c1d94071342e07f1bec2194f6035ba5ded3936500eb82dfda6e8afb655b1ef3d0d7ebf86b66dd9f29f6b1d324fe8b26ce38ab2013dd13f611e7a594d675c4432350ea244cc34f3873cba06592987a1d7e852adc22ef5a2ee28132031e48f74037e3b34ab747f",
"exponent": "03",
"expDate": "20201231",
"checkSum": "f910a1504d5ffb793d94f3b500765e1abcad72d9"
},
{
"rid": "A000000004",
"indx": "F1",
"hashInd": "01",
"arithInd": "01",
"modul": "a0dcf4bde19c3546b4b6f0414d174dde294aabbb828c5a834d73aae27c99b0b053a90278007239b6459ff0bbcd7b4b9c6c50ac02ce91368da1bd21aaeadbc65347337d89b68f5c99a09d05be02dd1f8c5ba20e2f13fb2a27c41d3f85cad5cf6668e75851ec66edbf98851fd4e42c44c1d59f5984703b27d5b9f21b8fa0d93279fbbf69e090642909c9ea27f898959541aa6757f5f624104f6e1d3a9532f2a6e51515aead1b43b3d7835088a2fafa7be7",
"exponent": "03",
"expDate": "20201231",
"checkSum": "d8e68da167ab5a85d8c3d55ecb9b0517a1a5b4bb"
},
{
"rid": "A000000004",
"indx": "F3",
"hashInd": "01",
"arithInd": "01",
"modul": "98f0c770f23864c2e766df02d1e833dff4ffe92d696e1642f0a88c5694c6479d16db1537bfe29e4fdc6e6e8afd1b0eb7ea0124723c333179bf19e93f10658b2f776e829e87daeda9c94a8b3382199a350c077977c97aff08fd11310ac950a72c3ca5002ef513fccc286e646e3c5387535d509514b3b326e1234f9cb48c36ddd44b416d23654034a66f403ba511c5efa3",
"exponent": "03",
"expDate": "20201231",
"checkSum": "a69ac7603daf566e972dedc2cb433e07e8b01a9a"
},
{
"rid": "A000000004",
"indx": "F5",
"hashInd": "01",
"arithInd": "01",
"modul": "a6e6fb72179506f860ccca8c27f99cecd94c7d4f3191d303bbee37481c7aa15f233ba755e9e4376345a9a67e7994bdc1c680bb3522d8c93eb0ccc91ad31ad450da30d337662d19ac03e2b4ef5f6ec18282d491e19767d7b24542dfdeff6f62185503532069bbb369e3bb9fb19ac6f1c30b97d249eee764e0bac97f25c873d973953e5153a42064bbfabfd06a4bb486860bf6637406c9fc36813a4a75f75c31cca9f69f8de59adecef6bde7e07800fcbe035d3176af8473e23e9aa3dfee221196d1148302677c720cfe2544a03db553e7f1b8427ba1cc72b0f29b12dfef4c081d076d353e71880aadff386352af0ab7b28ed49e1e672d11f9",
"exponent": "010001",
"expDate": "20201231",
"checkSum": "c2239804c8098170be52d6d5d4159e81ce8466bf"
},
{
"rid": "A000000004",
"indx": "F6",
"hashInd": "01",
"arithInd": "01",
"modul": "a25a6bd783a5ef6b8fb6f83055c260f5f99ea16678f3b9053e0f6498e82c3f5d1e8c38f13588017e2b12b3d8ff6f50167f46442910729e9e4d1b3739e5067c0ac7a1f4487e35f675bc16e233315165cb142bfdb25e301a632a54a3371ebab6572deebaf370f337f057ee73b4ae46d1a8bc4da853ec3cc12c8cbc2da18322d68530c70b22bdac351dd36068ae321e11abf264f4d3569bb71214545005558de26083c735db776368172fe8c2f5c85e8b5b890cc682911d2de71fa626b8817fccc08922b703869f3baeac1459d77cd85376bc36182f4238314d6c4212fbdd7f23d3",
"exponent": "03",
"expDate": "20201231",
"checkSum": "502909ed545e3c8dbd00ea582d0617fee9f6f684"
},
{
"rid": "A000000004",
"indx": "F7",
"hashInd": "01",
"arithInd": "01",
"modul": "94ea62f6d58320e354c022addcf0559d8cf206cd92e869564905ce21d720f971b7aea374830ebe1757115a85e088d41c6b77cf5ec821f30b1d890417bf2fa31e5908ded5fa677f8c7b184ad09028fdde96b6a6109850aa800175eabcdbbb684a96c2eb6379dfea08d32fe2331fe103233ad58dcdb1e6e077cb9f24eaec5c25af",
"exponent": "010001",
"expDate": "20201231",
"checkSum": "eeb0dd9b2477bee3209a914cdba94c1c4a9bded9"
},
{
"rid": "A000000004",
"indx": "F8",
"hashInd": "01",
"arithInd": "01",
"modul": "a1f5e1c9bd8650bd43ab6ee56b891ef7459c0a24fa84f9127d1a6c79d4930f6db1852e2510f18b61cd354db83a356bd190b88ab8df04284d02a4204a7b6cb7c5551977a9b36379ca3de1a08e69f301c95cc1c20506959275f41723dd5d2925290579e5a95b0df6323fc8e9273d6f849198c4996209166d9bfc973c361cc826e1",
"exponent": "03",
"expDate": "20201231",
"checkSum": "f06ecc6d2aaebf259b7e755a38d9a9b24e2ff3dd"
},
{
"rid": "A000000004",
"indx": "F9",
"hashInd": "01",
"arithInd": "01",
"modul": "a99a6d3e071889ed9e3a0c391c69b0b804fc160b2b4bdd570c92dd5a0f45f53e8621f7c96c40224266735e1ee1b3c06238ae35046320fd8e81f8ceb3f8b4c97b940930a3ac5e790086dad41a6a4f5117ba1ce2438a51ac053eb002aed866d2c458fd73359021a12029a0c043045c11664fe0219ec63c10bf2155bb2784609a106421d45163799738c1c30909bb6c6fe52bbb76397b9740ce064a613ff8411185f08842a423ead20edffbff1cd6c3fe0c9821479199c26d8572cc8afff087a9c3",
"exponent": "03",
"expDate": "20201231",
"checkSum": "336712dcc28554809c6aa9b02358de6f755164db"
},
{
"rid": "A000000004",
"indx": "FA",
"hashInd": "01",
"arithInd": "01",
"modul": "a90fcd55aa2d5d9963e35ed0f440177699832f49c6bab15cdae5794be93f934d4462d5d12762e48c38ba83d8445deaa74195a301a102b2f114eada0d180ee5e7a5c73e0c4e11f67a43ddab5d55683b1474cc0627f44b8d3088a492ffaadad4f42422d0e7013536c3c49ad3d0fae96459b0f6b1b6056538a3d6d44640f94467b108867dec40faaecd740c00e2b7a8852d",
"exponent": "03",
"expDate": "20201231",
"checkSum": "5bed4068d96ea16d2d77e03d6036fc7a160ea99c"
},
{
"rid": "A000000004",
"indx": "FE",
"hashInd": "01",
"arithInd": "01",
"modul": "a653eac1c0f786c8724f737f172997d63d1c3251c44402049b865bae877d0f398cbfbe8a6035e24afa086befde9351e54b95708ee672f0968bcd50dce40f783322b2aba04ef137ef18abf03c7dbc5813aeaef3aa7797ba15df7d5ba1cbaf7fd520b5a482d8d3fee105077871113e23a49af3926554a70fe10ed728cf793b62a1",
"exponent": "03",
"expDate": "20201231",
"checkSum": "9a295b05fb390ef7923f57618a9fda2941fc34e0"
},
{
"rid": "A000000004",
"indx": "EF",
"hashInd": "01",
"arithInd": "01",
"modul": "a191cb87473f29349b5d60a88b3eaee0973aa6f1a082f358d849fddff9c091f899eda9792caf09ef28f5d22404b88a2293eebbc1949c43bea4d60cfd879a1539544e09e0f09f60f065b2bf2a13ecc705f3d468b9d33ae77ad9d3f19ca40f23dcf5eb7c04dc8f69eba565b1ebcb4686cd274785530ff6f6e9ee43aa43fdb02ce00daec15c7b8fd6a9b394baba419d3f6dc85e16569be8e76989688efea2df22ff7d35c043338deaa982a02b866de5328519ebbcd6f03cdd686673847f84db651ab86c28cf1462562c577b853564a290c8556d818531268d25cc98a4cc6a0bdfffda2dcca3a94c998559e307fddf915006d9a987b07ddaeb3b",
"exponent": "03",
"expDate": "20201231",
"checkSum": "21766ebb0ee122afb65d7845b73db46bab65427a"
},
{
"rid": "A000000333",
"indx": "0A",
"hashInd": "01",
"arithInd": "01",
"modul": "B2AB1B6E9AC55A75ADFD5BBC34490E53C4C3381F34E60E7FAC21CC2B26DD34462B64A6FAE2495ED1DD383B8138BEA100FF9B7A111817E7B9869A9742B19E5C9DAC56F8B8827F11B05A08ECCF9E8D5E85B0F7CFA644EFF3E9B796688F38E006DEB21E101C01028903A06023AC5AAB8635F8E307A53AC742BDCE6A283F585F48EF",
"exponent": "03",
"expDate": "3230333031323331",
"checkSum": "C88BE6B2417C4F941C9371EA35A377158767E4E3"
},
{ {
"rid": "A000000333", "rid": "A000000333",
"indx": "08", "indx": "08",
@ -90,6 +250,16 @@
"expDate": "3230333031323331", "expDate": "3230333031323331",
"checkSum": "BD331F9996A490B33C13441066A09AD3FEB5F66C" "checkSum": "BD331F9996A490B33C13441066A09AD3FEB5F66C"
}, },
{
"rid": "A000000065",
"indx": "07",
"hashInd": "01",
"arithInd": "00",
"modul": "B8DAB883EF1B5763E4F861F9EA3044B276635D402F3AE5E6B6C0547E368E79A36366DAC5609B6EC486DA1A8D2002CA4F4EFC2CB0EC1573A0B0917969EB60645BAEDF11C050C5D07FED817D11E84A174859A0DAE7F7935F109229C0AC4EE5BFB3D65533A679F0486C5AEFCC937379833BEC45D79DCF97B5228B1910FA03765331",
"exponent": "010001",
"expDate": "20201231",
"checkSum": "4896DD5A9EB5B11B9DCCA6DFE336C009F69F509A"
},
{ {
"rid": "A000000065", "rid": "A000000065",
"indx": "08", "indx": "08",
@ -97,7 +267,7 @@
"arithInd": "00", "arithInd": "00",
"modul": "B74670DAD1DC8983652000E5A7F2F8B35DFD083EE593E5BA895C95729F2BADE9C8ABF3DD9CE240C451C6CEFFC768D83CBAC76ABB8FEA58F013C647007CFF7617BAC2AE3981816F25CC7E5238EF34C4F02D0B01C24F80C2C65E7E7743A4FA8E23206A23ECE290C26EA56DB085C5C5EAE26292451FC8292F9957BE8FF20FAD53E5", "modul": "B74670DAD1DC8983652000E5A7F2F8B35DFD083EE593E5BA895C95729F2BADE9C8ABF3DD9CE240C451C6CEFFC768D83CBAC76ABB8FEA58F013C647007CFF7617BAC2AE3981816F25CC7E5238EF34C4F02D0B01C24F80C2C65E7E7743A4FA8E23206A23ECE290C26EA56DB085C5C5EAE26292451FC8292F9957BE8FF20FAD53E5",
"exponent": "03", "exponent": "03",
"expDate": "3230333031323331", "expDate": "20201231",
"checkSum": "DD36D5896228C8C4900742F107E2F91FE50BC7EE" "checkSum": "DD36D5896228C8C4900742F107E2F91FE50BC7EE"
}, },
{ {
@ -117,7 +287,7 @@
"arithInd": "00", "arithInd": "00",
"modul": "99B63464EE0B4957E4FD23BF923D12B61469B8FFF8814346B2ED6A780F8988EA9CF0433BC1E655F05EFA66D0C98098F25B659D7A25B8478A36E489760D071F54CDF7416948ED733D816349DA2AADDA227EE45936203CBF628CD033AABA5E5A6E4AE37FBACB4611B4113ED427529C636F6C3304F8ABDD6D9AD660516AE87F7F2DDF1D2FA44C164727E56BBC9BA23C0285", "modul": "99B63464EE0B4957E4FD23BF923D12B61469B8FFF8814346B2ED6A780F8988EA9CF0433BC1E655F05EFA66D0C98098F25B659D7A25B8478A36E489760D071F54CDF7416948ED733D816349DA2AADDA227EE45936203CBF628CD033AABA5E5A6E4AE37FBACB4611B4113ED427529C636F6C3304F8ABDD6D9AD660516AE87F7F2DDF1D2FA44C164727E56BBC9BA23C0285",
"exponent": "03", "exponent": "03",
"expDate": "3230333031323331", "expDate": "20201231",
"checkSum": "C75E5210CBE6E8F0594A0F1911B07418CADB5BAB" "checkSum": "C75E5210CBE6E8F0594A0F1911B07418CADB5BAB"
}, },
{ {
@ -127,7 +297,7 @@
"arithInd": "00", "arithInd": "00",
"modul": "A2583AA40746E3A63C22478F576D1EFC5FB046135A6FC739E82B55035F71B09BEB566EDB9968DD649B94B6DEDC033899884E908C27BE1CD291E5436F762553297763DAA3B890D778C0F01E3344CECDFB3BA70D7E055B8C760D0179A403D6B55F2B3B083912B183ADB7927441BED3395A199EEFE0DEBD1F5FC3264033DA856F4A8B93916885BD42F9C1F456AAB8CFA83AC574833EB5E87BB9D4C006A4B5346BD9E17E139AB6552D9C58BC041195336485", "modul": "A2583AA40746E3A63C22478F576D1EFC5FB046135A6FC739E82B55035F71B09BEB566EDB9968DD649B94B6DEDC033899884E908C27BE1CD291E5436F762553297763DAA3B890D778C0F01E3344CECDFB3BA70D7E055B8C760D0179A403D6B55F2B3B083912B183ADB7927441BED3395A199EEFE0DEBD1F5FC3264033DA856F4A8B93916885BD42F9C1F456AAB8CFA83AC574833EB5E87BB9D4C006A4B5346BD9E17E139AB6552D9C58BC041195336485",
"exponent": "03", "exponent": "03",
"expDate": "3230333031323331", "expDate": "20201231",
"checkSum": "D9FD62C9DD4E6DE7741E9A17FB1FF2C5DB948BCB" "checkSum": "D9FD62C9DD4E6DE7741E9A17FB1FF2C5DB948BCB"
}, },
{ {
@ -137,28 +307,17 @@
"arithInd": "00", "arithInd": "00",
"modul": "AEED55B9EE00E1ECEB045F61D2DA9A66AB637B43FB5CDBDB22A2FBB25BE061E937E38244EE5132F530144A3F268907D8FD648863F5A96FED7E42089E93457ADC0E1BC89C58A0DB72675FBC47FEE9FF33C16ADE6D341936B06B6A6F5EF6F66A4EDD981DF75DA8399C3053F430ECA342437C23AF423A211AC9F58EAF09B0F837DE9D86C7109DB1646561AA5AF0289AF5514AC64BC2D9D36A179BB8A7971E2BFA03A9E4B847FD3D63524D43A0E8003547B94A8A75E519DF3177D0A60BC0B4BAB1EA59A2CBB4D2D62354E926E9C7D3BE4181E81BA60F8285A896D17DA8C3242481B6C405769A39D547C74ED9FF95A70A796046B5EFF36682DC29", "modul": "AEED55B9EE00E1ECEB045F61D2DA9A66AB637B43FB5CDBDB22A2FBB25BE061E937E38244EE5132F530144A3F268907D8FD648863F5A96FED7E42089E93457ADC0E1BC89C58A0DB72675FBC47FEE9FF33C16ADE6D341936B06B6A6F5EF6F66A4EDD981DF75DA8399C3053F430ECA342437C23AF423A211AC9F58EAF09B0F837DE9D86C7109DB1646561AA5AF0289AF5514AC64BC2D9D36A179BB8A7971E2BFA03A9E4B847FD3D63524D43A0E8003547B94A8A75E519DF3177D0A60BC0B4BAB1EA59A2CBB4D2D62354E926E9C7D3BE4181E81BA60F8285A896D17DA8C3242481B6C405769A39D547C74ED9FF95A70A796046B5EFF36682DC29",
"exponent": "03", "exponent": "03",
"expDate": "3230333031323331", "expDate": "20201231",
"checkSum": "43A3151513B7ADCEB92DBEA2A262CEB336D26C83" "checkSum": "43A3151513B7ADCEB92DBEA2A262CEB336D26C83"
}, },
{ {
"rid": "A000000004", "rid": "A000000065",
"indx": "F1", "indx": "13",
"hashInd": "01", "hashInd": "01",
"arithInd": "01", "arithInd": "00",
"modul": "A0DCF4BDE19C3546B4B6F0414D174DDE294AABBB828C5A834D73AAE27C99B0B053A90278007239B6459FF0BBCD7B4B9C6C50AC02CE91368DA1BD21AAEADBC65347337D89B68F5C99A09D05BE02DD1F8C5BA20E2F13FB2A27C41D3F85CAD5CF6668E75851EC66EDBF98851FD4E42C44C1D59F5984703B27D5B9F21B8FA0D93279FBBF69E090642909C9EA27F898959541AA6757F5F624104F6E1D3A9532F2A6E51515AEAD1B43B3D7835088A2FAFA7BE7", "modul": "A3270868367E6E29349FC2743EE545AC53BD3029782488997650108524FD051E3B6EACA6A9A6C1441D28889A5F46413C8F62F3645AAEB30A1521EEF41FD4F3445BFA1AB29F9AC1A74D9A16B93293296CB09162B149BAC22F88AD8F322D684D6B49A12413FC1B6AC70EDEDB18EC1585519A89B50B3D03E14063C2CA58B7C2BA7FB22799A33BCDE6AFCBEB4A7D64911D08D18C47F9BD14A9FAD8805A15DE5A38945A97919B7AB88EFA11A88C0CD92C6EE7DC352AB0746ABF13585913C8A4E04464B77909C6BD94341A8976C4769EA6C0D30A60F4EE8FA19E767B170DF4FA80312DBA61DB645D5D1560873E2674E1F620083F30180BD96CA589",
"exponent": "03", "exponent": "03",
"expDate": "20201231", "expDate": "20201231",
"checkSum": "D8E68DA167AB5A85D8C3D55ECB9B0517A1A5B4BB" "checkSum": "54CFAE617150DFA09D3F901C9123524523EBEDF3"
},
{
"rid": "A000000004",
"indx": "EF",
"hashInd": "01",
"arithInd": "01",
"modul": "A191CB87473F29349B5D60A88B3EAEE0973AA6F1A082F358D849FDDFF9C091F899EDA9792CAF09EF28F5D22404B88A2293EEBBC1949C43BEA4D60CFD879A1539544E09E0F09F60F065B2BF2A13ECC705F3D468B9D33AE77AD9D3F19CA40F23DCF5EB7C04DC8F69EBA565B1EBCB4686CD274785530FF6F6E9EE43AA43FDB02CE00DAEC15C7B8FD6A9B394BABA419D3F6DC85E16569BE8E76989688EFEA2DF22FF7D35C043338DEAA982A02B866DE5328519EBBCD6F03CDD686673847F84DB651AB86C28CF1462562C577B853564A290C8556D818531268D25CC98A4CC6A0BDFFFDA2DCCA3A94C998559E307FDDF915006D9A987B07DDAEB3B",
"exponent": "03",
"expDate": "20201231",
"checkSum": "21766EBB0EE122AFB65D7845B73DB46BAB65427A"
} }
] ]

View File

@ -21,7 +21,7 @@ public class ExampleUnitTest {
@Test @Test
public void testCAPKIndex() { public void testCAPKIndex() {
String index = "99"; String index = "F1";
int data = Integer.parseInt(index,16); int data = Integer.parseInt(index,16);
System.out.println("Data: "+data); System.out.println("Data: "+data);

View File

@ -6,6 +6,7 @@ import android.os.Looper;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import com.nexgo.common.LogUtils;
import com.nexgo.oaf.apiv3.SdkResult; import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.reader.CardInfoEntity; import com.nexgo.oaf.apiv3.device.reader.CardInfoEntity;
import com.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum; import com.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum;
@ -106,6 +107,14 @@ public class CheckCardX {
Log.d(TAG, "Find IC"); Log.d(TAG, "Find IC");
} else if(cardInfoEntity.getCardExistslot() == CardSlotTypeEnum.RF) { } else if(cardInfoEntity.getCardExistslot() == CardSlotTypeEnum.RF) {
checkCardResultX.onSuccess(CardTypeX.NFC,false); checkCardResultX.onSuccess(CardTypeX.NFC,false);
} else if(cardInfoEntity.getCardExistslot() == CardSlotTypeEnum.SWIPE) {
LogUtils.debug(TAG,"Found Swipe");
Bundle info = new Bundle();
info.putString("TRACK1",cardInfoEntity.getTk1());
info.putString("TRACK2",cardInfoEntity.getTk2());
info.putString("TRACK3",cardInfoEntity.getTk3());
MAGXReadCard.getInstance().setBundle(info);
checkCardResultX.onSuccess(CardTypeX.MAG,false);
} }
} else if( i == SdkResult.Fail) { } else if( i == SdkResult.Fail) {
checkCardResultX.onError(i,"Failure"); checkCardResultX.onError(i,"Failure");

View File

@ -1,2 +1,2 @@
configurations.maybeCreate("default") configurations.maybeCreate("default")
artifacts.add("default", file('nexgo-smartpos-sdk-v3.08.006_20241216.aar')) artifacts.add("default", file('nexgo-smartpos-sdk-v3.08.013_20260416.aar'))

Binary file not shown.

Binary file not shown.

View File

@ -1,15 +1,17 @@
package com.utsmyanmar.paylibs.model; package com.utsmyanmar.paylibs.model;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class CardSettleData { public class CardSettleData implements Serializable {
private String cardType; private String cardType;
private String cardNum; private String cardNum;
private String expDate; private String expDate;
private String invoiceNum; private String invoiceNum;
private String transType; private String transType;
private String currencyCode;
private long amount; private long amount;
@ -21,12 +23,13 @@ public class CardSettleData {
public CardSettleData() { public CardSettleData() {
} }
public CardSettleData(String cardType, String cardNum, String expDate, String invoiceNum, String transType, long amount, String transDate, String transTime, String approvalCode) { public CardSettleData(String cardType, String cardNum, String expDate, String invoiceNum, String transType, String currencyCode, long amount, String transDate, String transTime, String approvalCode) {
this.cardType = cardType; this.cardType = cardType;
this.cardNum = cardNum; this.cardNum = cardNum;
this.expDate = expDate; this.expDate = expDate;
this.invoiceNum = invoiceNum; this.invoiceNum = invoiceNum;
this.transType = transType; this.transType = transType;
this.currencyCode = currencyCode;
this.amount = amount; this.amount = amount;
this.transDate = transDate; this.transDate = transDate;
this.transTime = transTime; this.transTime = transTime;
@ -53,6 +56,10 @@ public class CardSettleData {
this.transType = transType; this.transType = transType;
} }
public void setCurrencyCode(String currencyCode) {
this.currencyCode = currencyCode;
}
public void setAmount(long amount) { public void setAmount(long amount) {
this.amount = amount; this.amount = amount;
} }
@ -85,6 +92,10 @@ public class CardSettleData {
return transType; return transType;
} }
public String getCurrencyCode() {
return currencyCode;
}
public long getAmount() { public long getAmount() {
return amount; return amount;
} }
@ -114,6 +125,7 @@ public class CardSettleData {
cardSettleData.setExpDate(pay.getEXPDate()); cardSettleData.setExpDate(pay.getEXPDate());
cardSettleData.setInvoiceNum(pay.getInvoiceNo()); cardSettleData.setInvoiceNum(pay.getInvoiceNo());
cardSettleData.setTransType(pay.getTransType()); cardSettleData.setTransType(pay.getTransType());
cardSettleData.setCurrencyCode(pay.getCurrencyCode());
cardSettleData.setAmount(pay.getAmount()); cardSettleData.setAmount(pay.getAmount());
cardSettleData.setTransDate(pay.getTransDate()); cardSettleData.setTransDate(pay.getTransDate());
cardSettleData.setTransTime(pay.getTransTime()); cardSettleData.setTransTime(pay.getTransTime());

View File

@ -1,9 +1,10 @@
package com.utsmyanmar.paylibs.model; package com.utsmyanmar.paylibs.model;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class QRSettleData { public class QRSettleData implements Serializable {
private String transId; private String transId;
private String date; private String date;

View File

@ -1,6 +1,8 @@
package com.utsmyanmar.paylibs.model; package com.utsmyanmar.paylibs.model;
public class SettleData { import java.io.Serializable;
public class SettleData implements Serializable {
private int saleCount; private int saleCount;
private long saleAmount; private long saleAmount;

View File

@ -1,6 +1,8 @@
package com.utsmyanmar.paylibs.model.enums; package com.utsmyanmar.paylibs.model.enums;
public enum TransCVM { import java.io.Serializable;
public enum TransCVM implements Serializable {
OFFLINE_PIN("Offline PIN"), OFFLINE_PIN("Offline PIN"),
ONLINE_PIN("Online PIN"), ONLINE_PIN("Online PIN"),
SIGNATURE("Signature"), SIGNATURE("Signature"),

View File

@ -45,6 +45,7 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -122,7 +123,7 @@ public abstract class BaseXPrint {
returnText[1] = 0x33; returnText[1] = 0x33;
returnText[2] = (byte) height; returnText[2] = (byte) height;
Resources resources = PayLibNex.getInstance().context.getResources(); Resources resources = PayLibNex.getInstance().context.getResources();
printer.setTypeface(Typeface.createFromAsset(PayLibNex.getInstance().context.getAssets(), "fonts/fira_code_medium.ttf")); printer.setTypeface(Typeface.createFromAsset(PayLibNex.getInstance().context.getAssets(), "fonts/firaCode_bold.ttf"));
printer.setGray(getGrayLevel()); printer.setGray(getGrayLevel());
} }
@ -212,26 +213,38 @@ public abstract class BaseXPrint {
} }
protected void printTransDetailSettlement(PayDetail payDetail) { protected void printTransDetailSettlement(PayDetail payDetail) {
SettleData settleData = payDetail.getSettleDataObj(); SettleData settleData = payDetail.getSettleDataObj();
int totalCount = settleData.getSaleCount() + settleData.getPreAuthCompCount() + settleData.getRefundCount() + settleData.getCashAdvanceCount(); List<CardSettleData> cardSettleDataList = payDetail.getCardSettleData();
long totalAmount = settleData.getSaleAmount() + settleData.getPreAuthCompAmount() + settleData.getCashAdvanceAmount(); CurrencySettlementSummary mmkSummary = new CurrencySettlementSummary();
CurrencySettlementSummary usdSummary = new CurrencySettlementSummary();
print3ColumnsString("TRX TYPE ", "CNT", "AMOUNT"); if (cardSettleDataList != null && !cardSettleDataList.isEmpty()) {
print3ColumnsString("SALE ", countStringFormat(settleData.getSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getSaleAmount())); for (CardSettleData cardSettleData : cardSettleDataList) {
print3ColumnsString("PREAUTH COMP ", countStringFormat(settleData.getPreAuthCompCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getPreAuthCompAmount())); CurrencySettlementSummary summary = "USD".equals(normalizeSettlementCurrency(cardSettleData.getCurrencyCode())) ? usdSummary : mmkSummary;
if (settleData.getCashAdvanceCount() != 0) applyCardSettlementSummary(summary, cardSettleData);
print3ColumnsString("CASH ADVANCE ", countStringFormat(settleData.getCashAdvanceCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getCashAdvanceAmount())); }
print3ColumnsString("REFUND ", countStringFormat(settleData.getRefundCount()), "- " + PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getRefundAmount())); } else {
print3ColumnsString("TOTAL(MMK) ", countStringFormat(totalCount), PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount)); mmkSummary.saleCount = settleData.getSaleCount();
mmkSummary.saleAmount = settleData.getSaleAmount();
mmkSummary.preAuthCompCount = settleData.getPreAuthCompCount();
mmkSummary.preAuthCompAmount = settleData.getPreAuthCompAmount();
mmkSummary.refundCount = settleData.getRefundCount();
mmkSummary.refundAmount = settleData.getRefundAmount();
mmkSummary.cashAdvanceCount = settleData.getCashAdvanceCount();
mmkSummary.cashAdvanceAmount = settleData.getCashAdvanceAmount();
}
printSettlementCurrencySection("MMK", mmkSummary);
if (usdSummary.hasAnyValue()) {
emptyLine(1);
printSettlementCurrencySection("USD", usdSummary);
}
emptyLine(2); emptyLine(2);
} }
protected void printTransDetailSettlement(PayDetail payDetail, List<CardSettleData> cardSettleDataList) { protected void printTransDetailSettlement(PayDetail payDetail, List<CardSettleData> cardSettleDataList) {
boolean isDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
lineBreak(); lineBreak();
print2SideStringMargin("CARD TYPE ","CARD NUMBER"); print2SideStringMargin("CARD TYPE ","CARD NUMBER");
@ -243,7 +256,7 @@ public abstract class BaseXPrint {
for (CardSettleData cardSettleData:cardSettleDataList) { for (CardSettleData cardSettleData:cardSettleDataList) {
print2SideStringMargin(cardSettleData.getCardType(),PrintUtils.getInstance().maskCardNumberPciDss(cardSettleData.getCardNum())); print2SideStringMargin(cardSettleData.getCardType(),PrintUtils.getInstance().maskCardNumberPciDss(cardSettleData.getCardNum()));
print2SideStringMargin("XX/XX",cardSettleData.getInvoiceNum()); print2SideStringMargin("XX/XX",cardSettleData.getInvoiceNum());
print2SideStringMargin(cardSettleData.getTransType(),"MMK "+PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount(),true)); print2SideStringMargin(cardSettleData.getTransType(),"MMK "+PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount(), isDecimalEnabled));
print2SideStringMargin(cardSettleData.getApprovalCode(),cardSettleData.getTransDate() + " " + cardSettleData.getTransTime() ); print2SideStringMargin(cardSettleData.getApprovalCode(),cardSettleData.getTransDate() + " " + cardSettleData.getTransTime() );
emptyLine(1); emptyLine(1);
} }
@ -254,28 +267,95 @@ public abstract class BaseXPrint {
long totalAmount = settleData.getSaleAmount() + settleData.getPreAuthCompAmount() + settleData.getCashAdvanceAmount(); long totalAmount = settleData.getSaleAmount() + settleData.getPreAuthCompAmount() + settleData.getCashAdvanceAmount();
print3ColumnsString("TRX TYPE ", "CNT", "AMOUNT"); print3ColumnsString("TRX TYPE ", "CNT", "AMOUNT");
print3ColumnsString("SALE ", countStringFormat(settleData.getSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getSaleAmount())); print3ColumnsString("SALE ", countStringFormat(settleData.getSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getSaleAmount(), isDecimalEnabled));
print3ColumnsString("VOID SALE ", countStringFormat(settleData.getVoidSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getVoidSaleAmount())); print3ColumnsString("VOID SALE ", countStringFormat(settleData.getVoidSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getVoidSaleAmount(), isDecimalEnabled));
print3ColumnsString("PREAUTH COMP ", countStringFormat(settleData.getPreAuthCompCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getPreAuthCompAmount())); print3ColumnsString("PREAUTH COMP ", countStringFormat(settleData.getPreAuthCompCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getPreAuthCompAmount(), isDecimalEnabled));
if (settleData.getCashAdvanceCount() != 0) if (settleData.getCashAdvanceCount() != 0)
print3ColumnsString("CASH ADV ", countStringFormat(settleData.getCashAdvanceCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getCashAdvanceAmount())); print3ColumnsString("CASH ADV ", countStringFormat(settleData.getCashAdvanceCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getCashAdvanceAmount(), isDecimalEnabled));
print3ColumnsString("REFUND ", countStringFormat(settleData.getRefundCount()), "- " + PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getRefundAmount())); print3ColumnsString("REFUND ", countStringFormat(settleData.getRefundCount()), "- " + PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getRefundAmount(), isDecimalEnabled));
emptyLine(1); emptyLine(1);
printer.appendPrnStr("GRAND TOTAL", fontLarge, AlignEnum.LEFT,true); printer.appendPrnStr("GRAND TOTAL", fontLarge, AlignEnum.LEFT,true);
emptyLine(1); emptyLine(1);
// print3ColumnsString("TOTAL(MMK) ", countStringFormat(totalCount), PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount)); // print3ColumnsString("TOTAL(MMK) ", countStringFormat(totalCount), PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount));
print3ColumnsString("TRX TYPE ", "CNT", "AMOUNT"); print3ColumnsString("TRX TYPE ", "CNT", "AMOUNT");
print3ColumnsString("SALE ", countStringFormat(settleData.getSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getSaleAmount())); print3ColumnsString("SALE ", countStringFormat(settleData.getSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getSaleAmount(), isDecimalEnabled));
print3ColumnsString("VOID SALE ", countStringFormat(settleData.getVoidSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getVoidSaleAmount())); print3ColumnsString("VOID SALE ", countStringFormat(settleData.getVoidSaleCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getVoidSaleAmount(), isDecimalEnabled));
print3ColumnsString("PREAUTH COMP ", countStringFormat(settleData.getPreAuthCompCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getPreAuthCompAmount())); print3ColumnsString("PREAUTH COMP ", countStringFormat(settleData.getPreAuthCompCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getPreAuthCompAmount(), isDecimalEnabled));
if (settleData.getCashAdvanceCount() != 0) if (settleData.getCashAdvanceCount() != 0)
print3ColumnsString("CASH ADV ", countStringFormat(settleData.getCashAdvanceCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getCashAdvanceAmount())); print3ColumnsString("CASH ADV ", countStringFormat(settleData.getCashAdvanceCount()), PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getCashAdvanceAmount(), isDecimalEnabled));
print3ColumnsString("REFUND ", countStringFormat(settleData.getRefundCount()), "- " + PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getRefundAmount())); print3ColumnsString("REFUND ", countStringFormat(settleData.getRefundCount()), "- " + PrintUtils.getInstance().getSeparatorNumberFormat(settleData.getRefundAmount(), isDecimalEnabled));
emptyLine(2); emptyLine(2);
} }
private void printSettlementCurrencySection(String currencyLabel, CurrencySettlementSummary summary) {
if (!summary.hasAnyValue()) {
return;
}
boolean isDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
int totalCount = summary.saleCount + summary.preAuthCompCount + summary.refundCount + summary.cashAdvanceCount;
long totalAmount = summary.saleAmount + summary.preAuthCompAmount + summary.cashAdvanceAmount - summary.refundAmount;
printString("CURRENCY : " + currencyLabel, true);
print3ColumnsString("TRX TYPE ", "CNT", "AMOUNT");
print3ColumnsString("SALE ", countStringFormat(summary.saleCount), PrintUtils.getInstance().getSeparatorNumberFormat(summary.saleAmount, isDecimalEnabled));
print3ColumnsString("PREAUTH COMP ", countStringFormat(summary.preAuthCompCount), PrintUtils.getInstance().getSeparatorNumberFormat(summary.preAuthCompAmount, isDecimalEnabled));
if (summary.cashAdvanceCount != 0) {
print3ColumnsString("CASH ADVANCE ", countStringFormat(summary.cashAdvanceCount), PrintUtils.getInstance().getSeparatorNumberFormat(summary.cashAdvanceAmount, isDecimalEnabled));
}
print3ColumnsString("REFUND ", countStringFormat(summary.refundCount), "- " + PrintUtils.getInstance().getSeparatorNumberFormat(summary.refundAmount, isDecimalEnabled));
print3ColumnsString("TOTAL(" + currencyLabel + ") ", countStringFormat(totalCount), PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount, isDecimalEnabled));
}
private void applyCardSettlementSummary(CurrencySettlementSummary summary, CardSettleData cardSettleData) {
String transType = cardSettleData.getTransType() == null ? "" : cardSettleData.getTransType().trim().toUpperCase(Locale.getDefault());
long amount = cardSettleData.getAmount();
if ("SALE".equals(transType)) {
summary.saleCount++;
summary.saleAmount += amount;
} else if ("PREAUTH COMPLETION".equals(transType) || "PRE_AUTH_COMPLETE".equals(transType)) {
summary.preAuthCompCount++;
summary.preAuthCompAmount += amount;
} else if ("REFUND".equals(transType)) {
summary.refundCount++;
summary.refundAmount += amount;
} else if ("CASH_OUT".equals(transType) || "CASH_ADVANCE".equals(transType)) {
summary.cashAdvanceCount++;
summary.cashAdvanceAmount += amount;
}
}
private String normalizeSettlementCurrency(String currencyCode) {
if (currencyCode == null) {
return "MMK";
}
String value = currencyCode.trim().toUpperCase(Locale.getDefault());
if ("840".equals(value) || "USD".equals(value)) {
return "USD";
}
return "MMK";
}
private static class CurrencySettlementSummary {
int saleCount;
long saleAmount;
int preAuthCompCount;
long preAuthCompAmount;
int refundCount;
long refundAmount;
int cashAdvanceCount;
long cashAdvanceAmount;
boolean hasAnyValue() {
return saleCount > 0 || preAuthCompCount > 0 || refundCount > 0 || cashAdvanceCount > 0
|| saleAmount > 0 || preAuthCompAmount > 0 || refundAmount > 0 || cashAdvanceAmount > 0;
}
}
private String currencyCodeToText(String currencyCode) { private String currencyCodeToText(String currencyCode) {
String currencyText = "MMK"; String currencyText = "MMK";
@ -324,7 +404,7 @@ public abstract class BaseXPrint {
print2ColumnsStringNoSpace("ENTRY MODE :", PrintUtils.getInstance().getEntryType(payDetail.getCardType())); print2ColumnsStringNoSpace("ENTRY MODE :", PrintUtils.getInstance().getEntryType(payDetail.getCardType()));
print2ColumnsStringNoSpace("EXP DATE :",PrintUtils.getInstance().getFormatExpDate(payDetail.getEXPDate())); print2ColumnsStringNoSpace("EXP DATE :",PrintUtils.getInstance().getFormatExpDate(payDetail.getEXPDate()));
print2ColumnsStringNoSpace("CARD TYPE :", payDetail.getAccountType()); print2ColumnsStringNoSpace("CARD TYPE :", payDetail.getAccountType());
print2ColumnsStringNoSpace("TRACE NUM :", payDetail.getVoucherNo()); print2ColumnsStringNoSpace("TRACE NUM :", payDetail.getInvoiceNo());
if (payDetail.getCardType() != BaseCardType.MAGNETIC.getValue()) { if (payDetail.getCardType() != BaseCardType.MAGNETIC.getValue()) {
print2ColumnsStringNoSpace("CARD HOLDER:", firsLineName); print2ColumnsStringNoSpace("CARD HOLDER:", firsLineName);
@ -350,10 +430,11 @@ public abstract class BaseXPrint {
boolean isDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
if (payDetail.getTradeAnswerCode().equals("00") || payDetail.getTradeAnswerCode().equals("000")) { if (payDetail.getTradeAnswerCode().equals("00") || payDetail.getTradeAnswerCode().equals("000")) {
if (payDetail.getTransactionType() == TransactionType.CASH_ADVANCE) { if (payDetail.getTransactionType() == TransactionType.CASH_ADVANCE) {
print2ColumnsStringNoSpace("TXN AMOUNT", ":" + PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount())); print2ColumnsStringNoSpace("TXN AMOUNT", ":" + PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount(), isDecimalEnabled));
print2ColumnsStringNoSpace("TXN FEES", ":" + PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAdditionalAmount())); print2ColumnsStringNoSpace("TXN FEES", ":" + PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAdditionalAmount(), isDecimalEnabled));
} }
} }
dotBreak(); dotBreak();
@ -364,12 +445,12 @@ public abstract class BaseXPrint {
printer.appendPrnStr("MMK " + PrintUtils.getInstance().getBalanceInquiryNumberFormat(payDetail.getAmount()), fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("MMK " + PrintUtils.getInstance().getBalanceInquiryNumberFormat(payDetail.getAmount()), fontNormal, AlignEnum.LEFT,false);
} else if (payDetail.getTransactionType() == TransactionType.VOID || payDetail.getTransactionType() == TransactionType.REFUND || payDetail.getTransactionType() == TransactionType.PRE_SALE_CANCEL || payDetail.getTransactionType() == TransactionType.PRE_SALE_COMPLETE_VOID) { } else if (payDetail.getTransactionType() == TransactionType.VOID || payDetail.getTransactionType() == TransactionType.REFUND || payDetail.getTransactionType() == TransactionType.PRE_SALE_CANCEL || payDetail.getTransactionType() == TransactionType.PRE_SALE_COMPLETE_VOID) {
print2SideString("AMT:" + currencySign, "- " + PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount())); print2SideString("AMT:" + currencySign, "- " + PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount(), isDecimalEnabled));
} else if (payDetail.getTransactionType() == TransactionType.CASH_ADVANCE) { } else if (payDetail.getTransactionType() == TransactionType.CASH_ADVANCE) {
long totalAmount = payDetail.getAmount() + payDetail.getAdditionalAmount(); long totalAmount = payDetail.getAmount() + payDetail.getAdditionalAmount();
print2SideString("AMT:" + currencySign, PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount)); print2SideString("AMT:" + currencySign, PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount, isDecimalEnabled));
} else { } else {
print2SideString("AMT:" + currencySign, PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount())); print2SideString("AMT:" + currencySign, PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount(), isDecimalEnabled));
} }
dotBreak(); dotBreak();
} else { } else {
@ -446,15 +527,14 @@ public abstract class BaseXPrint {
printer.appendPrnStr("BTH NO:" + batchNum, fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("BTH NO:" + batchNum, fontNormal, AlignEnum.LEFT,false);
} else { } else {
// printer.printColumnsString(new String[]{"BATCH NO :" + batchNum, "INV NO: " + invoiceNo}, new int[]{2, 2}, new int[]{0, 2}, null); // printer.printColumnsString(new String[]{"BATCH NO :" + batchNum, "INV NO: " + invoiceNo}, new int[]{2, 2}, new int[]{0, 2}, null);
printer.appendPrnStr("BTH NO:" + batchNum + " TRACE NO:" + traceNo, fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("BTH NO:" + batchNum + " INV NO:" + traceNo, fontNormal, AlignEnum.LEFT,false);
} }
// printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false);
printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false);
printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false);
printer.appendPrnStr(transType.replace("_", " "), fontNormal, AlignEnum.CENTER,true); printer.appendPrnStr(transType.replace("_", " "), fontNormal, AlignEnum.CENTER,true);
printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false); // printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false);
printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false); // printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false);
} }
@ -496,7 +576,7 @@ public abstract class BaseXPrint {
print2ColumnsStringNoSpace("ENTRY MODE:", PrintUtils.getInstance().getEntryType(payDetail.getCardType())); print2ColumnsStringNoSpace("ENTRY MODE:", PrintUtils.getInstance().getEntryType(payDetail.getCardType()));
print2ColumnsStringNoSpace("EXP DATE :",PrintUtils.getInstance().getFormatExpDate(payDetail.getEXPDate())); print2ColumnsStringNoSpace("EXP DATE :",PrintUtils.getInstance().getFormatExpDate(payDetail.getEXPDate()));
print2ColumnsStringNoSpace("CARD TYPE :", payDetail.getAccountType()); print2ColumnsStringNoSpace("CARD TYPE :", payDetail.getAccountType());
print2ColumnsStringNoSpace("TRACE NUM :", payDetail.getVoucherNo()); print2ColumnsStringNoSpace("TRACE NUM :", payDetail.getInvoiceNo());
if (payDetail.getCardType() != BaseCardType.MAGNETIC.getValue()) { if (payDetail.getCardType() != BaseCardType.MAGNETIC.getValue()) {
print2ColumnsStringNoSpace("CARD HOLDER:", firsLineName); print2ColumnsStringNoSpace("CARD HOLDER:", firsLineName);
@ -516,26 +596,27 @@ public abstract class BaseXPrint {
print2ColumnsStringNoSpace("AID :", payDetail.getAID()); print2ColumnsStringNoSpace("AID :", payDetail.getAID());
lineBreak(); dotBreak();
// check is pin change // check is pin change
if (payDetail.getTradeAnswerCode().equals("00") || payDetail.getTradeAnswerCode().equals("000")) { if (payDetail.getTradeAnswerCode().equals("00") || payDetail.getTradeAnswerCode().equals("000")) {
boolean isDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
String currencySign = currencyCodeToText(payDetail.getCurrencyCode()); String currencySign = currencyCodeToText(payDetail.getCurrencyCode());
// CurrencyType currencySign = currencyTextToCurrencyType(payDetail.getCurrencyCode()); // CurrencyType currencySign = currencyTextToCurrencyType(payDetail.getCurrencyCode());
if (payDetail.getTransactionType() == TransactionType.BALANCE_INQUIRY) { if (payDetail.getTransactionType() == TransactionType.BALANCE_INQUIRY) {
printer.appendPrnStr("MMK " + PrintUtils.getInstance().getBalanceInquiryNumberFormat(payDetail.getAmount()), fontNormal, AlignEnum.LEFT,true); printer.appendPrnStr("MMK " + PrintUtils.getInstance().getBalanceInquiryNumberFormat(payDetail.getAmount()), fontNormal, AlignEnum.LEFT,true);
} else { } else {
print2SideString("AMOUNT:" + currencySign, PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount())); print2SideString("AMT:" + currencySign, PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount(), isDecimalEnabled));
// printer.appendPrnStr("AMOUNT:" + currencySign + " " + PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount()), fontNormal, AlignEnum.LEFT,true); // printer.appendPrnStr("AMOUNT:" + currencySign + " " + PrintUtils.getInstance().getSeparatorNumberFormat(payDetail.getAmount()), fontNormal, AlignEnum.LEFT,true);
} }
lineBreak(); dotBreak();
} else { } else {
// lineBreak(); // lineBreak();
emptyLine(1); emptyLine(1);
printer.appendPrnStr(BaseErrorCode.getCode(payDetail.getTradeAnswerCode()), fontNormal, AlignEnum.CENTER,true); printer.appendPrnStr(BaseErrorCode.getCode(payDetail.getTradeAnswerCode()), fontNormal, AlignEnum.CENTER,true);
emptyLine(1); emptyLine(1);
lineBreak(); dotBreak();
} }
emptyLine(1); emptyLine(1);
@ -545,11 +626,12 @@ public abstract class BaseXPrint {
private void printColumnString(String label, int count, long amount, boolean isNegative) { private void printColumnString(String label, int count, long amount, boolean isNegative) {
if (count > 0) { if (count > 0) {
String amountString = PrintUtils.getInstance().getSeparatorNumberFormat(amount); boolean isDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
String amountString = PrintUtils.getInstance().getSeparatorNumberFormat(amount, isDecimalEnabled);
if (isNegative) { if (isNegative) {
amountString = "-" + amountString; amountString = "-" + amountString;
} }
printer.appendPrnStr(label + countStringFormat(count) + MMK + " " + PrintUtils.getInstance().getSeparatorNumberFormat(amount), fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr(label + countStringFormat(count) + MMK + " " + amountString, fontNormal, AlignEnum.LEFT,false);
} }
} }
@ -683,6 +765,296 @@ public abstract class BaseXPrint {
} }
class TempSummary {
int saleCount, voidSaleCount, refundCount, cashOutCount;
int preAuthSaleCount, preAuthVoidCount;
int qrPayCount, qrRefundCount;
int preAuthCompCount, preAuthCompVoidCount;
long saleAmount, voidSaleAmount, refundAmount, cashOutAmount;
long preAuthSaleAmount, preAuthVoidAmount;
long qrPayAmount, qrRefundAmount;
long preAuthCompAmount, preAuthCompVoidAmount;
}
private void applyTempSummary(TempSummary summary, PayDetail item) {
int transactionType = item.getTransactionType();
long amount = item.getAmount();
if (transactionType == TransactionsType.SALE.value) {
summary.saleCount++;
summary.saleAmount += amount;
return;
}
if (transactionType == TransactionsType.VOID.value) {
summary.voidSaleCount++;
summary.voidSaleAmount += amount;
return;
}
if (transactionType == TransactionsType.REFUND.value) {
summary.refundCount++;
summary.refundAmount += amount;
return;
}
if (transactionType == TransactionsType.CASH_OUT.value) {
summary.cashOutCount++;
summary.cashOutAmount += amount;
return;
}
if (transactionType == TransactionsType.PRE_AUTH_SALE.value) {
summary.preAuthSaleCount++;
summary.preAuthSaleAmount += amount;
return;
}
if (transactionType == TransactionsType.PRE_AUTH_VOID.value) {
summary.preAuthVoidCount++;
summary.preAuthVoidAmount += amount;
return;
}
if (transactionType == TransactionsType.MMQR.value) {
summary.qrPayCount++;
summary.qrPayAmount += amount;
return;
}
if (transactionType == TransactionsType.MMQR_REFUND.value) {
summary.qrRefundCount++;
summary.qrRefundAmount += amount;
return;
}
if (transactionType == TransactionsType.PRE_AUTH_COMPLETE.value) {
summary.preAuthCompCount++;
summary.preAuthCompAmount += amount;
return;
}
if (transactionType == TransactionsType.PRE_AUTH_COMPLETE_VOID.value) {
summary.preAuthCompVoidCount++;
summary.preAuthCompVoidAmount += amount;
return;
}
String transType = item.getTransType() == null ? "" : item.getTransType().trim().toUpperCase(Locale.getDefault());
switch (transType) {
case "SALE":
summary.saleCount++;
summary.saleAmount += amount;
break;
case "VOID SALE":
case "VOID_SALE":
summary.voidSaleCount++;
summary.voidSaleAmount += amount;
break;
case "REFUND":
summary.refundCount++;
summary.refundAmount += amount;
break;
case "PRE-AUTH":
case "PRE_AUTH_SALE":
summary.preAuthSaleCount++;
summary.preAuthSaleAmount += amount;
break;
case "PREAUTH CANCELLATION":
case "PRE_AUTH_VOID":
summary.preAuthVoidCount++;
summary.preAuthVoidAmount += amount;
break;
case "CASH OUT":
case "CASH_OUT":
case "CASH_ADVANCE":
summary.cashOutCount++;
summary.cashOutAmount += amount;
break;
case "QR_PAY":
summary.qrPayCount++;
summary.qrPayAmount += amount;
break;
case "QR_REFUND":
summary.qrRefundCount++;
summary.qrRefundAmount += amount;
break;
case "PREAUTH COMPLETION":
case "PRE_AUTH_COMPLETE":
case "PREAUTH_COMP":
summary.preAuthCompCount++;
summary.preAuthCompAmount += amount;
break;
case "VOID PREAUTH COMPLETE":
case "PRE_AUTH_COMPLETE_VOID":
case "PREAUTH_COMP_VOID":
summary.preAuthCompVoidCount++;
summary.preAuthCompVoidAmount += amount;
break;
}
}
private boolean matchesSummaryHostType(PayDetail item, HostType hostType) {
if (hostType == null || item == null) {
return true;
}
int transactionType = item.getTransactionType();
if (hostType == HostType.QR) {
return transactionType == TransactionsType.MMQR.value
|| transactionType == TransactionsType.MMQR_REFUND.value;
}
if (hostType == HostType.MPU || hostType == HostType.VISA_MASTER) {
return transactionType != TransactionsType.MMQR.value
&& transactionType != TransactionsType.MMQR_REFUND.value;
}
return true;
}
protected void printTransDetailSummary(PayDetail payDetail, List<PayDetail> list) {
printTransDetailSummary(payDetail, list, null);
}
protected void printTransDetailSummary(PayDetail payDetail, List<PayDetail> list, HostType hostType) {
if (list == null || list.isEmpty()) {
printErrorBlock("NO TRANSACTION FOUND");
printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false);
return;
}
Map<String, TempSummary> currencyMap = new HashMap<>();
for (PayDetail item : list) {
if (item == null) continue;
if (!matchesSummaryHostType(item, hostType)) continue;
String currency = item.getCurrencyCode();
TempSummary s = currencyMap.get(currency);
if (s == null) {
s = new TempSummary();
currencyMap.put(currency, s);
}
applyTempSummary(s, item);
}
if (currencyMap.isEmpty()) {
printErrorBlock("NO TRANSACTION FOUND");
printer.appendPrnStr("\n", fontNormal, AlignEnum.LEFT,false);
return;
}
boolean isQrDecimalEnabled = SystemParamsOperation.getInstance().isQrDecimalEnable();
boolean isDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
for (String currency : currencyMap.keySet()) {
TempSummary data = currencyMap.get(currency);
boolean isQrHost = hostType == HostType.QR;
printer.appendPrnStr( currencyCodeToText(currency) + " " +"Transactions", fontNormal, AlignEnum.LEFT, false);
emptyLine(1);
// printer.appendPrnStr("(COUNT)TRANS", "AMOUNT(" + currencyCodeToText(currency) + ")", fontNormal, false);
print3ColumnsStringWithAlign("COUNT", "TRANS", "AMOUNT" + "(" + currencyCodeToText(currency) + ")", fontNormal, false);
if (isQrHost) {
if (data.qrPayCount > 0) {
print3ColumnsStringWithAlign("(" + data.qrPayCount + ")",
"QR PAY",
PrintUtils.getInstance().getSeparatorNumberFormat(data.qrPayAmount, isQrDecimalEnabled),
fontNormal, false);
}
if (data.qrRefundCount > 0) {
print3ColumnsStringWithAlign("(" + data.qrRefundCount + ")",
"QR REFUND",
"- " + PrintUtils.getInstance().getSeparatorNumberFormat(data.qrRefundAmount, isQrDecimalEnabled),
fontNormal, false);
}
} else {
if (data.saleCount > 0) {
print3ColumnsStringWithAlign("(" + data.saleCount + ")",
"SALES",
PrintUtils.getInstance().getSeparatorNumberFormat(data.saleAmount, isDecimalEnabled),
fontNormal, false);
}
if (data.voidSaleCount > 0) {
print3ColumnsStringWithAlign("(" + data.voidSaleCount + ")",
"VOID",
"- " + PrintUtils.getInstance().getSeparatorNumberFormat(data.voidSaleAmount, isDecimalEnabled),
fontNormal, false);
}
if (data.cashOutCount > 0) {
print3ColumnsStringWithAlign("(" + data.cashOutCount + ")",
"CASH ADV",
PrintUtils.getInstance().getSeparatorNumberFormat(data.cashOutAmount, isDecimalEnabled),
fontNormal, false);
}
if (data.preAuthSaleCount > 0) {
print3ColumnsStringWithAlign("(" + data.preAuthSaleCount + ")",
"PRE-AUTH",
PrintUtils.getInstance().getSeparatorNumberFormat(data.preAuthSaleAmount, isDecimalEnabled),
fontNormal, false);
}
if (data.preAuthVoidCount > 0) {
print3ColumnsStringWithAlign("(" + data.preAuthVoidCount + ")",
"PREAUTH VOID",
"- " + PrintUtils.getInstance().getSeparatorNumberFormat(data.preAuthVoidAmount, isDecimalEnabled),
fontNormal, false);
}
if (data.refundCount > 0) {
print3ColumnsStringWithAlign("(" + data.refundCount + ")",
"REFUND",
"- " + PrintUtils.getInstance().getSeparatorNumberFormat(data.refundAmount, isDecimalEnabled),
fontNormal, false);
}
if (data.preAuthCompCount > 0) {
print3ColumnsStringWithAlign("(" + data.preAuthCompCount + ")",
"PREAUTH COMP",
PrintUtils.getInstance().getSeparatorNumberFormat(data.preAuthCompAmount, isDecimalEnabled),
fontNormal, false);
}
}
dotBreak();
long totalAmount = isQrHost
? data.qrPayAmount - data.qrRefundAmount
: (data.saleAmount + data.cashOutAmount + data.preAuthSaleAmount + data.preAuthCompAmount)
- (data.voidSaleAmount + data.preAuthVoidAmount + data.refundAmount + data.preAuthCompVoidAmount);
printer.appendPrnStr( "TOTAL"+ " " + currencyCodeToText(currency),
PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount, isQrHost ? isQrDecimalEnabled : isDecimalEnabled),
fontNormal, false);
emptyLine(2);
}
}
/* private void backup(){ /* private void backup(){
SettleData settleData = payDetail.getSettleDataObj(); SettleData settleData = payDetail.getSettleDataObj();
@ -775,48 +1147,60 @@ public abstract class BaseXPrint {
// printer.appendPrnStr(first + " " + second + " " + third, fontNormal, AlignEnum.LEFT,false); // printer.appendPrnStr(first + " " + second + " " + third, fontNormal, AlignEnum.LEFT,false);
printer.appendPrnStr(first + " " + second + " " + third, fontNormal, AlignEnum.LEFT,isBold); printer.appendPrnStr(first + " " + second + " " + third, fontNormal, AlignEnum.LEFT,isBold);
} }
protected void dotBreak(){ protected void print3ColumnsStringWithAlign(String first, String second, String third, int font, boolean isBold){
printer.appendPrnStr(new String(new char[29]).replace("\0", "."), fontNormal, AlignEnum.LEFT, false); String fixedSizeString = String.format("%-5s", first);
printer.appendPrnStr(fixedSizeString + " " + second, third, font, isBold);
} }
protected void dotBreak(){
printer.appendPrnStr(new String(new char[29]).replace("\0", "."), fontNormal, AlignEnum.CENTER, false);
}
class CurrencySummary {
long total = 0;
int count = 0;
}
protected void printTransDetailReport(List<PayDetail> lists, HostType hostType) { protected void printTransDetailReport(List<PayDetail> lists, HostType hostType) {
// ✅ Summary holder (total + count per currency)
if (hostType == HostType.MPU || hostType == HostType.VISA_MASTER) { class CurrencySummary {
// Use the same line-by-line style as QR detail report long total = 0;
} else if (hostType == HostType.QR) { int count = 0;
// print2ColumnsString("PAYMENT NAME", "");
// print2ColumnsString("DATE", "TIME");
// print2ColumnsString("TRANSACTION", "TRACE NO");
// print2ColumnsString("TRXN ID", "");
// print2ColumnsString("AMOUNT", "");
} }
Map<String, CurrencySummary> currencyMap = new HashMap<>();
// breakingLine();
long totalAmount = 0;
for (PayDetail pay : lists) { for (PayDetail pay : lists) {
boolean isNeedMinusSign = pay.getTransactionType() == TransactionsType.VOID.value || pay.getTransactionType() == TransactionsType.REFUND.value || pay.getTransactionType() == TransactionsType.MMQR_REFUND.value;
boolean isDecimalEnabled = SystemParamsOperation.getInstance().isQrDecimalEnable();
boolean isNeedMinusSign =
pay.getTransactionType() == TransactionsType.VOID.value ||
pay.getTransactionType() == TransactionsType.REFUND.value ||
pay.getTransactionType() == TransactionsType.MMQR_REFUND.value;
boolean isDecimalEnabledQr = SystemParamsOperation.getInstance().isQrDecimalEnable();
String currency = currencyCodeToText(pay.getCurrencyCode());
// =============================
// PRINT DETAIL
// =============================
if (hostType == HostType.MPU || hostType == HostType.VISA_MASTER) { if (hostType == HostType.MPU || hostType == HostType.VISA_MASTER) {
boolean isDecimalEnabledCard = SystemParamsOperation.getInstance().getDecimalEnable(); boolean isDecimalEnabledCard = SystemParamsOperation.getInstance().getDecimalEnable();
printString("CARD TYPE:" + pay.getAccountType()); printString("CARD TYPE:" + pay.getAccountType());
printString("CARD NO :" + PrintUtils.getInstance().maskCardNumberPciDss(pay.getCardNo())); printString("CARD NO :" + PrintUtils.getInstance().maskCardNumberPciDss(pay.getCardNo()));
printString("TRACE NO :" + pay.getVoucherNo()); printString("INV NO :" + pay.getVoucherNo());
printString("RRN :" + pay.getReferNo()); printString("RRN :" + pay.getReferNo());
printString("DATE :" + POSUtil.getInstance().formatDisplayDate(pay.getTransDate()) + " " + pay.getTransTime()); printString("DATE :" + POSUtil.getInstance().formatDisplayDate(pay.getTransDate()));
printString(" " + pay.getTransTime());
printString("TYPE :" + pay.getTransType().replace("_", " ")); printString("TYPE :" + pay.getTransType().replace("_", " "));
printString("AMOUNT :" + printString("AMOUNT :" +
(isNeedMinusSign (isNeedMinusSign
? "-" + PrintUtils.getInstance() ? "-" + PrintUtils.getInstance().getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabledCard)
.getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabledCard) : PrintUtils.getInstance().getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabledCard))
: PrintUtils.getInstance() + " " + currency);
.getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabledCard))
+ " " + "MMK");
dotBreak(); dotBreak();
} else if (hostType == HostType.QR) { } else if (hostType == HostType.QR) {
@ -824,64 +1208,91 @@ public abstract class BaseXPrint {
printString("TRANS ID:" + pay.getQrTransId()); printString("TRANS ID:" + pay.getQrTransId());
printString("STATUS :" + pay.getTC()); printString("STATUS :" + pay.getTC());
printString("SOURCE :" + printString("SOURCE :" +
(pay.getTransactionType() == TransactionsType.MMQR_REFUND.value (pay.getTransactionType() == TransactionsType.MMQR_REFUND.value
? "QR PAYMENT" ? "QR PAYMENT"
: pay.getCustomerMobile()) : pay.getCustomerMobile()));
); printString("DATE :" + POSUtil.getInstance().formatDisplayDate(pay.getTransDate()));
// printString("TXN NAME:" + pay.getTransType().replace("_", " ")); printString(" " + pay.getTransTime());
printString("DATE :" + POSUtil.getInstance().formatDisplayDate(pay.getTransDate()) + " " + pay.getTransTime()); printString("INV NO :" + pay.getVoucherNo());
printString("TRACE NO:" + pay.getVoucherNo());
if (pay.getTransactionType() == TransactionsType.MMQR_REFUND.value) { if (pay.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
printString("RRN :" + pay.getReferNo()); printString("RRN :" + pay.getReferNo());
} }
printString("AMOUNT :" + printString("AMOUNT :" +
(isNeedMinusSign (isNeedMinusSign
? "-" + PrintUtils.getInstance() ? "-" + PrintUtils.getInstance().getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabledQr)
.getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabled) : PrintUtils.getInstance().getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabledQr))
: PrintUtils.getInstance() + " " + currency);
.getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabled))
+ " " +"MMK");
dotBreak(); dotBreak();
// if (pay.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
// print2ColumnsString("QR PAYMENT", "");
// } else {
// print2ColumnsString(pay.getCustomerMobile(), "");
// }
// print2ColumnsString(pay.getTransDate(), pay.getTransTime());
// print2ColumnsString(pay.getTransType().replace("_", " "), pay.getVoucherNo());
// if (pay.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
// print2ColumnsString(pay.getReferNo() + "(RRN)", "");
// print2ColumnsString(isNeedMinusSign ? "-" + PrintUtils.getInstance().getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabled) : "" + PrintUtils.getInstance().getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabled), "");
// } else {
// print2ColumnsString(pay.getQrTransId(), "");
// print2ColumnsString(isNeedMinusSign ? "-" + PrintUtils.getInstance().getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabled) : "" + PrintUtils.getInstance().getSeparatorNumberFormat(pay.getAmount(), isDecimalEnabled) , "");
// }
} }
emptyLine(1); emptyLine(1);
// =============================
// ✅ ACCUMULATE TOTAL + COUNT PER CURRENCY
// =============================
CurrencySummary summary = currencyMap.getOrDefault(currency, new CurrencySummary());
if (isNeedMinusSign) { if (isNeedMinusSign) {
totalAmount -= pay.getAmount(); summary.total -= pay.getAmount();
} else { } else {
totalAmount += pay.getAmount(); summary.total += pay.getAmount();
} }
summary.count++; // ✅ count per currency
currencyMap.put(currency, summary);
} }
// =============================
// PRINT SUMMARY
// =============================
if (hostType == HostType.MPU || hostType == HostType.VISA_MASTER) { if (hostType == HostType.MPU || hostType == HostType.VISA_MASTER) {
boolean isDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable(); boolean isDecimalEnabled = SystemParamsOperation.getInstance().getDecimalEnable();
print2ColumnsString("CARD", ""); print2ColumnsString("CARD", "");
print3ColumnsString("TYPE ", "COUNT", "AMOUNT"); print3ColumnsStringWithAlign("TYPE ", "COUNT", "AMOUNT", fontNormal, true);
print3ColumnsString("CARD", " " + countStringFormat(lists.size()), "MMK " + PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount, isDecimalEnabled), true);
for (Map.Entry<String, CurrencySummary> entry : currencyMap.entrySet()) {
String currency = entry.getKey();
CurrencySummary summary = entry.getValue();
print3ColumnsStringWithAlign(
"CARD",
" " + countStringFormat(summary.count),
currency + " " + PrintUtils.getInstance()
.getSeparatorNumberFormat(summary.total, isDecimalEnabled),
fontNormal,
false
);
}
} else if (hostType == HostType.QR) { } else if (hostType == HostType.QR) {
boolean isDecimalEnabled = SystemParamsOperation.getInstance().isQrDecimalEnable(); boolean isDecimalEnabled = SystemParamsOperation.getInstance().isQrDecimalEnable();
print2ColumnsString("PAYMENT", ""); print2ColumnsString("PAYMENT", "");
print3ColumnsString("TYPE ", "COUNT", "AMOUNT"); print3ColumnsStringWithAlign("TYPE ", "COUNT", "AMOUNT", fontNormal, true);
// emptyLine(1);
print3ColumnsString("QR PAY", " "+ countStringFormat(lists.size()), "MMK " + PrintUtils.getInstance().getSeparatorNumberFormat(totalAmount, isDecimalEnabled), true); for (Map.Entry<String, CurrencySummary> entry : currencyMap.entrySet()) {
String currency = entry.getKey();
CurrencySummary summary = entry.getValue();
print3ColumnsStringWithAlign(
"QR PAY",
" " + countStringFormat(summary.count),
currency + " " + PrintUtils.getInstance()
.getSeparatorNumberFormat(summary.total, isDecimalEnabled),
fontNormal,
false
);
}
} }
// emptyLine(2);
} }
protected void printQRSettlementTransDetail(List<QRSettleData> lists) { protected void printQRSettlementTransDetail(List<QRSettleData> lists) {
@ -1162,6 +1573,7 @@ public abstract class BaseXPrint {
String transType = payDetail.getTransType(); String transType = payDetail.getTransType();
String batchNum = ""; String batchNum = "";
String traceNum = payDetail.getVoucherNo(); String traceNum = payDetail.getVoucherNo();
boolean isDuelCurrency = SystemParamsOperation.getInstance().getDuelCurrencyStatus();
String currencySign = currencyCodeToText(payDetail.getCurrencyCode()); String currencySign = currencyCodeToText(payDetail.getCurrencyCode());
boolean isSettlement = payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value; boolean isSettlement = payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value;
@ -1176,7 +1588,7 @@ public abstract class BaseXPrint {
if (payDetail.getTransactionType() == TransactionsType.MMQR.value && payDetail.getQrTransStatus() == 1) { if (payDetail.getTransactionType() == TransactionsType.MMQR.value && payDetail.getQrTransStatus() == 1) {
printer.appendPrnStr("TRACE NO :" + traceNum , fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("TRACE NO :" + traceNum , fontNormal, AlignEnum.LEFT,false);
} else if (!payDetail.getTransType().equals(SETTLEMENT) && !payDetail.getTransType().equals(SUMMARY) && payDetail.getTransactionType() != TransactionsType.MMQR_REFUND.value && payDetail.getTransactionType() != TransactionsType.MMQR.value) { } else if (!payDetail.getTransType().equals(SETTLEMENT) && !payDetail.getTransType().equals(SUMMARY) && payDetail.getTransactionType() != TransactionsType.MMQR_REFUND.value && payDetail.getTransactionType() != TransactionsType.MMQR.value) {
printer.appendPrnStr("BTH NO:" + batchNum + " INV NO:" + invoiceNo, fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("BTH NO:" + batchNum + " INV NO:" + traceNum, fontNormal, AlignEnum.LEFT,false);
} else if (payDetail.getTransType().equals(SUMMARY)) { } else if (payDetail.getTransType().equals(SUMMARY)) {
printer.appendPrnStr("HOST :" + HOST_NAME_MPU + "", fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("HOST :" + HOST_NAME_MPU + "", fontNormal, AlignEnum.LEFT,false);
} }
@ -1186,8 +1598,16 @@ public abstract class BaseXPrint {
if (payDetail.getTransactionType() == TransactionsType.MMQR.value || payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value){ if (payDetail.getTransactionType() == TransactionsType.MMQR.value || payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value){
printer.appendPrnStr("SHORT CODE :" + payDetail.getMerchantNo(), fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("SHORT CODE :" + payDetail.getMerchantNo(), fontNormal, AlignEnum.LEFT,false);
}else{ }else{
printer.appendPrnStr("MID :" + payDetail.getMerchantNo(), fontNormal, AlignEnum.LEFT,false);
printer.appendPrnStr("TID :" + payDetail.getTerminalNo(), fontNormal, AlignEnum.LEFT,false); if(isSettlement && isDuelCurrency){
printer.appendPrnStr("MID :" + safe(SystemParamsOperation.getInstance().getMerchantId()), fontNormal, AlignEnum.LEFT, false);
printer.appendPrnStr("TID :" + safe(SystemParamsOperation.getInstance().getTerminalId()), fontNormal, AlignEnum.LEFT, false);
printer.appendPrnStr("MID :" + safe(SystemParamsOperation.getInstance().getThirdHostMerchantId()), fontNormal, AlignEnum.LEFT, false);
printer.appendPrnStr("TID :" + safe(SystemParamsOperation.getInstance().getThirdHostTerminalId()), fontNormal, AlignEnum.LEFT, false);
}else{
printer.appendPrnStr("MID :" + payDetail.getMerchantNo(), fontNormal, AlignEnum.LEFT,false);
printer.appendPrnStr("TID :" + payDetail.getTerminalNo(), fontNormal, AlignEnum.LEFT,false);
}
} }
if(isSettlement) { if(isSettlement) {
@ -1257,7 +1677,7 @@ public abstract class BaseXPrint {
// printer.appendPrnStr("INV NO :" + invoiceNo , fontNormal, AlignEnum.LEFT,false); // printer.appendPrnStr("INV NO :" + invoiceNo , fontNormal, AlignEnum.LEFT,false);
printer.appendPrnStr("TRACE NO :" + traceNum , fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("TRACE NO :" + traceNum , fontNormal, AlignEnum.LEFT,false);
} else if (!payDetail.getTransType().equals(SETTLEMENT) && !payDetail.getTransType().equals(SUMMARY) && payDetail.getTransactionType() != TransactionsType.MMQR_REFUND.value && payDetail.getTransactionType() != TransactionsType.MMQR.value) { } else if (!payDetail.getTransType().equals(SETTLEMENT) && !payDetail.getTransType().equals(SUMMARY) && payDetail.getTransactionType() != TransactionsType.MMQR_REFUND.value && payDetail.getTransactionType() != TransactionsType.MMQR.value) {
// printer.appendPrnStr("BTH NO :" + batchNum + " INV NO:" + invoiceNo, fontNormal, AlignEnum.LEFT,false); // printer.appendPrnStr("BTH NO :" + batchNum + " INV NO:" + traceNum, fontNormal, AlignEnum.LEFT,false);
} else if (payDetail.getTransType().equals(SUMMARY)) { } else if (payDetail.getTransType().equals(SUMMARY)) {
printer.appendPrnStr("HOST :" + HOST_NAME_MPU + "", fontNormal, AlignEnum.LEFT,false); printer.appendPrnStr("HOST :" + HOST_NAME_MPU + "", fontNormal, AlignEnum.LEFT,false);
} }
@ -1316,18 +1736,19 @@ public abstract class BaseXPrint {
protected void printTerminalConfiguration() { protected void printTerminalConfiguration() {
SystemParamsOperation sp = SystemParamsOperation.getInstance(); SystemParamsOperation sp = SystemParamsOperation.getInstance();
// ---------- PRIMARY HOST ---------- // ---------- PRIMARY HOST ----------
printer.appendPrnStr("PRIMARY HOST", fontNormal, AlignEnum.LEFT, true); printer.appendPrnStr("PRIMARY HOST", fontNormal, AlignEnum.LEFT, true);
printer.appendPrnStr("Name : " + sp.getHostName(), fontNormal, AlignEnum.LEFT, false); printer.appendPrnStr("Name : " + safe(sp.getHostName()), fontNormal, AlignEnum.LEFT, false);
printer.appendPrnStr("TID : " + sp.getTerminalId(), fontNormal, AlignEnum.LEFT, false); printer.appendPrnStr("TID : " + safe(sp.getTerminalId()), fontNormal, AlignEnum.LEFT, false);
printer.appendPrnStr("MID : " + sp.getMerchantId(), fontNormal, AlignEnum.LEFT, false); printer.appendPrnStr("MID : " + safe(sp.getMerchantId()), fontNormal, AlignEnum.LEFT, false);
String[] ipPort = splitIpAndPort(sp.getIpAddress()); String[] ipPort = splitIpAndPort(sp.getIpAddress());
printer.appendPrnStr("Primary Ip : " + ipPort[0], fontNormal, AlignEnum.LEFT, false); printer.appendPrnStr("Primary IP : " + ipPort[0], fontNormal, AlignEnum.LEFT, false);
printer.appendPrnStr("Primary Port : " + ipPort[1], fontNormal, AlignEnum.LEFT, false); printer.appendPrnStr("Primary Port : " + ipPort[1], fontNormal, AlignEnum.LEFT, false);
String[] secIpPort = splitIpAndPort(sp.getSecIpAddress()); String[] secIpPort = splitIpAndPort(sp.getSecIpAddress());
printer.appendPrnStr("Secondary Ip : " + secIpPort[0], fontNormal, AlignEnum.LEFT, false); printer.appendPrnStr("Secondary IP : " + secIpPort[0], fontNormal, AlignEnum.LEFT, false);
printer.appendPrnStr("Secondary Port: " + secIpPort[1], fontNormal, AlignEnum.LEFT, false); printer.appendPrnStr("Secondary Port: " + secIpPort[1], fontNormal, AlignEnum.LEFT, false);
printer.appendPrnStr("Currency Code : " + sp.getCurrencyType(), fontNormal, AlignEnum.LEFT, false); printer.appendPrnStr("Currency : " + normalizeHostCurrency(sp.getCurrencyType() == null ? "" : sp.getCurrencyType().toString()), fontNormal, AlignEnum.LEFT, false);
dotBreak(); dotBreak();
// ---------- SECONDARY HOST (optional) ---------- // ---------- SECONDARY HOST (optional) ----------
if (!TextUtils.isEmpty(sp.getSecHostName())) { if (!TextUtils.isEmpty(sp.getSecHostName())) {

View File

@ -20,6 +20,8 @@ public interface PrintX {
void printSmileSummaryReport(PayDetail payDetail, HostType hostType, PrintXStatus printXStatus); void printSmileSummaryReport(PayDetail payDetail, HostType hostType, PrintXStatus printXStatus);
void printSmileSummaryReport(PayDetail payDetail, List<PayDetail> list, HostType hostType, PrintXStatus printXStatus);
void printSmileSettlementReport(PayDetail payDetail,PrintXStatus printXStatus); void printSmileSettlementReport(PayDetail payDetail,PrintXStatus printXStatus);
void printQRSettlementReport(PayDetail payDetail, List<QRSettleData> list, PrintXStatus printXStatus); void printQRSettlementReport(PayDetail payDetail, List<QRSettleData> list, PrintXStatus printXStatus);

View File

@ -222,6 +222,8 @@ public class PrintXImpl extends BaseXPrint implements PrintX {
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override @Override
public void printDetailReport(PayDetail payDetail, List<PayDetail> lists, HostType hostType,PrintXStatus printXStatus) { public void printDetailReport(PayDetail payDetail, List<PayDetail> lists, HostType hostType,PrintXStatus printXStatus) {
@ -431,7 +433,6 @@ public class PrintXImpl extends BaseXPrint implements PrintX {
this.callbackStatus = printXStatus; this.callbackStatus = printXStatus;
try { try {
// LogUtil.d(TAG, payDetail.getSettleDataObj().toString()); // LogUtil.d(TAG, payDetail.getSettleDataObj().toString());
setHeight(0x12); setHeight(0x12);
printLogo(); printLogo();
printMerchantHeader(); printMerchantHeader();
@ -447,6 +448,21 @@ public class PrintXImpl extends BaseXPrint implements PrintX {
} }
} }
@Override
public void printSmileSummaryReport(PayDetail payDetail, List<PayDetail> list, HostType hostType, PrintXStatus printXStatus) {
this.callbackStatus = printXStatus;
try {
setHeight(0x12);
printLogo();
printMerchantHeader();
printTranHeader("SUMMARY REPORT");
printTransDetailSummary(payDetail, list, hostType);
startPrintNex();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override @Override
public void printTerminalConfig(PrintXStatus printXStatus) { public void printTerminalConfig(PrintXStatus printXStatus) {
this.callbackStatus = printXStatus; this.callbackStatus = printXStatus;

View File

@ -59,6 +59,9 @@ public class PrintXReceipt {
public void printSmileSummaryReport(PayDetail payDetail, HostType hostType, PrintXStatus printXStatus) { public void printSmileSummaryReport(PayDetail payDetail, HostType hostType, PrintXStatus printXStatus) {
printX.printSmileSummaryReport(payDetail, hostType, printXStatus); printX.printSmileSummaryReport(payDetail, hostType, printXStatus);
} }
public void printSmileSummaryReport(PayDetail payDetail,List<PayDetail> list, HostType hostType, PrintXStatus printXStatus) {
printX.printSmileSummaryReport(payDetail, list, hostType, printXStatus);
}
public void printTerminalHostConfig(PrintXStatus printXStatus){ public void printTerminalHostConfig(PrintXStatus printXStatus){
printX.printTerminalConfig(printXStatus); printX.printTerminalConfig(printXStatus);

View File

@ -434,6 +434,7 @@ public class TransactionsOperation {
} else { } else {
boolean equals = TextUtils.equals(resultStr, Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, Constant.ANSWER_CODE_APPROVED); boolean equals = TextUtils.equals(resultStr, Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, Constant.ANSWER_CODE_APPROVED);
EmvOnlineResultEntity emvOnlineResult = new EmvOnlineResultEntity(); EmvOnlineResultEntity emvOnlineResult = new EmvOnlineResultEntity();
emvOnlineResult.setRejCode("00");
// MsgField field38,field39,field55; // MsgField field38,field39,field55;
// if (resp != null) { // if (resp != null) {
// field38 = resp.get("F038"); // field38 = resp.get("F038");
@ -455,7 +456,10 @@ public class TransactionsOperation {
// } // }
// //
// } // }
if(equals) { if(equals) {
emvOnlineResult.setRejCode("00");
emvOnlineResult.setRecvField55(null);
importOnlineProcessStatus(SdkResult.Success,emvOnlineResult); importOnlineProcessStatus(SdkResult.Success,emvOnlineResult);
} else { } else {
importOnlineProcessStatus(SdkResult.Fail,emvOnlineResult); importOnlineProcessStatus(SdkResult.Fail,emvOnlineResult);

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