diff --git a/app/build.gradle b/app/build.gradle
index 60e4d69..12aa58e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -216,6 +216,7 @@ dependencies {
implementation project(path: ':xpay')
// implementation project(path: ':sunmiui-lib')
implementation project(path: ':qrgen-lib')
+ implementation project(path: ':cmhl')
//// implementation project(path: ':samlSirius')
// Legacy ECR (kept for backward compatibility during migration)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2cbf5ff..d1938f4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -35,6 +35,7 @@
+
@@ -98,7 +99,14 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/utsmm/kbz/MainFragment.java b/app/src/main/java/com/utsmm/kbz/MainFragment.java
index bc2e9dc..bd15c0d 100644
--- a/app/src/main/java/com/utsmm/kbz/MainFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/MainFragment.java
@@ -1,8 +1,13 @@
package com.utsmm.kbz;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
@@ -20,6 +25,19 @@ import androidx.lifecycle.Observer;
import com.denzcoskun.imageslider.ImageSlider;
import com.denzcoskun.imageslider.constants.ScaleTypes;
import com.denzcoskun.imageslider.models.SlideModel;
+import com.kizzy.cmhl.EcrManager;
+import com.kizzy.cmhl.EcrRequestDispatcher;
+import com.kizzy.cmhl.EcrRequestListener;
+import com.kizzy.cmhl.models.EcrPacket;
+import com.kizzy.cmhl.models.PingRequest;
+import com.kizzy.cmhl.models.PreAuthCancellationRequest;
+import com.kizzy.cmhl.models.PreAuthCompletionRequest;
+import com.kizzy.cmhl.models.PreAuthRequest;
+import com.kizzy.cmhl.models.QrPaymentRequest;
+import com.kizzy.cmhl.models.SaleRequest;
+import com.kizzy.cmhl.models.SettlementRequest;
+import com.kizzy.cmhl.models.VoidQrPaymentRequest;
+import com.kizzy.cmhl.models.VoidRequest;
import com.nexgo.oaf.apiv3.APIProxy;
import com.nexgo.oaf.apiv3.DeviceEngine;
import com.nexgo.oaf.apiv3.SdkResult;
@@ -29,6 +47,7 @@ import com.nexgo.oaf.apiv3.emv.AidEntity;
import com.nexgo.oaf.apiv3.emv.CapkEntity;
//import com.pos.connection.bridge.binder.ECRConstant;
+import com.utsmm.kbz.service.SerialPortService;
import com.utsmm.kbz.util.MockData;
//import com.utsmm.kbz.util.ecr.ModernECRFactory;
//import com.utsmm.kbz.util.ecr.ModernECRManager;
@@ -49,6 +68,7 @@ import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.print.PrintHelper;
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.utils.POSUtil;
+import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
@@ -90,6 +110,7 @@ import com.utsmyanmar.paylibs.utils.params.Params;
//import com.utsmm.kbz.util.ecr.ModernECRFactory;
//import com.utsmm.kbz.util.ecr.ModernECRManager;
import androidx.lifecycle.ViewModelProvider;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@AndroidEntryPoint
public class MainFragment extends DataBindingFragment {
@@ -134,16 +155,42 @@ public class MainFragment extends DataBindingFragment {
// modernECRManager = new ViewModelProvider(this, factory).get(ModernECRManager.class);
}
+ @Override
+ public void onStart() {
+ super.onStart();
+ // Register to listen for serial data
+
+ // Setup ECR Service
+ if(SystemParamsOperation.getInstance().getECRStatus()){
+ LocalBroadcastManager.getInstance(requireContext())
+ .registerReceiver(serialReceiver,
+ new IntentFilter(SerialPortService.ACTION_DATA_RECEIVED));
+
+ // Start the service
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ requireContext().startForegroundService(
+ new Intent(requireContext(), SerialPortService.class));
+ }
+
+ LogUtil.d(TAG,"ECR service initialized!");
+ }
+
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ LocalBroadcastManager.getInstance(requireContext())
+ .unregisterReceiver(serialReceiver);
+ }
+
@Override
public void onResume() {
super.onResume();
setNavBarIconWithTitle(getResourceString(R.string.menu_dashboard));
- // Setup ECR Service
- if(SystemParamsOperation.getInstance().getECRStatus()){
- setUpECR();
- }
+
sharedViewModel.isEcrFinished.postValue(true);
sharedViewModel.isEcr.postValue(false);
@@ -196,7 +243,33 @@ public class MainFragment extends DataBindingFragment {
safeNavigateToRouteId();
}
}
-
+
+ private BroadcastReceiver serialReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String data = intent.getStringExtra(SerialPortService.EXTRA_DATA);
+ LogUtil.d("USB", "UI received: " + data);
+ // update your UI here
+
+// LogUtil.d(TAG, "Received : " + msg);
+
+
+ if (sharedViewModel.isEcrFinished.getValue() != null && sharedViewModel.isEcrFinished.getValue()) {
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRActionCHML(ByteUtil.hexStr2Bytes(data));
+ } else {
+ ECRAction(data);
+ }
+
+ } else {
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRActionCHML(ByteUtil.hexStr2Bytes(data));
+ } else {
+ ECRAction(data);
+ }
+ }
+ }
+ };
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -260,68 +333,8 @@ public class MainFragment extends DataBindingFragment {
// queryAidCAPKList();
queryAidCAPKList();
// generateMockQR();
- DeviceEngine deviceEngine = APIProxy.getDeviceEngine(requireContext());
-
- port = deviceEngine.getSerialPortDriver(0);
-
- SerialCfgEntity entity = new SerialCfgEntity();
- entity.setBaudRate(115200);
- entity.setDataBits(8);
- entity.setParity('n');
- entity.setStopBits(1);
-
- int result = port.connect(entity);
-
- if (result == SdkResult.Success) {
-
- LogUtil.d("USB", "USB Serial connected");
- String echo = "Hello ECR";
- byte[] data = echo.getBytes(StandardCharsets.UTF_8);
- port.send(data, data.length);
-
- port.clrBuffer();
-
- isRunning = true;
- startReceiveThread();
-
- } else {
-
- LogUtil.e("USB", "USB Serial connect failed");
-
- }
}
- private void startReceiveThread() {
-
- new Thread(() -> {
-
- byte[] buffer = new byte[2048];
-
- while (isRunning) {
-
- int len = port.recv(buffer, buffer.length, 3000);
-
- if (len > 0) {
-
- String msg = new String(buffer, 0, len);
-
- LogUtil.d("USB", "Received: " + msg);
-
- requireActivity().runOnUiThread(() -> {
-
- // update UI here
- // example:
- // binding.txtResult.setText(msg);
-
- });
- }
- }
-
- }).start();
- }
-
-
-
/*
* @param
*
@@ -366,25 +379,8 @@ public class MainFragment extends DataBindingFragment {
});
}
- private void setUpECR() {
- if (checkECRServiceAppExistOrNot()) {
- // Initialize Modern ECR Manager
-// modernECRManager.init();
-////
-//// // Observe navigation requests
-// modernECRManager.getNavigationRequest().observe(getViewLifecycleOwner(), destinationId -> {
-// if (destinationId != null) {
-// delayFunctionCall(() -> isRouteValidAndNavigateToRoute(destinationId));
-// }
-// });
-
- showShortToast("ECR Service initialized");
- } else {
- Toast.makeText(getContext(), "ECR Service Not Found!", Toast.LENGTH_SHORT).show();
- }
- }
- // Legacy ECR methods removed
+
private void updateButtonStatus() {
@@ -761,6 +757,204 @@ public class MainFragment extends DataBindingFragment {
}
+ private void ECRAction(String msg) {
+
+// LogUtil.d(TAG, "ECR msg here : " + msg);
+
+ String ecrKey = SystemParamsOperation.getInstance().getEcrKey().toUpperCase();
+ String pkgName = BuildConfig.APPLICATION_ID;
+ String serialNo = TerminalUtil.getInstance().getSerialNo();
+
+ ResultOf result = ECRProcess.INSTANCE.parseECRRequest(ecrKey,pkgName,serialNo,msg);
+
+ if (result instanceof ResultOf.Success) {
+ Transactions trans = ((ResultOf.Success) result).getValue();
+
+
+ CoreUtils.getInstance(sharedViewModel).logTrans(trans);
+
+ sharedViewModel.ecrCMD.postValue(trans.getCMD());
+ sharedViewModel.ecrTrans.postValue(trans);
+
+ switch (Objects.requireNonNull(trans.getCMD())) {
+ case ECHO:
+ CoreUtils.getInstance(sharedViewModel).setUpECREchoTest();
+ break;
+ case SALE:
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRSale(trans)) {
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
+ }
+ break;
+ case VOID:
+ if(!SystemParamsOperation.getInstance().getVoidStatus()) {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(trans,"Void is disabled!");
+ return;
+ }
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRVoid(trans)) {
+ delayFunctionCall(() -> {
+ if(Objects.requireNonNull(getNavController(Constants.NAV_HOST_ID).getCurrentDestination()).getId() == R.id.nav_main) {
+ setToolBarTitle(getResourceString(R.string.menu_sale_void));
+ }
+
+ isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_inputPasswordFragment);
+ });
+ }
+ break;
+ case CASH_ADVANCE: {
+
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRCashAdvance(trans)) {
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
+ }
+
+ break;
+ }
+ case QR_SALE: {
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRQR(trans)) {
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_QRConnectingFragment));
+ }
+ break;
+
+ }
+
+ case SETTLEMENT: {
+ if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(trans,"Settlement is disabled!");
+ return;
+ }
+ CoreUtils.getInstance(sharedViewModel).setUpECRSettlement();
+
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_inputPasswordFragment));
+
+ break;
+ }
+
+ default:
+ showDeclineDialog("No Action found on \n" + trans.getCMD());
+ break;
+ }
+ } else {
+ String errorMsg = ((ResultOf.Failure) result).getMessage();
+ showDeclineDialog("No Action found on \n" + errorMsg);
+ }
+
+ }
+
+ private void ECRActionCHML(byte[] data) {
+
+// LogUtil.d(TAG, "ECR msg here : " + msg);
+ try {
+ EcrPacket ecrPacket = EcrManager.parsePacket(data);
+
+ EcrRequestDispatcher.dispatch(ecrPacket, new EcrRequestListener() {
+ @Override
+ public void onPingRequest(PingRequest request) {
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+
+ CoreUtils.getInstance(sharedViewModel).setupPingRequest(request);
+
+
+ }
+
+ @Override
+ public void onSaleRequest(SaleRequest request) {
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRSale(request)) {
+ LogUtil.d(TAG,"Starting to process sale transaction!");
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
+ }
+
+
+ }
+
+ @Override
+ public void onVoidRequest(VoidRequest request) {
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRVoid(request)) {
+ delayFunctionCall(() -> {
+ if(Objects.requireNonNull(getNavController(Constants.NAV_HOST_ID).getCurrentDestination()).getId() == R.id.nav_main) {
+ setToolBarTitle(getResourceString(R.string.menu_sale_void));
+ }
+
+ isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_inputPasswordFragment);
+ });
+ }
+ }
+
+ @Override
+ public void onSettlementRequest(SettlementRequest request) {
+//
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+
+ CoreUtils.getInstance(sharedViewModel).setUpECRSettlement();
+
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_inputPasswordFragment));
+ }
+
+ @Override
+ public void onPreAuthRequest(PreAuthRequest request) {
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRPreAuth(request)) {
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
+ }
+
+ }
+
+ @Override
+ public void onPreAuthCompletionRequest(PreAuthCompletionRequest request) {
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRPreAuthComplete(request)) {
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
+ }
+ }
+
+ @Override
+ public void onPreAuthCancellationRequest(PreAuthCancellationRequest request) {
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRPreAuthVoid(request)) {
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
+ }
+ }
+
+ @Override
+ public void onQrPaymentRequest(QrPaymentRequest request) {
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+
+ if (CoreUtils.getInstance(sharedViewModel).setUpECRQR(request)) {
+ delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_QRConnectingFragment));
+ }
+
+ }
+
+ @Override
+ public void onVoidQrPaymentRequest(VoidQrPaymentRequest request) {
+
+ }
+
+ @Override
+ public void onUnknownRequest(EcrPacket packet) {
+ System.out.println("command :"+packet.getCommandCode());
+ }
+ });
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ }
+
public class ClickEvent {
public void onClickTrans() {
diff --git a/app/src/main/java/com/utsmm/kbz/MyApplication.java b/app/src/main/java/com/utsmm/kbz/MyApplication.java
index f0ab182..2a77f6e 100644
--- a/app/src/main/java/com/utsmm/kbz/MyApplication.java
+++ b/app/src/main/java/com/utsmm/kbz/MyApplication.java
@@ -1,6 +1,7 @@
package com.utsmm.kbz;
import com.utsmyanmar.baselib.BaseApplication;
+import com.utsmyanmar.ecr.ECRHelper;
import dagger.hilt.android.HiltAndroidApp;
@@ -21,7 +22,7 @@ public class MyApplication extends BaseApplication {
super.onCreate();
app = this;
-
+ ECRHelper.INSTANCE.initSerialPort(getApplicationContext());
// emvParamOperation.loadDataFromJSON();
}
diff --git a/app/src/main/java/com/utsmm/kbz/service/SerialPortService.java b/app/src/main/java/com/utsmm/kbz/service/SerialPortService.java
new file mode 100644
index 0000000..6308756
--- /dev/null
+++ b/app/src/main/java/com/utsmm/kbz/service/SerialPortService.java
@@ -0,0 +1,112 @@
+package com.utsmm.kbz.service;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Build;
+import android.os.IBinder;
+
+import androidx.annotation.Nullable;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
+import com.nexgo.oaf.apiv3.APIProxy;
+import com.nexgo.oaf.apiv3.DeviceEngine;
+import com.nexgo.oaf.apiv3.SdkResult;
+import com.nexgo.oaf.apiv3.device.serialport.SerialCfgEntity;
+import com.nexgo.oaf.apiv3.device.serialport.SerialPortDriver;
+import com.utsmm.kbz.R;
+import com.utsmyanmar.paylibs.utils.LogUtil;
+
+import java.nio.charset.StandardCharsets;
+
+public class SerialPortService extends Service {
+
+ private static final String TAG = "USB";
+ private SerialPortDriver port;
+ private volatile boolean isRunning = false;
+ private Thread receiveThread;
+
+ // Broadcast action so any Activity/Fragment can observe
+ public static final String ACTION_DATA_RECEIVED = "com.yourapp.SERIAL_DATA";
+ public static final String EXTRA_DATA = "data";
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ startForegroundNotification(); // required for foreground service
+ connectAndListen();
+ return START_STICKY; // restarts if killed
+ }
+
+ private void connectAndListen() {
+ DeviceEngine deviceEngine = APIProxy.getDeviceEngine(this);
+ port = deviceEngine.getSerialPortDriver(0);
+
+ SerialCfgEntity entity = new SerialCfgEntity();
+ entity.setBaudRate(115200);
+ entity.setDataBits(8);
+ entity.setParity('n');
+ entity.setStopBits(1);
+
+ int result = port.connect(entity);
+
+ if (result == SdkResult.Success) {
+ LogUtil.d(TAG, "Connected");
+ isRunning = true;
+ startReceiveThread();
+ } else {
+ LogUtil.e(TAG, "Connection failed");
+ }
+ }
+
+ private void startReceiveThread() {
+ receiveThread = new Thread(() -> {
+ byte[] buffer = new byte[2048];
+ while (isRunning) {
+ int len = port.recv(buffer, buffer.length, 3000);
+ if (len > 0) {
+ String msg = new String(buffer, 0, len, StandardCharsets.UTF_8);
+ LogUtil.d(TAG, "Received: " + msg);
+ broadcastData(msg); // notify UI
+ }
+ }
+ });
+ receiveThread.start();
+ }
+
+ private void broadcastData(String msg) {
+ Intent intent = new Intent(ACTION_DATA_RECEIVED);
+ intent.putExtra(EXTRA_DATA, msg);
+ LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
+ }
+
+ @Override
+ public void onDestroy() {
+ isRunning = false;
+ if (port != null) port.disconnect();
+ super.onDestroy();
+ }
+
+ private void startForegroundNotification() {
+ NotificationChannel channel = null;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ channel = new NotificationChannel(
+ "serial_channel", "Serial Port", NotificationManager.IMPORTANCE_LOW);
+
+ getSystemService(NotificationManager.class).createNotificationChannel(channel);
+
+ Notification notification = new Notification.Builder(this, "serial_channel")
+ .setContentTitle("Serial Port Active")
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .build();
+
+ startForeground(1, notification);
+ }
+
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) { return null; }
+}
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 c8a9668..94d07af 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
@@ -7,6 +7,8 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.kizzy.cmhl.EcrManager;
+import com.kizzy.cmhl.models.SaleResponse;
import com.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum;
import com.utsmm.kbz.ui.pinpad.PinPadViewModel;
import com.utsmm.kbz.util.TransactionUtil;
@@ -20,7 +22,9 @@ import com.utsmyanmar.checkxread.readcard.MPUXReadCard;
import com.utsmyanmar.checkxread.readcard.ReadCardResultX;
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.checkxread.util.CardTypeX;
+import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.paylibs.model.TradeData;
+import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
@@ -109,10 +113,25 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
private void finishECR() {
sharedViewModel.isEcr.postValue(false);
- CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getResourceString(R.string.txt_cancel_trans));
sharedViewModel.isEcrFinished.postValue(true);
+
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRHelper.INSTANCE.send(generateCHMLResponse());
+// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+ } else {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getResourceString(R.string.txt_cancel_trans));
+ }
}
+ private byte[] generateCHMLResponse() {
+ SaleResponse saleResponse = new SaleResponse.Builder()
+ .setResponseCode("FF")
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(SystemDateTime.getMMDD())
+ .build();
+
+ return EcrManager.buildPacket(saleResponse);
+ }
public class ClickEvent {
@@ -362,8 +381,15 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false);
- CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.isEcrFinished.postValue(true);
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRHelper.INSTANCE.send(generateCHMLResponse());
+
+// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+ } else {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
+ }
+
}
}
}
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 babb908..f0d2574 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
@@ -11,6 +11,8 @@ import androidx.appcompat.app.AlertDialog;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
+import com.kizzy.cmhl.EcrManager;
+import com.kizzy.cmhl.models.SaleResponse;
import com.utsmm.kbz.ui.core_viewmodel.CardReadViewModel;
import com.utsmm.kbz.ui.pinpad.PinPadViewModel;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
@@ -20,8 +22,10 @@ import com.utsmyanmar.baselib.util.CardDetectCallback;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.checkxread.util.CardTypeX;
+import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
+import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
@@ -392,17 +396,36 @@ public class EmvTransactionFragment extends DataBindingFragment {
}
+ ECRActionCancel(ecrErrorMsg);
navigateToError();
});
}
+ private byte[] generateCHMLResponse() {
+ SaleResponse saleResponse = new SaleResponse.Builder()
+ .setResponseCode("FF")
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(SystemDateTime.getMMDD())
+ .build();
+
+ return EcrManager.buildPacket(saleResponse);
+ }
+
private void ECRActionCancel(String message) {
if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) {
LogUtil.d(TAG, "isECR true");
sharedViewModel.isEcrFinished.postValue(true);
- CoreUtils.getInstance(sharedViewModel).responseRejectMsg(message);
+ sharedViewModel.isEcr.postValue(false);
+
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRHelper.INSTANCE.send(generateCHMLResponse());
+// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+ } else {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(message);
+ }
+
if (isEmvTrans()) {
emvTransactionViewModel.onCancelEmvTransaction();
@@ -411,6 +434,7 @@ public class EmvTransactionFragment extends DataBindingFragment {
}
+
private boolean isEmvTrans() {
return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue();
}
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..16cea4a 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
@@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
+import com.utsmm.kbz.util.ecr.ECRResultStatus;
import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptCardRequest;
@@ -17,6 +18,7 @@ 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.ecr.ECRHelper;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
@@ -238,15 +240,26 @@ public class ProcessingFragment extends DataBindingFragment {
if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false);
- CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
+
sharedViewModel.isEcrFinished.postValue(true);
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRHelper.INSTANCE.send(getECRResponseCMHL());
+
+// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+ } else {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
+ }
+
if(isEmvTrans()) {
emvTransactionProcessViewModel.onCancelEmvTransaction();
}
}
}
+ private byte[] getECRResponseCMHL() {
+ return CoreUtils.getInstance(sharedViewModel).generateCMHLResponse(ECRResultStatus.TIME_OUT);
+ }
private void navigateToError() {
routeId = R.id.action_processingFragment_to_errorFragment;
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 2bf8be7..ac583a0 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
@@ -10,6 +10,7 @@ import androidx.appcompat.app.AppCompatActivity;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.MalformedJsonException;
+import com.utsmm.kbz.util.ecr.ECRResultStatus;
import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusError;
@@ -29,6 +30,7 @@ import com.utsmyanmar.paylibs.print.PaperRollStatusCallback;
import com.utsmyanmar.paylibs.print.PrintHelper;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
import com.utsmyanmar.paylibs.utils.PrintStatus;
+import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
@@ -423,10 +425,23 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
return ECRProcess.INSTANCE.generateECRResponse(resp);
}
+ private byte[] getECRResponseCMHL() {
+ return CoreUtils.getInstance(sharedViewModel).generateCMHLResponse(ECRResultStatus.RESPONSE_RECEIVED);
+ }
private void ecrAction() {
- LogUtil.d(TAG,"ECR Response :"+getECRResponseMessage());
- ECRHelper.INSTANCE.send(getECRResponseMessage().getBytes());
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ LogUtil.d(TAG,"ECR Response :"+ ByteUtil.bytes2HexStr(getECRResponseCMHL()));
+
+ ECRHelper.INSTANCE.send(getECRResponseCMHL());
+
+
+ } else {
+ LogUtil.d(TAG,"ECR Response :"+getECRResponseMessage());
+
+ ECRHelper.INSTANCE.send(getECRResponseMessage().getBytes());
+ }
+
ECRHelper.INSTANCE.setOnBindSuccess(() -> {
LogUtil.d(TAG, "Send Success!");
@@ -435,6 +450,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
}
+
@Override
public void onBackPress() {
isCardInside();
diff --git a/app/src/main/java/com/utsmm/kbz/ui/kpay/QRConnectingFragment.java b/app/src/main/java/com/utsmm/kbz/ui/kpay/QRConnectingFragment.java
index c5128f6..20d3e10 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/kpay/QRConnectingFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/kpay/QRConnectingFragment.java
@@ -7,6 +7,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.github.gcacace.signaturepad.BR;
+import com.kizzy.cmhl.EcrManager;
+import com.kizzy.cmhl.models.QrPaymentResponse;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.DemoQRRequest;
import com.utsmyanmar.baselib.network.model.KPayQRRequest;
@@ -17,7 +19,9 @@ import com.utsmyanmar.ecr.ECRProcess;
import com.utsmyanmar.ecr.data.model.TransactionsResp;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
+import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.POSUtil;
+import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
@@ -220,8 +224,11 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
private void ecrAction() {
- LogUtil.d(TAG,"ECR Response :"+getECRResponseMessage());
- ECRHelper.INSTANCE.send(getECRResponseMessage().getBytes());
+ if(!SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ LogUtil.d(TAG,"ECR Response :"+getECRResponseMessage());
+ ECRHelper.INSTANCE.send(getECRResponseMessage().getBytes());
+ }
+
ECRHelper.INSTANCE.setOnBindSuccess(() -> {
LogUtil.d(TAG, "Send Success!");
@@ -237,7 +244,14 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
private void finishECR() {
sharedViewModel.isEcr.postValue(false);
- CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getResourceString(R.string.txt_cancel_trans));
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRHelper.INSTANCE.send(generateCHMLResponse());
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+ } else {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getResourceString(R.string.txt_cancel_trans));
+ }
+
sharedViewModel.isEcrFinished.postValue(true);
}
@@ -246,8 +260,15 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false);
- CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.isEcrFinished.postValue(true);
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRHelper.INSTANCE.send(generateCHMLResponse());
+
+ CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+ } else {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
+ }
+
}
}
}
@@ -261,6 +282,16 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
return ECRProcess.INSTANCE.generateECRResponse(resp);
}
+ private byte[] generateCHMLResponse() {
+ QrPaymentResponse qrPaymentResponse = new QrPaymentResponse.Builder()
+ .setResponseCode("FF")
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(SystemDateTime.getMMDD())
+ .build();
+
+ return EcrManager.buildPacket(qrPaymentResponse);
+ }
+
@Override
public void onBackPress() {
if (sharedViewModel.isEcr.getValue() != null) {
diff --git a/app/src/main/java/com/utsmm/kbz/ui/kpay/QRTransactionFragment.java b/app/src/main/java/com/utsmm/kbz/ui/kpay/QRTransactionFragment.java
index 7a490ed..39aba37 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/kpay/QRTransactionFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/kpay/QRTransactionFragment.java
@@ -9,6 +9,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.kizzy.cmhl.EcrManager;
+import com.kizzy.cmhl.models.QrPaymentResponse;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmm.kbz.util.enums.TransResultStatus;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
@@ -21,6 +23,7 @@ import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.ecr.ECRProcess;
import com.utsmyanmar.ecr.data.model.TransactionsResp;
import com.utsmyanmar.paylibs.model.PayDetail;
+import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.R;
import com.utsmm.kbz.BR;
@@ -163,8 +166,24 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
private void finishECR() {
sharedViewModel.isEcr.postValue(false);
- CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getResourceString(R.string.txt_cancel_trans));
sharedViewModel.isEcrFinished.postValue(true);
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRHelper.INSTANCE.send(generateCHMLResponse());
+
+// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+ } else {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getResourceString(R.string.txt_cancel_trans));
+ }
+ }
+
+ private byte[] generateCHMLResponse() {
+ QrPaymentResponse qrPaymentResponse = new QrPaymentResponse.Builder()
+ .setResponseCode("FF")
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(SystemDateTime.getMMDD())
+ .build();
+
+ return EcrManager.buildPacket(qrPaymentResponse);
}
private void ecrActionCancel(String msg) {
@@ -476,6 +495,8 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
);
}
+
+
private String getECRResponseMessage() {
sharedViewModel.payDetail.setValue(payDetail);
@@ -485,7 +506,6 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
return ECRProcess.INSTANCE.generateECRResponse(resp);
}
-
private void ecrAction() {
LogUtil.d(TAG, "ECR Response :" + getECRResponseMessage());
diff --git a/app/src/main/java/com/utsmm/kbz/ui/pinpad/PinPadFragment.java b/app/src/main/java/com/utsmm/kbz/ui/pinpad/PinPadFragment.java
index 349a318..d430656 100644
--- a/app/src/main/java/com/utsmm/kbz/ui/pinpad/PinPadFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/ui/pinpad/PinPadFragment.java
@@ -9,12 +9,14 @@ import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
+import com.utsmm.kbz.util.ecr.ECRResultStatus;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
//import com.utsmyanmar.mpulib.readcard.ReadCardProcess;
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
+import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.utils.POSUtil;
@@ -27,6 +29,7 @@ import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.core_viewmodel.TransProcessViewModel;
import com.utsmm.kbz.util.ecr.CoreUtils;
import com.utsmm.kbz.util.enums.PinPadStatus;
+import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
public class PinPadFragment extends DataBindingFragment {
@@ -157,13 +160,27 @@ public class PinPadFragment extends DataBindingFragment {
});
}
+ private byte[] getECRResponseCMHL() {
+ return CoreUtils.getInstance(sharedViewModel).generateCMHLResponse(ECRResultStatus.USER_CANCEL);
+ }
private void ecrActionCancel(String msg) {
if (sharedViewModel.isEcr.getValue() != null) {
if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false);
- CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
+
+ sharedViewModel.payDetail.setValue(pinPadViewModel.getPayDetail());
+
sharedViewModel.isEcrFinished.postValue(true);
+
+ if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
+ ECRHelper.INSTANCE.send(getECRResponseCMHL());
+
+// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
+ } else {
+ CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
+ }
+
}
}
}
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..73b32c4 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,7 @@ 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/java/com/utsmm/kbz/util/ecr/CoreUtils.java b/app/src/main/java/com/utsmm/kbz/util/ecr/CoreUtils.java
index e5e6666..17716f5 100644
--- a/app/src/main/java/com/utsmm/kbz/util/ecr/CoreUtils.java
+++ b/app/src/main/java/com/utsmm/kbz/util/ecr/CoreUtils.java
@@ -4,12 +4,30 @@ import android.annotation.SuppressLint;
import android.text.TextUtils;
import android.util.Log;
+import com.kizzy.cmhl.EcrManager;
+import com.kizzy.cmhl.models.PingRequest;
+import com.kizzy.cmhl.models.PingResponse;
+import com.kizzy.cmhl.models.PreAuthCancellationRequest;
+import com.kizzy.cmhl.models.PreAuthCompletionRequest;
+import com.kizzy.cmhl.models.PreAuthCompletionResponse;
+import com.kizzy.cmhl.models.PreAuthRequest;
+import com.kizzy.cmhl.models.PreAuthResponse;
+import com.kizzy.cmhl.models.QrPaymentRequest;
+import com.kizzy.cmhl.models.QrPaymentResponse;
+import com.kizzy.cmhl.models.SaleRequest;
+import com.kizzy.cmhl.models.SaleResponse;
+import com.kizzy.cmhl.models.SettlementRequest;
+import com.kizzy.cmhl.models.SettlementResponse;
+import com.kizzy.cmhl.models.VoidQrPaymentRequest;
+import com.kizzy.cmhl.models.VoidRequest;
+import com.kizzy.cmhl.models.VoidResponse;
import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.ecr.ECRProcess;
import com.utsmyanmar.ecr.data.RespType;
import com.utsmyanmar.ecr.data.model.Transactions;
import com.utsmyanmar.ecr.data.model.TransactionsResp;
import com.utsmyanmar.paylibs.model.PayDetail;
+import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
@@ -25,7 +43,7 @@ import com.utsmyanmar.paylibs.utils.LogUtil;
//@Keep
-public class CoreUtils implements OldECRSetups,ECRSetups {
+public class CoreUtils implements OldECRSetups,ECRSetups,ECRSetupsCMHL {
private static final String TAG = CoreUtils.class.getSimpleName();
@@ -166,7 +184,9 @@ public class CoreUtils implements OldECRSetups,ECRSetups {
return resp;
}
-
+ public void responseACKCMHL() {
+ ECRHelper.INSTANCE.send(new byte[]{0x06});
+ }
public void responseRejectMsg(String actionName) {
@@ -215,6 +235,183 @@ public class CoreUtils implements OldECRSetups,ECRSetups {
ECRResponseAction(msg);
}
+ @Override
+ public void setupPingRequest(PingRequest trans) {
+ PingResponse pingResponse = new PingResponse.Builder()
+ .setResponseCode("00")
+ .build();
+
+ byte[] packet = EcrManager.buildPacket(pingResponse);
+ ECRHelper.INSTANCE.send(packet);
+ }
+
+ @Override
+ public boolean setUpECRSale(SaleRequest trans) {
+ try{
+
+ LogUtil.d(TAG, "amount is "+trans.getAmount());
+ if (trans.getAmount() == null && Long.parseLong(trans.getAmount()) <= 0) {
+
+ LogUtil.d(TAG,"Amount field is invalid!");
+ return false;
+ }
+
+// int amount = reduceTrailingZeros(trans.getAMT());
+
+ long amount = Long.parseLong(trans.getAmount());
+
+ sharedViewModel.isEcrFinished.postValue(false);
+ sharedViewModel.isEcr.postValue(true);
+ sharedViewModel.amount.postValue(String.valueOf(amount));
+ sharedViewModel.transactionsType.postValue(TransactionsType.SALE);
+ sharedViewModel.processCode.postValue(ProcessCode.SALE_PURCHASE + ProcessCode.SMART + ProcessCode.TO_ACCOUNT);
+ return true;
+ }catch (Exception e){
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setUpECRQR(QrPaymentRequest trans) {
+ try{
+
+ LogUtil.d(TAG, "amount is "+trans.getAmount());
+ if (trans.getAmount() == null && Long.parseLong(trans.getAmount()) <= 0) {
+
+ LogUtil.d(TAG,"Amount field is invalid!");
+ return false;
+ }
+
+ long amount = Long.parseLong(trans.getAmount());
+
+ sharedViewModel.isEcrFinished.postValue(false);
+ sharedViewModel.isEcr.postValue(true);
+ sharedViewModel.amount.postValue(String.valueOf(amount));
+ sharedViewModel.transactionsType.postValue(TransactionsType.MMQR);
+ return true;
+ }catch (Exception e){
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setUpECRQRVoid(VoidQrPaymentRequest trans) {
+ return false;
+ }
+
+ @Override
+ public boolean setUpECRVoid(VoidRequest trans) {
+ try{
+ if (trans.getInvoiceNumber()== null && trans.getInvoiceNumber().isEmpty()) {
+ LogUtil.d(TAG,"Trace field is invalid!");
+ return false;
+ }
+
+ sharedViewModel.isEcrFinished.postValue(false);
+ sharedViewModel.isEcr.postValue(true);
+ sharedViewModel.traceNo.postValue(trans.getInvoiceNumber());
+ sharedViewModel.transactionName.postValue("SALE");
+ sharedViewModel.transactionsType.postValue(TransactionsType.VOID);
+ sharedViewModel.processCode.postValue(ProcessCode.SALE_VOID + ProcessCode.SMART + ProcessCode.TO_ACCOUNT);
+ return true;
+ }catch (Exception e){
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setUpECRPreAuth(PreAuthRequest trans) {
+ try{
+
+ LogUtil.d(TAG, "amount is "+trans.getAmount());
+ if (trans.getAmount() == null && Long.parseLong(trans.getAmount()) <= 0) {
+
+ LogUtil.d(TAG,"Amount field is invalid!");
+ return false;
+ }
+
+// int amount = reduceTrailingZeros(trans.getAMT());
+
+ long amount = Long.parseLong(trans.getAmount());
+
+ sharedViewModel.isEcrFinished.postValue(false);
+ sharedViewModel.isEcr.postValue(true);
+ sharedViewModel.amount.postValue(String.valueOf(amount));
+ sharedViewModel.transactionsType.postValue(TransactionsType.PRE_AUTH_SALE);
+ sharedViewModel.processCode.postValue(ProcessCode.PRE_AUTH_SALE + ProcessCode.SMART + ProcessCode.TO_ACCOUNT);
+ return true;
+ }catch (Exception e){
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setUpECRPreAuthVoid(PreAuthCancellationRequest trans) {
+ try{
+
+ LogUtil.d(TAG, "approval code is "+trans.getApprovalCode());
+ LogUtil.d(TAG, "reference num is "+trans.getApprovalCode());
+ if (trans.getApprovalCode() == null ) {
+
+ LogUtil.d(TAG,"Amount field is invalid!");
+ return false;
+ }
+
+// int amount = reduceTrailingZeros(trans.getAMT());
+
+ String approval = trans.getApprovalCode();
+ String rrn = trans.getReferenceNumber();
+ String cardType = trans.getCardType();
+
+ sharedViewModel.isEcrFinished.postValue(false);
+ sharedViewModel.isEcr.postValue(true);
+ sharedViewModel.rrNNo.postValue(rrn);
+ sharedViewModel.approvalCode.postValue(approval);
+
+ sharedViewModel.transactionsType.postValue(TransactionsType.PRE_AUTH_VOID);
+ sharedViewModel.processCode.postValue(ProcessCode.PRE_AUTH_VOID + ProcessCode.SMART + ProcessCode.TO_ACCOUNT);
+ return true;
+ }catch (Exception e){
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setUpECRPreAuthComplete(PreAuthCompletionRequest trans) {
+ try{
+
+ LogUtil.d(TAG, "approval code is "+trans.getApprovalCode());
+ LogUtil.d(TAG, "reference num is "+trans.getApprovalCode());
+ if (trans.getApprovalCode() == null ) {
+
+ LogUtil.d(TAG,"Amount field is invalid!");
+ return false;
+ }
+
+// int amount = reduceTrailingZeros(trans.getAMT());
+
+ String approval = trans.getApprovalCode();
+ String rrn = trans.getReferenceNumber();
+ String cardType = trans.getCardType();
+
+ sharedViewModel.isEcrFinished.postValue(false);
+ sharedViewModel.isEcr.postValue(true);
+ sharedViewModel.rrNNo.postValue(rrn);
+ sharedViewModel.approvalCode.postValue(approval);
+
+ sharedViewModel.transactionsType.postValue(TransactionsType.PRE_AUTH_COMPLETE);
+ sharedViewModel.processCode.postValue(ProcessCode.PRE_AUTH_COMPLETE + ProcessCode.SMART + ProcessCode.TO_ACCOUNT);
+ return true;
+ }catch (Exception e){
+ return false;
+ }
+ }
+
+ @Override
+ public void setUpECRSettlement(SettlementRequest trans) {
+
+ }
+
@Override
public boolean setUpECRSale(Transactions trans) {
@@ -661,4 +858,219 @@ public class CoreUtils implements OldECRSetups,ECRSetups {
sharedViewModel.processCode.postValue(ProcessCode.REFUND + ProcessCode.SMART + ProcessCode.TO_ACCOUNT);
return true;
}
+
+ public byte[] generateCMHLResponse(ECRResultStatus ecrResultStatus) {
+ Transactions trans = sharedViewModel.ecrTrans.getValue();
+ PayDetail payDetail = sharedViewModel.payDetail.getValue();
+ TransactionsType transactionsType = sharedViewModel.transactionsType.getValue();
+
+ boolean isApproved = false;
+
+ if(payDetail.getTradeAnswerCode() != null) {
+ isApproved = TextUtils.equals(payDetail.getTradeAnswerCode(),"000") || TextUtils.equals(payDetail.getTradeAnswerCode(),"00");
+ }
+// boolean isApproved = TextUtils.equals(payDetail.getTradeAnswerCode(),"000") || TextUtils.equals(payDetail.getTradeAnswerCode(),"00");
+
+ byte[] responsePacket;
+ switch (transactionsType) {
+ case SALE:
+ SaleResponse response;
+ if(ecrResultStatus == ECRResultStatus.RESPONSE_RECEIVED) {
+
+
+ if (isApproved) {
+ response = new SaleResponse.Builder()
+ .setResponseCode(POSUtil.getInstance().responseCodeConverter(payDetail.getTradeAnswerCode()))
+ .setAmount(POSUtil.getInstance().formatAmount(payDetail.getAmount()))
+ .setPan(payDetail.getCardNo())
+ .setExpDate(payDetail.getEXPDate())
+ .setTid(payDetail.getTerminalNo())
+ .setMid(payDetail.getMerchantNo())
+ .setTime(SystemDateTime.getHHmmss()) // for urgent testing purpose
+ .setDate(payDetail.getTradeDate())
+ .setReferenceNum(payDetail.getReferNo())
+ .setApprovalCode(payDetail.getApprovalCode())
+ .setInvoiceNumber(payDetail.getInvoiceNo())
+ .setStan(payDetail.getVoucherNo())
+ .setEntry(POSUtil.getInstance().getEntryCode(payDetail))
+ .setCardType(POSUtil.getInstance().getCardType(payDetail))
+ .setCurrency(payDetail.getCurrencyCode())
+ .build();
+ } else {
+ response = new SaleResponse.Builder()
+ .setResponseCode(POSUtil.getInstance().responseCodeConverter(payDetail.getTradeAnswerCode()))
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ }
+ } else if(ecrResultStatus == ECRResultStatus.USER_CANCEL){
+
+ response = new SaleResponse.Builder()
+ .setResponseCode("FF")
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ } else {
+ response = new SaleResponse.Builder()
+ .setResponseCode("FF")
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ }
+
+ responsePacket = EcrManager.buildPacket(response);
+ break;
+ case VOID:
+ VoidResponse voidResponse;
+ if(ecrResultStatus == ECRResultStatus.RESPONSE_RECEIVED) {
+ if (isApproved) {
+ voidResponse = new VoidResponse.Builder()
+ .setResponseCode(POSUtil.getInstance().responseCodeConverter(payDetail.getTradeAnswerCode()))
+ .setAmount(POSUtil.getInstance().formatAmount(payDetail.getAmount()))
+ .setVoucherNumber(payDetail.getVoucherNo())
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .setApprovalCode(payDetail.getApprovalCode())
+ .setReferenceNum(payDetail.getReferNo())
+ .setTid(payDetail.getTerminalNo())
+ .setMid(payDetail.getMerchantNo())
+ .setEntry(POSUtil.getInstance().getEntryCode(payDetail))
+ .build();
+ } else {
+ voidResponse = new VoidResponse.Builder()
+ .setResponseCode(POSUtil.getInstance().responseCodeConverter(payDetail.getTradeAnswerCode()))
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ }
+ } else if (ecrResultStatus == ECRResultStatus.USER_CANCEL) {
+ voidResponse = new VoidResponse.Builder()
+ .setResponseCode("FF")
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ } else {
+ voidResponse = new VoidResponse.Builder()
+ .setResponseCode("NR")
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ }
+
+
+ responsePacket = EcrManager.buildPacket(voidResponse);
+ break;
+ case SETTLEMENT:
+ SettlementResponse settlementResponse = new SettlementResponse.Builder()
+ .setResponseCode(POSUtil.getInstance().responseCodeConverter(payDetail.getTradeAnswerCode()))
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .setTid(payDetail.getTerminalNo())
+ .setMid(payDetail.getMerchantNo())
+ .build();
+ responsePacket = EcrManager.buildPacket(settlementResponse);
+ break;
+ case MMQR:
+ QrPaymentResponse qrPaymentRequest;
+ if(payDetail.getQrTransStatus() == 1) {
+ qrPaymentRequest = new QrPaymentResponse.Builder()
+ .setResponseCode("00")
+ .setAmount(POSUtil.getInstance().formatAmount(payDetail.getAmount()))
+ .setPan("0000000000000000000")
+ .setExpDate("0000")
+ .setTid(payDetail.getTerminalNo())
+ .setMid(payDetail.getMerchantNo())
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(payDetail.getTradeDate())
+ .setApprovalCode(payDetail.getQrTransId().substring(2,8))
+ .setRrn(payDetail.getQrReferNo())
+ .setPosEntryMode("000")
+ .setInvoiceNumber(payDetail.getInvoiceNo())
+ .setStan(payDetail.getVoucherNo())
+ .setPaymentType(payDetail.getCustomerMobile())
+ .setCurrencyCode(payDetail.getCurrencyCode())
+ .build();
+ } else {
+ qrPaymentRequest = new QrPaymentResponse.Builder()
+ .setResponseCode("05")
+ .setTime(SystemDateTime.getHHmmss())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ }
+
+ responsePacket = EcrManager.buildPacket(qrPaymentRequest);
+ break;
+// case WAVEPAY_REFUND:
+// break;
+ case PRE_AUTH_SALE:
+ PreAuthResponse preAuthResponse;
+ if(isApproved) {
+ preAuthResponse = new PreAuthResponse.Builder()
+ .setResponseCode(payDetail.getTradeAnswerCode())
+ .setAmount(POSUtil.getInstance().formatAmount(payDetail.getAmount()))
+ .setPan(payDetail.getCardNo())
+ .setTid(payDetail.getTerminalNo())
+ .setMid(payDetail.getMerchantNo())
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .setApprovalCode(payDetail.getApprovalCode())
+ .setInvoiceNumber(payDetail.getInvoiceNo())
+ .setStan(payDetail.getVoucherNo())
+ .setRrn(payDetail.getReferNo())
+ .setEntry(POSUtil.getInstance().getEntryCode(payDetail))
+ .setCardType(POSUtil.getInstance().getCardType(payDetail))
+ .build();
+ } else {
+ preAuthResponse = new PreAuthResponse.Builder()
+ .setResponseCode(payDetail.getTradeAnswerCode())
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ }
+
+ responsePacket = EcrManager.buildPacket(preAuthResponse);
+ break;
+ case PRE_AUTH_COMPLETE:
+ PreAuthCompletionResponse preAuthCompletionResponse;
+ if(isApproved) {
+ preAuthCompletionResponse = new PreAuthCompletionResponse.Builder()
+ .setResponseCode(payDetail.getTradeAnswerCode())
+ .setAmount(POSUtil.getInstance().formatAmount(payDetail.getAmount()))
+ .setPan(payDetail.getCardNo())
+ .setTid(payDetail.getTerminalNo())
+ .setMid(payDetail.getMerchantNo())
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .setApprovalCode(payDetail.getApprovalCode())
+ .setInvoiceNumber(payDetail.getInvoiceNo())
+ .setStan(payDetail.getVoucherNo())
+ .setRrn(payDetail.getReferNo())
+ .setEntry(POSUtil.getInstance().getEntryCode(payDetail))
+ .build();
+ } else {
+ preAuthCompletionResponse = new PreAuthCompletionResponse.Builder()
+ .setResponseCode(payDetail.getTradeAnswerCode())
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .build();
+ }
+
+ responsePacket = EcrManager.buildPacket(preAuthCompletionResponse);
+ break;
+ default:
+ SaleResponse saleResponses = new SaleResponse.Builder()
+ .setResponseCode(payDetail.getTradeAnswerCode())
+ .setTime(payDetail.getTradeTime())
+ .setDate(payDetail.getTradeDate())
+ .build();
+
+
+ responsePacket = EcrManager.buildPacket(saleResponses);
+ break;
+ }
+
+
+ return responsePacket;
+
+ }
}
diff --git a/app/src/main/java/com/utsmm/kbz/util/ecr/ECRResultStatus.java b/app/src/main/java/com/utsmm/kbz/util/ecr/ECRResultStatus.java
new file mode 100644
index 0000000..693eae3
--- /dev/null
+++ b/app/src/main/java/com/utsmm/kbz/util/ecr/ECRResultStatus.java
@@ -0,0 +1,12 @@
+package com.utsmm.kbz.util.ecr;
+
+public enum ECRResultStatus {
+
+
+ USER_CANCEL,
+ TIME_OUT,
+
+ RESPONSE_RECEIVED
+
+
+}
diff --git a/app/src/main/java/com/utsmm/kbz/util/ecr/ECRSetupsCMHL.java b/app/src/main/java/com/utsmm/kbz/util/ecr/ECRSetupsCMHL.java
new file mode 100644
index 0000000..a0afd10
--- /dev/null
+++ b/app/src/main/java/com/utsmm/kbz/util/ecr/ECRSetupsCMHL.java
@@ -0,0 +1,35 @@
+package com.utsmm.kbz.util.ecr;
+
+
+import com.kizzy.cmhl.models.PingRequest;
+import com.kizzy.cmhl.models.PreAuthCancellationRequest;
+import com.kizzy.cmhl.models.PreAuthCompletionRequest;
+import com.kizzy.cmhl.models.PreAuthRequest;
+import com.kizzy.cmhl.models.QrPaymentRequest;
+import com.kizzy.cmhl.models.SaleRequest;
+import com.kizzy.cmhl.models.SettlementRequest;
+import com.kizzy.cmhl.models.VoidQrPaymentRequest;
+import com.kizzy.cmhl.models.VoidRequest;
+
+public interface ECRSetupsCMHL {
+
+ void setUpECREchoTest();
+
+ void setupPingRequest(PingRequest trans);
+
+ boolean setUpECRSale(SaleRequest trans);
+
+ boolean setUpECRQR(QrPaymentRequest trans);
+ boolean setUpECRQRVoid(VoidQrPaymentRequest trans);
+
+ boolean setUpECRVoid(VoidRequest trans);
+
+ boolean setUpECRPreAuth(PreAuthRequest trans);
+
+ boolean setUpECRPreAuthVoid(PreAuthCancellationRequest trans);
+
+ boolean setUpECRPreAuthComplete(PreAuthCompletionRequest trans);
+
+ void setUpECRSettlement(SettlementRequest trans);
+
+}
diff --git a/app/src/main/java/com/utsmm/kbz/util/tms/TMSSetupsImpl.java b/app/src/main/java/com/utsmm/kbz/util/tms/TMSSetupsImpl.java
index e3d9e11..a789467 100644
--- a/app/src/main/java/com/utsmm/kbz/util/tms/TMSSetupsImpl.java
+++ b/app/src/main/java/com/utsmm/kbz/util/tms/TMSSetupsImpl.java
@@ -649,6 +649,8 @@ public class TMSSetupsImpl implements TMSSetups{
}
else if(TextUtils.equals(name, "printer_enabled")){
SystemParamsOperation.getInstance().setPrinterEnabled(parseBoolean(data));
+ } else if (TextUtils.equals(name,"cmhl_enabled")) {
+ SystemParamsOperation.getInstance().setCMHLEnable(parseBoolean(data));
}
}
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 4d31828..f836b2c 100644
--- a/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java
+++ b/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java
@@ -316,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();
@@ -751,6 +751,10 @@ 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:
diff --git a/ecr/build.gradle b/ecr/build.gradle
index 1892cc1..3a52af9 100644
--- a/ecr/build.gradle
+++ b/ecr/build.gradle
@@ -34,7 +34,7 @@ dependencies {
// implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
-
+ implementation project(path: ':nexsdk-lib')
// implementation files('libs/ecr-service-lib-1.1.11.aar')
implementation project(path: ':ecr-service-lib')
implementation project(path: ':paylibs')
diff --git a/ecr/src/main/java/com/utsmyanmar/ecr/ECRHelper.kt b/ecr/src/main/java/com/utsmyanmar/ecr/ECRHelper.kt
index 3e6ce3e..c24cf8d 100644
--- a/ecr/src/main/java/com/utsmyanmar/ecr/ECRHelper.kt
+++ b/ecr/src/main/java/com/utsmyanmar/ecr/ECRHelper.kt
@@ -1,19 +1,25 @@
package com.utsmyanmar.ecr
+import android.content.Context
import android.os.Bundle
import android.widget.Toast
+import com.nexgo.oaf.apiv3.APIProxy
+import com.nexgo.oaf.apiv3.SdkResult
+import com.nexgo.oaf.apiv3.device.serialport.SerialCfgEntity
+import com.nexgo.oaf.apiv3.device.serialport.SerialPortDriver
import com.pos.connection.bridge.ECRConnection
import com.pos.connection.bridge.ECRListener
import com.pos.connection.bridge.ECRRequestCallback
import com.pos.connection.bridge.ECRService
import com.pos.hardware.connection.library.ECRServiceKernel
+import com.utsmyanmar.paylibs.utils.LogUtil
import java.nio.charset.StandardCharsets
-
object ECRHelper {
val TAG = ECRHelper::class.java.simpleName
private var ecrService: ECRService? = null
+ private var serialPort: SerialPortDriver? = null
var onBindSuccess: () -> Unit = { }
var onBindFailure: () -> Unit = { }
@@ -26,6 +32,70 @@ object ECRHelper {
var onECRReceive: (bytes: ByteArray) -> Unit = { }
+ // ─── Serial Port Init (call this once, e.g. in Application or Activity) ───
+
+ fun initSerialPort(context: Context) {
+ try {
+ val deviceEngine = APIProxy.getDeviceEngine(context)
+ val port = deviceEngine.getSerialPortDriver(0)
+
+ val entity = SerialCfgEntity().apply {
+ baudRate = 115200
+ dataBits = 8
+ parity = 'n'
+ stopBits = 1
+ }
+
+ val result = port.connect(entity)
+ if (result == SdkResult.Success) {
+ serialPort = port
+ LogUtil.d(TAG, "USB Serial connected")
+ } else {
+ LogUtil.e(TAG, "USB Serial connect failed: $result")
+ onSendFailure(result, "Serial port connect failed")
+ }
+ } catch (ex: Throwable) {
+ ex.printStackTrace()
+ onSendFailure(-200, ex.localizedMessage ?: "Serial init error")
+ }
+ }
+
+ fun releaseSerialPort() {
+ try {
+ serialPort?.disconnect()
+ } catch (ex: Throwable) {
+ ex.printStackTrace()
+ } finally {
+ serialPort = null
+ }
+ }
+
+ // ─── Send: uses Serial Port instead of ECRService ─────────────────────────
+
+ fun send(bytes: ByteArray) {
+ try {
+ val port = serialPort
+ if (port != null) {
+ val result = port.send(bytes, bytes.size)
+ if (result == SdkResult.Success) {
+ LogUtil.d(TAG, "Serial send success")
+ onSendSuccess()
+ } else {
+ LogUtil.e(TAG, "Serial send failed: $result")
+ onSendFailure(result, "Serial send failed")
+ }
+ } else {
+ LogUtil.e(TAG, "Serial port not initialized")
+ onSendFailure(-100, "Serial port not initialized")
+ }
+ } catch (ex: Throwable) {
+ ex.printStackTrace()
+ onSendFailure(-200, ex.localizedMessage ?: "")
+ }
+ }
+
+ // ─── Everything below is unchanged ────────────────────────────────────────
+
fun connect(bundle: Bundle) {
call {
anyExecute(ecrService) {
@@ -51,59 +121,39 @@ object ECRHelper {
}
private val ecrListener = object : ECRListener.Stub() {
-
- override fun onReceive(byteArray: ByteArray ? ) {
+ override fun onReceive(byteArray: ByteArray?) {
if (byteArray != null) {
val string = String(byteArray, StandardCharsets.UTF_8)
Logger.e(TAG, "onReceive string: $string")
onECRReceive(byteArray)
}
}
-
- }
-
- fun send(bytes: ByteArray) {
- try {
- val bridgeService = ecrService
- if (bridgeService != null) {
- bridgeService.send(bytes, requestCallback)
- } else {
- onECRDisconnected(-100, "The bind ECRService failure")
- }
- } catch (ex: Throwable) {
- ex.printStackTrace()
- onSendFailure(-200, ex.localizedMessage ?: "")
- }
}
private val requestCallback = object : ECRRequestCallback.Stub() {
-
override fun onSuccess() {
Logger.e(TAG, "onSuccess")
onSendSuccess()
}
- override fun onFailure(code: Int, massage: String ? ) {
+ override fun onFailure(code: Int, massage: String?) {
Logger.e(TAG, "onFailure code: $code massage: $massage")
onSendFailure(code, massage ?: "failure")
}
-
}
private val ecrConnection = object : ECRConnection.Stub() {
-
override fun onConnected() {
Logger.d(TAG, "onConnected")
ECRUtil.connected = true
onECRConnected()
}
- override fun onDisconnected(code: Int, massage: String ? ) {
+ override fun onDisconnected(code: Int, massage: String?) {
Logger.d(TAG, "onDisconnected code: $code massage: $massage")
ECRUtil.connected = false
onECRDisconnected(code, massage ?: "failure")
}
-
}
fun bindECRService() {
@@ -111,7 +161,6 @@ object ECRHelper {
}
private val connectionCallback = object : ECRServiceKernel.ConnectionCallback {
-
override fun onServiceConnected() {
Logger.e(TAG, "onServiceConnected")
ecrService = ECRServiceKernel.getInstance().ecrService
@@ -124,7 +173,6 @@ object ECRHelper {
ecrService = null
onBindFailure()
}
-
}
private fun call(block: () -> Unit) {
@@ -140,5 +188,4 @@ object ECRHelper {
onECRDisconnected(-200, ex.localizedMessage ?: "")
}
}
-
}
\ No newline at end of file
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/system/BaseErrorCode.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/system/BaseErrorCode.java
index 3ccde43..ff14658 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/system/BaseErrorCode.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/system/BaseErrorCode.java
@@ -9,7 +9,64 @@ import java.util.Map;
public class BaseErrorCode {
+ private static final Map ISO_93_TO_87_MAP = new HashMap<>();
+ static {
+ // --- APPROVALS (000-099) ---
+ ISO_93_TO_87_MAP.put("000", "00"); // Approved
+ ISO_93_TO_87_MAP.put("001", "08"); // Honour with identification
+ ISO_93_TO_87_MAP.put("002", "10"); // Approved for partial amount
+ ISO_93_TO_87_MAP.put("003", "11"); // Approved (VIP)
+ ISO_93_TO_87_MAP.put("004", "16"); // Approved, update track 3
+ ISO_93_TO_87_MAP.put("007", "00"); // Approved, update ICC (Map to 00 generic)
+
+ // --- DECLINES: No Pickup (100-199) ---
+ ISO_93_TO_87_MAP.put("100", "05"); // Do not honour
+ ISO_93_TO_87_MAP.put("101", "54"); // Expired card (Standard 87 code is 54, sometimes 33)
+ ISO_93_TO_87_MAP.put("102", "59"); // Suspected fraud
+ ISO_93_TO_87_MAP.put("103", "60"); // Card acceptor contact acquirer
+ ISO_93_TO_87_MAP.put("104", "62"); // Restricted card
+ ISO_93_TO_87_MAP.put("105", "66"); // Call security
+ ISO_93_TO_87_MAP.put("106", "75"); // PIN tries exceeded (Also 38 in v87)
+ ISO_93_TO_87_MAP.put("107", "01"); // Refer to card issuer
+ ISO_93_TO_87_MAP.put("108", "02"); // Refer to special conditions
+ ISO_93_TO_87_MAP.put("109", "03"); // Invalid merchant
+ ISO_93_TO_87_MAP.put("110", "13"); // Invalid amount
+ ISO_93_TO_87_MAP.put("111", "14"); // Invalid card number
+ ISO_93_TO_87_MAP.put("112", "06"); // PIN required (Generic Error 06 mapped)
+ ISO_93_TO_87_MAP.put("114", "39"); // No account of type requested (No credit account)
+ ISO_93_TO_87_MAP.put("115", "40"); // Requested function not supported
+ ISO_93_TO_87_MAP.put("116", "51"); // Not sufficient funds
+ ISO_93_TO_87_MAP.put("117", "55"); // Incorrect PIN
+ ISO_93_TO_87_MAP.put("118", "56"); // No card record
+ ISO_93_TO_87_MAP.put("119", "57"); // Transaction not permitted to cardholder
+ ISO_93_TO_87_MAP.put("120", "58"); // Transaction not permitted to terminal
+ ISO_93_TO_87_MAP.put("121", "61"); // Exceeds withdrawal amount limit
+ ISO_93_TO_87_MAP.put("122", "63"); // Security violation
+ ISO_93_TO_87_MAP.put("123", "65"); // Exceeds withdrawal frequency limit
+ ISO_93_TO_87_MAP.put("125", "12"); // Card not effective (Mapped to Invalid Transaction)
+ ISO_93_TO_87_MAP.put("129", "59"); // Suspected counterfeit (Mapped to Suspected Fraud)
+
+ // --- DECLINES: Pickup Required (200-299) ---
+ ISO_93_TO_87_MAP.put("200", "04"); // Do not honour (Pickup) -> 04 Pick-up
+ ISO_93_TO_87_MAP.put("201", "33"); // Expired card (Pickup) -> 33 Expired
+ ISO_93_TO_87_MAP.put("202", "34"); // Suspected fraud (Pickup) -> 34 Suspected Fraud
+ ISO_93_TO_87_MAP.put("203", "35"); // Contact acquirer (Pickup)
+ ISO_93_TO_87_MAP.put("204", "36"); // Restricted card (Pickup)
+ ISO_93_TO_87_MAP.put("208", "41"); // Lost card
+ ISO_93_TO_87_MAP.put("209", "43"); // Stolen card
+
+ // --- SYSTEM ERRORS (900-999) ---
+ ISO_93_TO_87_MAP.put("902", "12"); // Invalid transaction
+ ISO_93_TO_87_MAP.put("903", "19"); // Re-enter transaction
+ ISO_93_TO_87_MAP.put("904", "30"); // Format error
+ ISO_93_TO_87_MAP.put("907", "91"); // Issuer or switch inoperative
+ ISO_93_TO_87_MAP.put("908", "92"); // Router not found
+ ISO_93_TO_87_MAP.put("909", "96"); // System malfunction
+ ISO_93_TO_87_MAP.put("911", "91"); // Time out (Mapped to Issuer inoperative)
+ ISO_93_TO_87_MAP.put("913", "94"); // Duplicate transmission
+ ISO_93_TO_87_MAP.put("923", "09"); // Request in progress
+ }
public static String getCode(String code) {
if (instance == null) instance = new BaseErrorCode();
@@ -25,6 +82,21 @@ public class BaseErrorCode {
}
+ public static String convert93to87(String code1993) {
+ if (code1993 == null) return "06"; // Default Error
+
+ if (ISO_93_TO_87_MAP.containsKey(code1993)) {
+ return ISO_93_TO_87_MAP.get(code1993);
+ }
+
+ if (code1993.startsWith("0")) return "00";
+
+ if (code1993.startsWith("1") || code1993.startsWith("2")) return "05";
+
+ if (code1993.startsWith("9")) return "96";
+
+ return "06"; // Default "Error" for unknown ranges
+ }
public static String getErrorMessage(String code) {
if (instance == null) instance = new BaseErrorCode();
String errorMsg = instance.errorCode.get(code);
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..ff2c949 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,7 @@ 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 +177,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 +205,7 @@ public class AuthorizationProcessUtil {
private void importOnlineProcessStatus(int sdkResult,EmvOnlineResultEntity emvOnlineResult) {
LogUtil.d(TAG, "importOnlineProcessStatus sdkResult:"+sdkResult);
LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+emvOnlineResult.toString());
+
PayLibNex.getInstance().deviceEngine.getEmvHandler2("app2").onSetOnlineProcResponse(sdkResult, emvOnlineResult);
}
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/POSUtil.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/POSUtil.java
index f22c086..ae9bf4b 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/POSUtil.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/POSUtil.java
@@ -6,9 +6,11 @@ import android.text.TextUtils;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.R;
import com.utsmyanmar.paylibs.model.PayDetail;
+import com.utsmyanmar.paylibs.model.enums.TransCVM;
import com.utsmyanmar.paylibs.system.BaseErrorCode;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.BaseCardType;
+import com.utsmyanmar.paylibs.utils.enums.CardScheme;
import com.utsmyanmar.paylibs.utils.enums.InvalidAmount;
import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
@@ -93,6 +95,33 @@ public class POSUtil {
return numberFormat.format(amount);
}
+ public String getEntryCode(PayDetail payDetail) {
+ String value;
+ if (BaseCardType.MAGNETIC.getValue() == payDetail.getCardType()) { // 磁条
+ value = "02";
+ } else if (BaseCardType.NFC.getValue() == payDetail.getCardType()) { // NFC
+ value = "07";
+ } else if (BaseCardType.IC.getValue() == payDetail.getCardType()) { // IC
+ value = "05";
+ } else if (-9 == payDetail.getCardType()){ // Fallback
+ value = "08";
+ } else { // Hand-in card number
+ value = "01";
+ }
+
+
+ if(payDetail.getTransCVM() == TransCVM.OFFLINE_PIN) {
+ value += "9";
+ } else {
+ if (payDetail.getPINCipher() != null && !payDetail.getPINCipher().trim().isEmpty()) {
+ value += "1";
+ } else {
+ value += "2";
+ }
+ }
+ return value;
+ }
+
public String getCurrentDateAndTime() {
SimpleDateFormat dfm = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault());
String currentTime = dfm.format(new Date());
@@ -124,6 +153,25 @@ public class POSUtil {
}
+ public String responseCodeConverter(String responseCode) {
+ return BaseErrorCode.convert93to87(responseCode);
+ }
+
+ public String getCardType(PayDetail payDetail) {
+ int value = 0;
+
+ if(payDetail.getAccountType().equals(CardScheme.VISA.name)) {
+ value = CardScheme.VISA.value;
+ } else if(payDetail.getAccountType().equals(CardScheme.MASTERCARD.name)) {
+ value = CardScheme.MASTERCARD.value;
+ } else if(payDetail.getAccountType().equals(CardScheme.UPI.name)) {
+ value = CardScheme.UPI.value;
+ } else if(payDetail.getAccountType().equals(CardScheme.MPU.name)) {
+ value = CardScheme.MPU.value;
+ }
+ return String.valueOf(value);
+ }
+
public String getMerchantName() {
return SystemParamsOperation.getInstance().getMerchantName();
}
@@ -135,6 +183,11 @@ public class POSUtil {
// return formatter.format(amt);
}
+ public String formatAmount(long amount) {
+
+ return String.format("%012d", amount/100);
+ }
+
public String currencyCodeToText(String currencyCode) {
String currencyText = "MMK";
switch (currencyCode) {
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsOperation.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsOperation.java
index 89b2073..028cb02 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsOperation.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsOperation.java
@@ -1761,4 +1761,15 @@ public class SystemParamsOperation {
SystemParamsSettings paramsSettings = getSystemParamsSettings();
return paramsSettings.getPrinterEnabled();
}
+
+ public void setCMHLEnable(boolean cmhlEnabled) {
+ SystemParamsSettings params = getSystemParamsSettings();
+ params.setCmhlEnabled(cmhlEnabled);
+ saveSystemParamsSettings(params);
+ }
+
+ public boolean isCMHLEnabled() {
+ SystemParamsSettings paramsSettings = getSystemParamsSettings();
+ return paramsSettings.isCmhlEnabled();
+ }
}
\ No newline at end of file
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsSettings.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsSettings.java
index 2531c0e..94e834d 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsSettings.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/core_utils/SystemParamsSettings.java
@@ -159,6 +159,8 @@ public class SystemParamsSettings implements Serializable {
private boolean fallbackEnabled = true;
+ private boolean cmhlEnabled = false;
+
private boolean manualUpdate = false;
private boolean emvEnabled = false;
@@ -484,6 +486,10 @@ public class SystemParamsSettings implements Serializable {
protected String getLastTransTime() { return lastTransTime; }
protected boolean isClearBatch() {return isClearBatch;}
+ protected boolean isCmhlEnabled() {return cmhlEnabled; }
+
+ protected void setCmhlEnabled(boolean cmhlEnabled) { this.cmhlEnabled = cmhlEnabled; }
+
protected void setClearBatch(boolean isClearBatch) {this.isClearBatch = isClearBatch;}
protected void setRandomPinPad(boolean randomPinPad) { this.isRandomPinPad = randomPinPad;}
diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/enums/CardScheme.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/enums/CardScheme.java
index bd63a94..6aa6998 100644
--- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/enums/CardScheme.java
+++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/enums/CardScheme.java
@@ -2,19 +2,22 @@ package com.utsmyanmar.paylibs.utils.enums;
public enum CardScheme {
- VISA("VISA"),
- MASTERCARD("MASTER"),
- UPI("UnionPay"),
- JCB("JCB"),
- AE("AmericanExpress"),
- MPU("MPU"),
- RUPAY("RuPay"),
- PURE("Pure"),
- MPU_CTLS("MPU Ctls");
+ VISA("VISA",1),
+ MASTERCARD("MASTER",2),
+ UPI("UnionPay",5),
+ JCB("JCB",3),
+ AE("AmericanExpress",0),
+ MPU("MPU",4),
+ RUPAY("RuPay",0),
+ PURE("Pure",0),
+ MPU_CTLS("MPU Ctls",4);
public final String name;
- CardScheme(String name){
+ public final int value;
+
+ CardScheme(String name,int value){
this.name = name;
+ this.value = value;
}
}
diff --git a/settings.gradle b/settings.gradle
index 457b0f5..53bde9e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -39,3 +39,4 @@ include ':ecr-service-lib'
include ':link-service-lib'
include ':qrgen-lib'
include ':nexdlkey-lib'
+include ':cmhl'