diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index d0d4139..8e60dc8 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -13,7 +13,6 @@
-
diff --git a/app/build.gradle b/app/build.gradle
index 66c899c..c9f111d 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -204,7 +204,7 @@ dependencies {
// ECR Dependencies - Modern ECR Client Library
// implementation project(path: ':ecr-client-lib')
- implementation project(path: ':ecr-service-lib')
+// implementation project(path: ':ecr-service-lib')
// Core Libraries
implementation project(path: ':paylibs')
diff --git a/app/src/main/java/com/utsmm/kbz/MainActivity.java b/app/src/main/java/com/utsmm/kbz/MainActivity.java
index 475a69d..27cebfc 100644
--- a/app/src/main/java/com/utsmm/kbz/MainActivity.java
+++ b/app/src/main/java/com/utsmm/kbz/MainActivity.java
@@ -4,6 +4,7 @@ import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.drawerlayout.widget.DrawerLayout;
+import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
@@ -471,58 +472,87 @@ public class MainActivity extends AppCompatActivity implements
private void handleAutoSettlementIntent(Intent intent) {
if (intent == null) return;
-
- // Handle regular auto settlement
- boolean auto = intent.getBooleanExtra("AUTO_SETTLEMENT", false);
- if (auto) {
+
+ boolean hasPOS = intent.getBooleanExtra("AUTO_SETTLEMENT", false);
+ boolean hasQR = intent.getBooleanExtra("AUTO_QR_SETTLEMENT", false);
+
+ if (hasPOS) {
PayDetail payDetail = (PayDetail) intent.getSerializableExtra("EXTRA_PAY_DETAIL");
if (payDetail != null) {
-
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT);
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount()));
+
try {
navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) {
LogUtil.e(TAG, "Navigation error: " + e.getMessage());
}
+
+ // If QR also exists, trigger it AFTER POS result is done
+ if (hasQR) {
+ navigateToQRSettlementAfterPOS(intent);
+ }
+ } else {
+ // POS had no data, go straight to QR if available
+ if (hasQR) {
+ handleQRSettlement(intent);
+ }
}
- 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 qrTransList = (List) intent.getSerializableExtra("QR_TRANS_LIST");
+ }
- // Create QR settlement PayDetail
- 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());
+ private void navigateToQRSettlementAfterPOS(Intent intent) {
+ // Observe transactionResultFragment's completion via ViewModel
+ // When POS result screen signals "done" (print complete / user dismissed),
+ // then navigate to QR result
+ sharedViewModel.onSettlementResultDone.observe(this, new Observer() {
+ @Override
+ public void onChanged(Boolean done) {
+ if (done != null && done) {
+ // Remove observer so it only fires once
+ sharedViewModel.onSettlementResultDone.removeObserver(this);
+ // Reset flag
+ sharedViewModel.onSettlementResultDone.postValue(false);
+ // Now navigate to QR
+ handleQRSettlement(intent);
+ }
}
+ });
+ }
+
+ private void handleQRSettlement(Intent intent) {
+ int qrSaleCount = intent.getIntExtra("QR_SALE_COUNT", 0);
+ long qrSaleAmount = intent.getLongExtra("QR_SALE_AMOUNT", 0L);
+ int qrRefundCount = intent.getIntExtra("QR_REFUND_COUNT", 0);
+ long qrRefundAmount = intent.getLongExtra("QR_REFUND_AMOUNT", 0L);
+ long totalAmount = intent.getLongExtra("QR_TOTAL_AMOUNT", 0L);
+ List qrTransList = (List) 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());
}
}
diff --git a/app/src/main/java/com/utsmm/kbz/MainFragment.java b/app/src/main/java/com/utsmm/kbz/MainFragment.java
index 0840b7c..7410bee 100644
--- a/app/src/main/java/com/utsmm/kbz/MainFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/MainFragment.java
@@ -29,9 +29,11 @@ import com.denzcoskun.imageslider.constants.ScaleTypes;
import com.denzcoskun.imageslider.models.SlideModel;
import com.nexgo.oaf.apiv3.emv.AidEntity;
import com.nexgo.oaf.apiv3.emv.CapkEntity;
-import com.pos.connection.bridge.binder.ECRConstant;
+//import com.pos.connection.bridge.binder.ECRConstant;
import com.utsmm.kbz.util.MockData;
+//import com.utsmm.kbz.util.ecr.ModernECRFactory;
+//import com.utsmm.kbz.util.ecr.ModernECRManager;
import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
@@ -316,8 +318,8 @@ public class MainFragment extends DataBindingFragment {
if (checkECRServiceAppExistOrNot()) {
// Initialize Modern ECR Manager
// modernECRManager.init();
-//
-// // Observe navigation requests
+////
+//// // Observe navigation requests
// modernECRManager.getNavigationRequest().observe(getViewLifecycleOwner(), destinationId -> {
// if (destinationId != null) {
// delayFunctionCall(() -> isRouteValidAndNavigateToRoute(destinationId));
diff --git a/app/src/main/java/com/utsmm/kbz/service/AutoSettleService.java b/app/src/main/java/com/utsmm/kbz/service/AutoSettleService.java
index 2e6563f..85a488d 100644
--- a/app/src/main/java/com/utsmm/kbz/service/AutoSettleService.java
+++ b/app/src/main/java/com/utsmm/kbz/service/AutoSettleService.java
@@ -20,6 +20,7 @@ import com.google.gson.Gson;
import com.utsmm.kbz.MainActivity;
import com.utsmm.kbz.util.EReceiptUtil;
+import com.utsmm.kbz.util.enums.TransactionStatus;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmm.kbz.BuildConfig;
@@ -34,6 +35,8 @@ import io.reactivex.rxjava3.schedulers.Schedulers;
import retrofit2.HttpException;
import com.utsmyanmar.paylibs.Constant;
+import com.utsmyanmar.paylibs.batch_upload.BatchListener;
+import com.utsmyanmar.paylibs.batch_upload.BatchUploadProcess;
import com.utsmyanmar.paylibs.isobuilder.ISOMode;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion;
@@ -44,6 +47,8 @@ import com.utsmyanmar.paylibs.model.SettleData;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.network.ISOCallback;
import com.utsmyanmar.paylibs.network.ISOSocket;
+import com.utsmyanmar.paylibs.sign_on.EchoTestProcess;
+import com.utsmyanmar.paylibs.sign_on.SignOnListener;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.MessageType;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
@@ -73,15 +78,26 @@ public class AutoSettleService extends Service {
// Flags to prevent infinite loops
private boolean regularSettlementCompleted = false;
private boolean qrSettlementCompleted = false;
+
+ private boolean posHasData = false; // true = POS actually ran and has result
+ private boolean qrHasData = false; // true = QR actually ran and has result
// Observers to keep reference for cleanup
- private Observer> regularSettlementObserver;
- private Observer> qrSettlementObserver;
+ private Observer> regularSettlementObserver;
+ private Observer> qrSettlementObserver;
+ private int i = 0;
+
+ private boolean flag = false;
@Inject
Repository repository;
+ private PayDetail pendingPayDetail = null;
+ private Bundle pendingQrData = null;
+ private boolean posSettlementReady = false;
+ private boolean qrSettlementReady = false;
+ ArrayList payDetails = new ArrayList<>();
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
@@ -188,6 +204,10 @@ public class AutoSettleService extends Service {
if (regularSettlementCompleted) {
return;
}
+
+ payDetails.clear();
+ payDetails.addAll(list);
+
regularSettlementCompleted = true;
repository.getSettlementPOS().removeObserver(this);
@@ -225,7 +245,13 @@ public class AutoSettleService extends Service {
String bitmap = BitmapConfig.BPC_SETTLEMENT;
payDetail.setTransType(TransactionsType.SETTLEMENT.name);
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());
SettleData settleData = new SettleData(
@@ -245,6 +271,14 @@ public class AutoSettleService extends Service {
} else {
settlementData = "C" + String.format(Locale.getDefault(), "%012d", totalAmount);
}
+
+ if(totalAmount == 0 && (saleCount == 0 || preCount == 0 || refundCount == 0 || caCount == 0)) {
+ posSettlementReady = true;
+ posHasData = false;
+ checkAndLaunch();
+ checkIfBothSettlementsComplete();
+ return;
+ }
payDetail.setSettleData(settlementData);
payDetail.setAmount(totalAmount);
@@ -269,7 +303,7 @@ public class AutoSettleService extends Service {
if (TextUtils.equals(resultStr, Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, Constant.ANSWER_CODE_APPROVED)) {
payDetail.setIsNeedReversal(false);
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
- payDetail.setIsNeedReversal(true);
+ payDetail.setIsNeedReversal(!flag);
}
}
}
@@ -284,34 +318,25 @@ public class AutoSettleService extends Service {
public void onComplete() {
LogUtil.d(TAG, "Auto settlement transaction completed successfully");
- if (list != null && !list.isEmpty()) {
- for (PayDetail p : list) {
- repository.deletePayDetail(p);
+ if(payDetail.getIsNeedReversal()) {
+ flag = true;
+ batchUploadProcess();
+ } else {
+
+ flag = false;
+
+ if (!list.isEmpty()) {
+ for (PayDetail p : list) {
+ repository.deletePayDetail(p);
+ }
}
+ repository.insertPayDetail(payDetail);
+
+ networkCutOver(payDetail);
+
}
- repository.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);
}
+ private void batchUploadProcess() {
+
+ if(payDetails == null || payDetails.isEmpty()){
+ regularSettlementCompleted = false;
+ performSettlement();
+ return;
+ }
+
+ PayDetail payDetail = payDetails.get(i);
+ TradeData tradeData = new TradeData();
+ tradeData.setPayDetail(payDetail);
+ BatchUploadProcess.getInstance().enqueue(tradeData).startBatchUpload(new BatchListener() {
+ @Override
+ public void onSuccessBatch() {
+
+ if (i < payDetails.size() - 1) {
+ LogUtil.d(TAG, "Pay detail Size:" + payDetails.size());
+ LogUtil.d(TAG, "Count value:" + i);
+ i++;
+ batchUploadProcess();
+ } else {
+ regularSettlementCompleted = false;
+ performSettlement();
+ }
+
+ LogUtil.e(TAG, "Batch Upload Success");
+ }
+
+ @Override
+ public void onFailBatch() {
+ LogUtil.e(TAG, "Batch Upload Fail");
+ }
+ });
+ }
+
private void performQRSettlement() {
if (qrSettlementCompleted) {
return;
@@ -365,6 +425,9 @@ public class AutoSettleService extends Service {
}
} catch (IllegalStateException e) {
LogUtil.e(TAG, "QR Auto Settlement: Database cursor error - likely due to large data size: " + e);
+ qrSettlementReady = true;
+ qrHasData = false;
+ checkAndLaunch();
checkIfBothSettlementsComplete();
return;
}
@@ -422,19 +485,24 @@ public class AutoSettleService extends Service {
qrData.putLong("QR_TOTAL_AMOUNT", totalAmount);
qrData.putSerializable("QR_TRANS_LIST", qrTransactionsList);
// 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) {
LogUtil.e(TAG, "Error launching app for QR settlement: " + e.getMessage());
+ qrHasData = false;
e.printStackTrace();
}
LogUtil.d(TAG, "QR Auto Settlement completed successfully");
} else {
LogUtil.d(TAG, "No QR transactions found for auto settlement");
+ qrHasData = false;
}
}
-
+ qrSettlementReady = true;
+ checkAndLaunch();
checkIfBothSettlementsComplete();
}
};
@@ -480,69 +548,120 @@ public class AutoSettleService extends Service {
}
- private void launchAppWithSettlementResult(String settlementType,
- PayDetail payDetail,
- Bundle qrData) {
+ private void networkCutOver(PayDetail payDetail) {
+ EchoTestProcess.getInstance().enqueueCutOver().startSignOn(new SignOnListener() {
+ @Override
+ public void onSuccessSignOn() {
+
+ pendingPayDetail = payDetail;
+ posHasData = true;
+ posSettlementReady = true;
+ checkAndLaunch();
+ checkIfBothSettlementsComplete();
+
+ }
+
+ @Override
+ public void onFailureSignOn(Integer resultCode) {
+ LogUtil.d(TAG,"Failure Cut Over message: "+resultCode);
+ // POS done but cutover failed — still mark ready
+ posSettlementReady = true;
+ posHasData = false;
+ checkAndLaunch();
+ checkIfBothSettlementsComplete();
+ }
+
+ @Override
+ public void onNetworkFailSignOn(String message) {
+ LogUtil.d(TAG,"Network Fail Cut Over message: "+message);
+ posSettlementReady = true;
+ posHasData = false;
+ checkAndLaunch();
+ checkIfBothSettlementsComplete();
+
+ }
+ });
+ }
+
+ private void checkAndLaunch() {
+ // !!!! need to add flag, if don't want both at once
+ if (!posSettlementReady || !qrSettlementReady) {
+ LogUtil.d(TAG, "Waiting for both settlements... POS=" + posSettlementReady + " QR=" + qrSettlementReady);
+ return;
+ }
+
+ LogUtil.d(TAG, "Both settlements ready. POS has data=" + posHasData + ", QR has data=" + qrHasData);
+
+ if (!posHasData && !qrHasData) {
+ LogUtil.d(TAG, "No settlement data to display");
+ return;
+ }
+
+ launchMainActivity();
+ }
+
+ private void launchMainActivity() {
try {
Intent launchIntent = new Intent(this, MainActivity.class);
- launchIntent.putExtra(settlementType, true);
-
- if ("AUTO_SETTLEMENT".equals(settlementType) && payDetail != null) {
+ launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_CLEAR_TOP |
+ Intent.FLAG_ACTIVITY_SINGLE_TOP);
+
+ if (posHasData && pendingPayDetail != null) {
+ launchIntent.putExtra("AUTO_SETTLEMENT", true);
launchIntent.putExtra("EXTRA_TRANSACTION_TYPE", TransactionsType.SETTLEMENT.value);
- launchIntent.putExtra("EXTRA_PAY_DETAIL", payDetail);
- } else if ("AUTO_QR_SETTLEMENT".equals(settlementType) && qrData != null) {
- launchIntent.putExtra("EXTRA_TRANSACTION_TYPE", TransactionsType.MMQR_SETTLEMENT.value);
- launchIntent.putExtras(qrData);
+ launchIntent.putExtra("EXTRA_PAY_DETAIL", pendingPayDetail);
+ }
+
+ if (qrHasData && pendingQrData != null) {
+ launchIntent.putExtra("AUTO_QR_SETTLEMENT", true);
+ launchIntent.putExtra("EXTRA_QR_TRANSACTION_TYPE", TransactionsType.MMQR_SETTLEMENT.value);
+ launchIntent.putExtras(pendingQrData);
}
PendingIntent pendingIntent = PendingIntent.getActivity(
- this,
- (int) System.currentTimeMillis(),
- launchIntent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
+ this,
+ (int) System.currentTimeMillis(),
+ launchIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
- "SETTLEMENT_COMPLETE",
- "Settlement Complete",
- NotificationManager.IMPORTANCE_HIGH
- );
+ "SETTLEMENT_COMPLETE", "Settlement Complete", NotificationManager.IMPORTANCE_HIGH);
channel.setDescription("Auto settlement completion notifications");
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "SETTLEMENT_COMPLETE")
- .setSmallIcon(R.drawable.ic_launcher_foreground)
- .setContentTitle("Auto Settlement Complete")
- .setContentText("Tap to view settlement results and print receipt")
- .setPriority(NotificationCompat.PRIORITY_HIGH)
- .setAutoCancel(true)
- .setContentIntent(pendingIntent)
- .setFullScreenIntent(pendingIntent, true);
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setContentTitle("Auto Settlement Complete")
+ .setContentText("Tap to view settlement results and print receipt")
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent)
+ .setFullScreenIntent(pendingIntent, true);
notificationManager.notify(2001, builder.build());
-
- LogUtil.d(TAG, " Settlement complete notification created - will launch app when tapped");
-
- try {
- launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_CLEAR_TOP |
- Intent.FLAG_ACTIVITY_SINGLE_TOP |
- Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- startActivity(launchIntent);
- } catch (Exception directException) {
- LogUtil.d(TAG, "Direct launch failed (expected on modern Android), notification approach will handle it");
- }
+
+ // Reset state
+ pendingPayDetail = null;
+ pendingQrData = null;
+ posSettlementReady = false;
+ qrSettlementReady = false;
+ posHasData = false;
+ qrHasData = false;
+
+ startActivity(launchIntent);
} catch (Exception e) {
- LogUtil.e(TAG, "Error creating settlement notification: " + e.getMessage());
+ LogUtil.e(TAG, "Error launching MainActivity: " + e.getMessage());
e.printStackTrace();
}
}
+
+
private void sendEReceipt(EReceiptRequest request) {
try {
LogUtil.d(TAG, "Sending e-receipt: " + new Gson().toJson(request));
diff --git a/app/src/main/java/com/utsmm/kbz/ui/SettingsFragment.java b/app/src/main/java/com/utsmm/kbz/ui/SettingsFragment.java
index 654f1b7..0b87604 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/SettingsFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/SettingsFragment.java
@@ -328,6 +328,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() {
try {
LogUtil.d(TAG, "TMS Config clicked");
diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_ui/CardWaitingFragment.java b/app/src/main/java/com/utsmm/kbz/ui/core_ui/CardWaitingFragment.java
index c128548..c8a9668 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/core_ui/CardWaitingFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/core_ui/CardWaitingFragment.java
@@ -262,6 +262,7 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
} else {
allType.add(CardSlotTypeEnum.ICC1);
allType.add(CardSlotTypeEnum.RF);
+ allType.add(CardSlotTypeEnum.SWIPE);
}
// int allType = AidlConstants.CardType.IC.getValue() | AidlConstants.CardType.MAGNETIC.getValue();
@@ -289,7 +290,7 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
} else if (isFallback && cardType == CardTypeX.MAG) {
/* do fallback transactions */
- sharedViewModel.isEmv.setValue(false);
+ sharedViewModel.isEmv.postValue(false);
cardReadViewModel.setCardTransactionType(CardTransactionType.FALLBACK);
} else if (cardType == CardTypeX.IC || cardType == CardTypeX.NFC) {
diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_ui/EmvTransactionFragment.java b/app/src/main/java/com/utsmm/kbz/ui/core_ui/EmvTransactionFragment.java
index 693cc73..babb908 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/core_ui/EmvTransactionFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/core_ui/EmvTransactionFragment.java
@@ -3,6 +3,7 @@ package com.utsmm.kbz.ui.core_ui;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
+import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -158,6 +159,7 @@ public class EmvTransactionFragment extends DataBindingFragment {
}
observeEmvResultStatus();
+ observePinWarning();
}
private boolean isNotManualTransaction() {
@@ -244,7 +246,7 @@ public class EmvTransactionFragment extends DataBindingFragment {
isCardTaped("Please try again",new CardDetectCallback() {
@Override
public void onComplete() {
- sharedViewModel.setIsSeePhone(true);
+ sharedViewModel.setIsSeePhone(false);
navigateToCheckCard();
}
});
@@ -349,6 +351,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() {
dismissLoadingDialog();
emvTransactionViewModel.errorCodeMsg.observe(getViewLifecycleOwner(), pair -> {
diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_ui/ProcessingFragment.java b/app/src/main/java/com/utsmm/kbz/ui/core_ui/ProcessingFragment.java
index 6cc28be..18b2c6a 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/core_ui/ProcessingFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/core_ui/ProcessingFragment.java
@@ -6,6 +6,8 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.Observer;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
@@ -17,6 +19,9 @@ import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TimeoutCallback;
+import com.utsmyanmar.paylibs.model.TradeData;
+import com.utsmyanmar.paylibs.reversal.ReversalAction;
+import com.utsmyanmar.paylibs.reversal.ReversalListener;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
@@ -104,6 +109,17 @@ public class ProcessingFragment extends DataBindingFragment {
setToolBarTitleWithoutBackIcon(getResourceString(R.string.title_processing));
+ checkReversal();
+
+
+
+// disableNavigationBar();
+
+ getNavController(Constants.NAV_HOST_ID).addOnDestinationChangedListener(listener);
+
+ }
+
+ private void startTransactionProcess() {
if(isEmvTrans()) {
startTransactionProcess(emvTransactionProcessViewModel);
} else {
@@ -111,13 +127,55 @@ public class ProcessingFragment extends DataBindingFragment {
}
sharedViewModel.loadingMsg(getResourceString(R.string.txt_sending));
-
-// disableNavigationBar();
-
- getNavController(Constants.NAV_HOST_ID).addOnDestinationChangedListener(listener);
-
}
+ private void checkReversal() {
+ observeOnce(sharedViewModel.getLastReversalTransaction(), payDetail -> {
+ if (payDetail != null) {
+ TradeData tradeData = new TradeData();
+ tradeData.setPayDetail(payDetail);
+ LogUtil.d(TAG, "Sending Reversal!");
+ sharedViewModel.loadingMsg(getResourceString(R.string.txt_sending_reversal));
+
+ ReversalAction.getInstance().setData(tradeData).enqueue().startReversal(new ReversalListener() {
+ @Override
+ public void onSuccessReversal() {
+ LogUtil.d(TAG, "Reversal Success!");
+ payDetail.setIsNeedReversal(false);
+ sharedViewModel.updatePayDetail(payDetail);
+ delayFunctionCall(()->startTransactionProcess());
+ }
+
+ @Override
+ public void onNetworkFail(String msg) {
+ LogUtil.d(TAG, "Reversal Network Fail!" + msg);
+ startTransactionProcess();
+ }
+
+ @Override
+ public void onFailReversal(String msg) {
+ LogUtil.d(TAG, "Reversal Fail!" + msg);
+ startTransactionProcess();
+ }
+ });
+ } else {
+ LogUtil.d(TAG,"No reversal found!");
+ startTransactionProcess();
+ }
+ });
+ }
+
+ private void observeOnce(LiveData liveData, Observer observer) {
+ liveData.observe(getViewLifecycleOwner(), new Observer() {
+ @Override
+ public void onChanged(T t) {
+ liveData.removeObserver(this);
+ observer.onChanged(t);
+ }
+ });
+ }
+
+
private boolean isEmvTrans() {
return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue();
}
diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_ui/TransactionResultFragment.java b/app/src/main/java/com/utsmm/kbz/ui/core_ui/TransactionResultFragment.java
index e691fe2..2d8d7f9 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/core_ui/TransactionResultFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/core_ui/TransactionResultFragment.java
@@ -335,6 +335,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
sharedViewModel.startPrintSettlement(new PrintXStatus() {
@Override
public void onSuccess() {
+ sharedViewModel.onSettlementResultDone.postValue(true);
isCardInside();
}
diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_viewmodel/SharedViewModel.java b/app/src/main/java/com/utsmm/kbz/ui/core_viewmodel/SharedViewModel.java
index 64b189f..903af51 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/core_viewmodel/SharedViewModel.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/core_viewmodel/SharedViewModel.java
@@ -2,6 +2,7 @@ package com.utsmm.kbz.ui.core_viewmodel;
import android.graphics.Bitmap;
import android.util.Log;
+import android.widget.ListView;
import dagger.hilt.android.lifecycle.HiltViewModel;
import androidx.lifecycle.LiveData;
@@ -73,7 +74,8 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent transactionName = new SingleLiveEvent<>();
-
+ // In SharedViewModel
+ public MutableLiveData onSettlementResultDone = new MutableLiveData<>(false);
/*May 16 2022*/
public SingleLiveEvent isEcr = new SingleLiveEvent<>();
@@ -446,6 +448,14 @@ public class SharedViewModel extends ViewModel {
return repository.getReversalTransaction(voucherNo);
}
+ public LiveData getLastReversalTransaction() {
+ return repository.getLastReversalTransaction();
+ }
+
+ public LiveData> getAllReversalTransaction() {
+ return repository.getAllReversalTransactions();
+ }
+
public void updatePayDetail(PayDetail payDetail){
repository.updatePayDetail(payDetail);
}
diff --git a/app/src/main/java/com/utsmm/kbz/ui/management/SelectHostFragment.java b/app/src/main/java/com/utsmm/kbz/ui/management/SelectHostFragment.java
index 668d63d..66deee9 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/management/SelectHostFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/management/SelectHostFragment.java
@@ -210,21 +210,43 @@ public class SelectHostFragment extends DataBindingFragment implements DataBindi
private void clearReversal() {
checkPointReversal = false;
- sharedViewModel.getReversalTransaction(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), payDetail -> {
- if (payDetail != null) {
- if (!checkPointReversal) {
- payDetail.setIsNeedReversal(false);
- sharedViewModel.updatePayDetail(payDetail);
- checkPointReversal = true;
+// sharedViewModel.getReversalTransaction(SystemParamsOperation.getInstance().getCurrentSerialNum()).observe(getViewLifecycleOwner(), payDetail -> {
+// if (payDetail != null) {
+// if (!checkPointReversal) {
+// payDetail.setIsNeedReversal(false);
+// sharedViewModel.updatePayDetail(payDetail);
+// checkPointReversal = true;
+//
+// showSuccessDialog("Clear reversal success!");
+// }
+// } else {
+// if (!checkPointReversal) {
+// showInfoDialog("Clear reversal", "No reversal found!");
+// checkPointReversal = true;
+// }
+//
+// }
+// });
- showSuccessDialog("Clear reversal success!");
- }
- } else {
- if (!checkPointReversal) {
- showInfoDialog("Clear reversal", "No reversal found!");
- checkPointReversal = true;
- }
+ sharedViewModel.getAllReversalTransaction().observe(getViewLifecycleOwner(), new Observer>() {
+ @Override
+ public void onChanged(List payDetails) {
+ if(payDetails != null && !payDetails.isEmpty()) {
+ if(!checkPointReversal) {
+ for (PayDetail payDetail : payDetails) {
+ payDetail.setIsNeedReversal(false);
+ sharedViewModel.updatePayDetail(payDetail);
+ }
+ checkPointReversal = true;
+ showSuccessDialog("Clear reversal success!");
+ }
+ } else {
+ if (!checkPointReversal) {
+ showInfoDialog("Clear reversal", "No reversal found!");
+ checkPointReversal = true;
+ }
+ }
}
});
}
diff --git a/app/src/main/java/com/utsmm/kbz/ui/pinpad/PinPadViewModel.java b/app/src/main/java/com/utsmm/kbz/ui/pinpad/PinPadViewModel.java
index f475406..923d05d 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/pinpad/PinPadViewModel.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/pinpad/PinPadViewModel.java
@@ -359,7 +359,10 @@ public class PinPadViewModel extends ViewModel {
handler.obtainMessage(ON_ERROR_PIN_PAD,retCode).sendToTarget();
}
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));
}
diff --git a/app/src/main/java/com/utsmm/kbz/ui/settlement/SettlementViewModel.java b/app/src/main/java/com/utsmm/kbz/ui/settlement/SettlementViewModel.java
index 7094ec3..0dbf281 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/settlement/SettlementViewModel.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/settlement/SettlementViewModel.java
@@ -462,11 +462,7 @@ public class SettlementViewModel extends ViewModel {
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
//reversal
// if (!flag && isNoData.getValue()) {
- if (!flag ) {
- payDetail.setIsNeedReversal(true);
- } else {
- payDetail.setIsNeedReversal(false);
- }
+ payDetail.setIsNeedReversal(!flag);
}
} else {
diff --git a/app/src/main/java/com/utsmm/kbz/util/TransactionUtil.java b/app/src/main/java/com/utsmm/kbz/util/TransactionUtil.java
index 35e0a8e..f8890db 100644
--- a/app/src/main/java/com/utsmm/kbz/util/TransactionUtil.java
+++ b/app/src/main/java/com/utsmm/kbz/util/TransactionUtil.java
@@ -6,6 +6,7 @@ import com.utsmyanmar.paylibs.model.CardInfo;
import com.utsmyanmar.paylibs.model.MAGCardInfo;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
+import com.utsmyanmar.paylibs.model.enums.TransCVM;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.params.Params;
@@ -98,7 +99,8 @@ public class TransactionUtil {
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setCardNo(cardDataX.getPan());
payDetail.setEXPDate(cardDataX.getExp());
-
+ payDetail.setTransCVM(TransCVM.SIGNATURE);
+
if(cardDataX.getPan().startsWith("4")) {
payDetail.setAccountType(VISA_CARD_SCHEME);
} else if(cardDataX.getPan().startsWith("5")) {
diff --git a/app/src/main/res/layout/fragment_emv_input_pin.xml b/app/src/main/res/layout/fragment_emv_input_pin.xml
index bef418c..d6771fa 100644
--- a/app/src/main/res/layout/fragment_emv_input_pin.xml
+++ b/app/src/main/res/layout/fragment_emv_input_pin.xml
@@ -120,16 +120,17 @@
diff --git a/app/src/main/res/layout/fragment_settings_modern.xml b/app/src/main/res/layout/fragment_settings_modern.xml
index 910234e..8796b87 100644
--- a/app/src/main/res/layout/fragment_settings_modern.xml
+++ b/app/src/main/res/layout/fragment_settings_modern.xml
@@ -969,6 +969,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
getReversalTransaction(String voucherNo);
+ @Query("SELECT * FROM PayDetail WHERE isNeedReversal = 1 ORDER BY PID DESC LIMIT 1")
+ LiveData getLastReversalTransactionLive();
+
+ @Query("SELECT * FROM PayDetail WHERE isNeedReversal = 1 ORDER BY PID DESC")
+ LiveData> getAllReversalTransactionsLive();
+
// @Query("SELECT * FROM paydetail WHERE transactionType != 10 ORDER BY PID DESC")
@Query("SELECT * FROM paydetail ORDER BY PID DESC")
LiveData> getTransactionHistory();
diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamHelper.java b/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamHelper.java
index 02ad555..bafad5f 100644
--- a/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamHelper.java
+++ b/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamHelper.java
@@ -349,7 +349,7 @@ public class EmvParamHelper {
private AidEntity convertContactlessAIDNex(ContactlessAid contactlessAid) {
AidEntity aidV2 = new AidEntity();
- aidV2.setTransType("FF");
+ aidV2.setTransType("FF"); // FF
aidV2.setOnlinePinCap(1);
aidV2.setAsi(0);
aidV2.setThreshold(0);
@@ -412,7 +412,8 @@ public class EmvParamHelper {
aidV2.setTransType("FF");
aidV2.setOnlinePinCap(1);
- aidV2.setAsi(1);
+ aidV2.setAsi(0); //1
+// aidV2.setThreshold(99);
if (!(contactAid.getCvmLimit() < 0)) {
aidV2.setContactlessCvmLimit(contactAid.getCvmLimit());
@@ -464,6 +465,10 @@ public class EmvParamHelper {
aidV2.setAppVerNum(contactAid.getApplicationVersion());
}
+ if (contactAid.getThreshold() != null && !contactAid.getThreshold().isEmpty()) {
+ aidV2.setThreshold(Long.parseLong(contactAid.getThreshold()));
+ }
+
return aidV2;
}
diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java b/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java
index 7608977..791cbac 100644
--- a/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java
+++ b/baselib/src/main/java/com/utsmyanmar/baselib/repo/Repository.java
@@ -146,6 +146,8 @@ public class Repository {
public void updatePayDetail(PayDetail payDetail){payDetailDao.update(payDetail);}
public LiveData getReversalTransaction(String voucherNo) { return payDetailDao.getReversalTransaction(voucherNo);}
+ public LiveData getLastReversalTransaction() { return payDetailDao.getLastReversalTransactionLive();}
+ public LiveData> getAllReversalTransactions() { return payDetailDao.getAllReversalTransactionsLive();}
public LiveData> getTransactionHistory(){ return payDetailDao.getTransactionHistory();}
diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java b/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java
index dac35b2..755a890 100644
--- a/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java
+++ b/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java
@@ -1,12 +1,15 @@
package com.utsmyanmar.baselib.viewModel;
+import android.app.AlertDialog;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
+import android.view.View;
import android.view.ViewTreeObserver;
+import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
@@ -105,6 +108,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
public MutableLiveData pinPadVisibility = new MutableLiveData<>(8);
protected int pinEnterCount;
+ private int offlinePinIncorrectPromptCount;
public CustomPinPadKeyboard customPinPadKeyboard;
private int mWidth = 239; // Single item width of password keyboard
@@ -245,6 +249,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
transData.setTransTime(new SimpleDateFormat("hhmmss", Locale.getDefault()).format(new Date()));
transData.setTraceNo(mPayDetail.getVoucherNo());
+
transData.setEmvProcessFlowEnum(EmvProcessFlowEnum.EMV_PROCESS_FLOW_STANDARD);
if (mPayDetail.getCardType() == CardTypeX.NFC.value) {
transData.setEmvEntryModeEnum(EmvEntryModeEnum.EMV_ENTRY_MODE_CONTACTLESS);
@@ -260,7 +265,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
unionPayTransDataEntity.setSupportCDCVM(true);
//if support QPS, please enable below lines
unionPayTransDataEntity.setSupportContactlessQps(true);
- unionPayTransDataEntity.setContactlessQpsLimit("000090000000");
+ unionPayTransDataEntity.setContactlessQpsLimit("000000030000");
+
transData.setUnionPayTransDataEntity(unionPayTransDataEntity);
@@ -269,6 +275,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
emvHandler.contactlessAppendAidIntoKernel(EmvCardBrandEnum.EMV_CARD_BRAND_MASTER, (byte) 0x08, ByteUtils.hexString2ByteArray("A000000732100123"));
LogUtil.d(TAG, "TransData :" + transData.getTransAmount());
LogUtil.d(TAG, "start emv ");
+
+// emvHandler.emvDebugLog(true);
emvHandler.emvProcess(transData, emvProcessListener);
@@ -276,7 +284,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
private void initData() {
try {
- emvHandler = BaseApplication.getInstance().deviceEngine.getEmvHandler2("app2");
+ emvHandler = BaseApplication.getInstance().deviceEngine.getEmvHandler2("app2");
if (emvHandler == null) {
LogUtil.e(TAG, "Failed to initialize EMV handler - emvHandler is null");
// Post error status to inform UI
@@ -308,8 +316,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
return;
}
try {
- LogUtil.d(TAG, "Selected :" + position);
- emvHandler.onSetSelAppResponse(position);
+ LogUtil.d(TAG, "Selected :" + position + 1);
+ emvHandler.onSetSelAppResponse(position + 1);
} catch (Exception e) {
LogUtil.e(TAG, "Exception during app selection: " + e.getMessage());
e.printStackTrace();
@@ -425,213 +433,142 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
initKeyboard(isOnlinePin == 1);
}
-
-
private void initKeyboard(boolean isOnlinePin) {
-
- LogUtil.d(TAG,"init keyboard!");
+ LogUtil.d(TAG, "init keyboard!");
pinPadVisibility.setValue(0);
- 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, "pin pad is visible now!");
- LogUtil.d(TAG,"inside the global layout!");
- PinpadLayoutEntity pinpadLayout = new PinpadLayoutEntity();
- int[] location = new int[2];
- Rect r;
- customPinPadKeyboard.getKey_1().getLocationOnScreen(location);
- r = new Rect();
- r.left = location[0];
- r.top = location[1];
- r.right = customPinPadKeyboard.getKey_1().getWidth() + r.left;
- r.bottom = customPinPadKeyboard.getKey_1().getHeight() + r.top;
- pinpadLayout.setKey1(r);
-
- customPinPadKeyboard.getKey_2().getLocationOnScreen(location);
- 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, 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);
+ // Check if the view is already laid out
+ if (customPinPadKeyboard.getWidth() > 0 && customPinPadKeyboard.getHeight() > 0) {
+ // View already laid out — call setup directly
+ setupPinPadLayout(isOnlinePin);
+ } else {
+ // View not yet laid out — wait for layout
+ customPinPadKeyboard.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (customPinPadKeyboard.getWidth() > 0 && customPinPadKeyboard.getHeight() > 0) {
+ customPinPadKeyboard.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ setupPinPadLayout(isOnlinePin);
}
}
}
+ );
+ }
+ }
+ 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) {
+ 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, 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() {
@@ -676,11 +613,11 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
}
} 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
-
- }
+// 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);
@@ -705,6 +642,9 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
public void onCardHolderInputPin(boolean isOnlinePin, int leftTimes) {
LogUtil.d(TAG, "onCardHolderInputPin isOnlinePin = " + isOnlinePin);
LogUtil.d(TAG, "onCardHolderInputPin leftTimes = " + leftTimes);
+ if (isOnlinePin) {
+ pinRemainingCount.postValue("");
+ }
// startPinProcess(isOnlinePin ? 1 : 0);
mProcessStep = EMV_SHOW_PIN_PAD;
// mHandler.obtainMessage(EMV_SHOW_PIN_PAD, isOnlinePin ? 1 : 0).sendToTarget();
@@ -743,7 +683,17 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
@Override
public void onPrompt(PromptEnum 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
@@ -801,6 +751,9 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
byte[] tlv_50 = emvHandler.getTlv(new byte[]{(byte) 0x50}, EmvDataSourceEnum.FROM_KERNEL);
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) {
case SdkResult.Emv_Success_Arpc_Fail:
case SdkResult.Success:
@@ -967,6 +920,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
emvCardType.postValue("");
pinText.setValue("");
pinEnterCount = 0;
+ offlinePinIncorrectPromptCount = 0;
}
protected void getCardInfo() {
@@ -1256,8 +1210,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
kernelTTQ[1] = TTQ[1];
kernelTTQ[2] = TTQ[2];
kernelTTQ[3] = TTQ[3];
-
- // FIXME: 2019/3/20
+
//If there is no special requirements, do not change TTQ byte1
//if online force required , can set byte2 bit 8 = 1
emvHandler.setTlv(ByteUtils.hexString2ByteArray("9F66"), kernelTTQ);
diff --git a/baselib/src/main/res/raw/quickpass_config.json b/baselib/src/main/res/raw/quickpass_config.json
index a56020b..47b3a28 100644
--- a/baselib/src/main/res/raw/quickpass_config.json
+++ b/baselib/src/main/res/raw/quickpass_config.json
@@ -14,7 +14,7 @@
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
- "cvmLimit": 75000,
+ "cvmLimit": 30000,
"transLimit": "9999999999",
"transLimitCDV": "9999999999",
"terminalCapability": "0000000000000000",
@@ -26,7 +26,6 @@
},
{
"aidEnable": true,
- "aid": "A000000333010102",
"cardLabel": "UPI",
"applicationVersion": "0002",
"emvDDOL": "9F3704",
@@ -39,7 +38,57 @@
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"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",
"transLimitCDV": "9999999999",
"terminalCapability": "0000000000000000",
diff --git a/mpulib/src/main/java/com/utsmyanmar/checkxread/checkcard/CheckCardX.java b/mpulib/src/main/java/com/utsmyanmar/checkxread/checkcard/CheckCardX.java
index f63029c..567475a 100644
--- a/mpulib/src/main/java/com/utsmyanmar/checkxread/checkcard/CheckCardX.java
+++ b/mpulib/src/main/java/com/utsmyanmar/checkxread/checkcard/CheckCardX.java
@@ -6,6 +6,7 @@ import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
+import com.nexgo.common.LogUtils;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.reader.CardInfoEntity;
import com.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum;
@@ -106,6 +107,14 @@ public class CheckCardX {
Log.d(TAG, "Find IC");
} else if(cardInfoEntity.getCardExistslot() == CardSlotTypeEnum.RF) {
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) {
checkCardResultX.onError(i,"Failure");
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/model/CardSettleData.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/model/CardSettleData.java
index b799fa5..29105c7 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/model/CardSettleData.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/model/CardSettleData.java
@@ -1,9 +1,10 @@
package com.utsmyanmar.paylibs.model;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-public class CardSettleData {
+public class CardSettleData implements Serializable {
private String cardType;
private String cardNum;
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/model/QRSettleData.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/model/QRSettleData.java
index e080e78..67d11c1 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/model/QRSettleData.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/model/QRSettleData.java
@@ -1,9 +1,10 @@
package com.utsmyanmar.paylibs.model;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-public class QRSettleData {
+public class QRSettleData implements Serializable {
private String transId;
private String date;
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/model/SettleData.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/model/SettleData.java
index 900f336..e0e6b14 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/model/SettleData.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/model/SettleData.java
@@ -1,6 +1,8 @@
package com.utsmyanmar.paylibs.model;
-public class SettleData {
+import java.io.Serializable;
+
+public class SettleData implements Serializable {
private int saleCount;
private long saleAmount;
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/model/enums/TransCVM.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/model/enums/TransCVM.java
index d3546a4..2dc403e 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/model/enums/TransCVM.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/model/enums/TransCVM.java
@@ -1,6 +1,8 @@
package com.utsmyanmar.paylibs.model.enums;
-public enum TransCVM {
+import java.io.Serializable;
+
+public enum TransCVM implements Serializable {
OFFLINE_PIN("Offline PIN"),
ONLINE_PIN("Online PIN"),
SIGNATURE("Signature"),
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/AuthorizationProcessUtil.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/AuthorizationProcessUtil.java
index b2de037..f267b98 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/AuthorizationProcessUtil.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/AuthorizationProcessUtil.java
@@ -154,7 +154,6 @@ public class AuthorizationProcessUtil {
hexValues[i] = value;
}
int status;
- String f055Data = getF055Data();
LogUtil.d(TAG,"is equal:"+equals);
LogUtil.d(TAG,"Emv Online Result:"+emvOnlineResult);
if (equals) {
@@ -177,7 +176,7 @@ public class AuthorizationProcessUtil {
LogUtil.e(Constant.TAG, "scriptResult: " + scriptResult);
payDetail.setScriptResult(scriptResult);
-
+ String f055Data = getF055Data();
LogUtil.e(Constant.TAG, "f055Data: " + f055Data);
// if (status >= 0) {
@@ -205,6 +204,9 @@ public class AuthorizationProcessUtil {
private void importOnlineProcessStatus(int sdkResult,EmvOnlineResultEntity emvOnlineResult) {
LogUtil.d(TAG, "importOnlineProcessStatus sdkResult:"+sdkResult);
LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+emvOnlineResult.toString());
+ LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+emvOnlineResult.getAuthCode());
+ LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+emvOnlineResult.getRejCode());
+ LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+ ByteUtil.bytes2HexStr(emvOnlineResult.getRecvField55()));
PayLibNex.getInstance().deviceEngine.getEmvHandler2("app2").onSetOnlineProcResponse(sdkResult, emvOnlineResult);
}
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/KernelDataProcessUtil.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/KernelDataProcessUtil.java
index 150af89..2452bc2 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/KernelDataProcessUtil.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/KernelDataProcessUtil.java
@@ -2,7 +2,10 @@ package com.utsmyanmar.paylibs.utils.core_utils;
import android.text.TextUtils;
+import com.nexgo.oaf.apiv3.emv.EmvDataSourceEnum;
+import com.nexgo.oaf.apiv3.emv.EmvHandler2;
import com.utsmyanmar.paylibs.Constant;
+import com.utsmyanmar.paylibs.PayLibNex;
import com.utsmyanmar.paylibs.model.BaseCardInfo;
import com.utsmyanmar.paylibs.model.CardInfo;
import com.utsmyanmar.paylibs.model.ICCardInfo;
@@ -670,43 +673,42 @@ public class KernelDataProcessUtil {
}
LogUtil.d(TAG,"9F6E data :"+hexStr);
-// byte[] dataOut = new byte[1024];
-//
-// try {
-// int len = PayLibsUtils.getInstance().emvOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYWAVE, tagList, dataOut);
-// if (len > 0) {
-// byte[] dataOutBytes = Arrays.copyOf(dataOut, len);
-// hexStr = ByteUtil.bytes2HexStr(dataOutBytes);
-// LogUtil.d(TAG, "get 9F6E Data :" + hexStr);
-// Map map = TLVUtil.buildTLVMap(hexStr);
-// LogUtil.d(TAG, "get 9F6E Data :" + map);
-//
-// } else {
-// LogUtil.e(TAG, "Get the data length of payWave is negative = " + len);
-// }
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
-//
+ byte[] dataOut = new byte[1024];
+ EmvHandler2 emvHandler = PayLibNex.getInstance().deviceEngine.getEmvHandler2("app2");
+ try {
+
+ byte[] dateValue = emvHandler.getTlv(ByteUtil.hexStr2Bytes("9F6E"), EmvDataSourceEnum.FROM_CARD);
+ if (dateValue != null) {
+
+ hexStr = ByteUtil.bytes2HexStr(dateValue);
+ LogUtil.d(TAG, "get 9F6E Data :" + hexStr);
+
+
+ } else {
+ LogUtil.e(TAG, "Get the data length of payWave is null = " );
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
// if (hexStr.equals("9F6E00")) {
// try {
-// int len = PayLibsUtils.getInstance().emvOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYPASS, tagList, dataOut);
-// if (len > 0) {
-// byte[] dataOutBytes = Arrays.copyOf(dataOut, len);
-// hexStr = ByteUtil.bytes2HexStr(dataOutBytes);
+// byte[] dateValue = emvHandler.getTlv(ByteUtil.hexStr2Bytes("9F6E"), EmvDataSourceEnum.FROM_CARD);
+// if (dateValue != null) {
+// hexStr = ByteUtil.bytes2HexStr(dateValue);
// LogUtil.d(TAG, "get 9F6E Data :" + hexStr);
// Map map = TLVUtil.buildTLVMap(hexStr);
// LogUtil.d(TAG, "get 9F6E Data :" + map);
//
// } else {
-// LogUtil.e(TAG, "Get the data length of payPass is negative = " + len);
+// LogUtil.e(TAG, "Get the data length of payPass is null = ");
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
-// if (!hexStr.equals("9F6E00")) {
-// f55WaveDataStr += hexStr;
+// if (!hexStr.isEmpty()) {
+// f55WaveDataStr += "9F6E04"+hexStr;
// }
icCardInfo.setICC55(f55WaveDataStr);
payDetail.setICC55(f55WaveDataStr);
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/BitmapConfig.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/BitmapConfig.java
index b48fc22..6364e1a 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/BitmapConfig.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/BitmapConfig.java
@@ -69,7 +69,8 @@ public class BitmapConfig {
// public static final String BPC_VOID = "3230058028C08000";
// commented on Nov 13,2024
- public static final String BPC_VOID = "3230058028C18000"; // original
+// public static final String BPC_VOID = "3230058028C18000"; // original
+ public static final String BPC_VOID = "3230058028C08000"; // original March 25, 2026
// public static final String BPC_VOID = "3230058028C08000"; // 16-May-2025 removed DE48 requested by KoAAT added DE2
// public static final String BPC_VOID = "3230058028C08000"; // 16-May-2025 removed DE48 requested by KoAAT
// public static final String BPC_VOID = "3230058028C18200";
@@ -108,8 +109,9 @@ public class BitmapConfig {
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7230058028C19800"; // added DE 2
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7234058008C09000"; // for tmk MPU
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7230058008C09000"; // for KBZ MPU
- public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7234058008C09000"; // for KBZ MPU added DE 14
-// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "3230058028C19800";
+// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7234058008C09000"; // for KBZ MPU added DE 14 Mar 25, 26
+ public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "3230058028C08000"; // from log March 25
+
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "3230058028C19A00"; //DE55
//
// public static final String BPC_PRE_AUTH_SALE_COMPLETE_VOID = "3230058028C09200";
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/FieldUtils.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/FieldUtils.java
index 41f7bb0..6ae9937 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/FieldUtils.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/FieldUtils.java
@@ -341,7 +341,8 @@ public class FieldUtils {
} else if (BaseCardType.IC.getValue() == cardType) { // IC
value = "05";
} else if (FALLBACK == cardType){ // Fallback
- value = "08";
+ value = "72";
+// value = "08";
} else { // Hand-in card number
value = "01";
}
@@ -350,11 +351,16 @@ public class FieldUtils {
if(payDetail.getTransCVM() == TransCVM.OFFLINE_PIN) {
value += "9";
} else {
- if (payDetail.getPINCipher() != null && !payDetail.getPINCipher().trim().isEmpty()) {
- value += "1";
+ if(payDetail.getTransactionType() == VOID.value) {
+ value += "0";
} else {
- value += "2";
+ if (payDetail.getPINCipher() != null && !payDetail.getPINCipher().trim().isEmpty()) {
+ value += "1";
+ } else {
+ value += "2";
+ }
}
+
}
diff --git a/settings.gradle b/settings.gradle
index 460fa7a..457b0f5 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -32,7 +32,7 @@ include ':baselib'
include ':mpulib'
//include ':ecr-client-lib'
-include ':ecr-service'
+//include ':ecr-service'
include ':xpay'
include ':ecr'
include ':ecr-service-lib'