ECR need polish

This commit is contained in:
kizzy 2026-03-24 15:33:16 +07:00
parent f8537986ce
commit 048f802c18
27 changed files with 1265 additions and 142 deletions

View File

@ -216,6 +216,7 @@ dependencies {
implementation project(path: ':xpay') implementation project(path: ':xpay')
// implementation project(path: ':sunmiui-lib') // implementation project(path: ':sunmiui-lib')
implementation project(path: ':qrgen-lib') implementation project(path: ':qrgen-lib')
implementation project(path: ':cmhl')
//// implementation project(path: ':samlSirius') //// implementation project(path: ':samlSirius')
// Legacy ECR (kept for backward compatibility during migration) // Legacy ECR (kept for backward compatibility during migration)

View File

@ -35,6 +35,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
<uses-feature android:name="android.hardware.usb.host" /> <uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" /> <uses-permission android:name="android.permission.USB_PERMISSION" />
@ -98,7 +99,14 @@
<meta-data <meta-data
android:name="androidx.hilt.EntryPoint" android:name="androidx.hilt.EntryPoint"
android:value="androidx.hilt.lifecycle.HiltService" /> android:value="androidx.hilt.lifecycle.HiltService" />
</service> </service>
<service
android:name="com.utsmm.kbz.service.SerialPortService"
android:foregroundServiceType="connectedDevice"
android:exported="false" />
</application> </application>
</manifest> </manifest>

View File

@ -1,8 +1,13 @@
package com.utsmm.kbz; 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.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.RemoteException; import android.os.RemoteException;
@ -20,6 +25,19 @@ import androidx.lifecycle.Observer;
import com.denzcoskun.imageslider.ImageSlider; import com.denzcoskun.imageslider.ImageSlider;
import com.denzcoskun.imageslider.constants.ScaleTypes; import com.denzcoskun.imageslider.constants.ScaleTypes;
import com.denzcoskun.imageslider.models.SlideModel; 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.APIProxy;
import com.nexgo.oaf.apiv3.DeviceEngine; import com.nexgo.oaf.apiv3.DeviceEngine;
import com.nexgo.oaf.apiv3.SdkResult; 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.nexgo.oaf.apiv3.emv.CapkEntity;
//import com.pos.connection.bridge.binder.ECRConstant; //import com.pos.connection.bridge.binder.ECRConstant;
import com.utsmm.kbz.service.SerialPortService;
import com.utsmm.kbz.util.MockData; import com.utsmm.kbz.util.MockData;
//import com.utsmm.kbz.util.ecr.ModernECRFactory; //import com.utsmm.kbz.util.ecr.ModernECRFactory;
//import com.utsmm.kbz.util.ecr.ModernECRManager; //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.PrintHelper;
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt; import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
import com.utsmyanmar.paylibs.utils.POSUtil; 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.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.CurrencyType; import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
import com.utsmyanmar.paylibs.utils.enums.TransMenu; 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.ModernECRFactory;
//import com.utsmm.kbz.util.ecr.ModernECRManager; //import com.utsmm.kbz.util.ecr.ModernECRManager;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@AndroidEntryPoint @AndroidEntryPoint
public class MainFragment extends DataBindingFragment { public class MainFragment extends DataBindingFragment {
@ -134,16 +155,42 @@ public class MainFragment extends DataBindingFragment {
// modernECRManager = new ViewModelProvider(this, factory).get(ModernECRManager.class); // 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 @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
setNavBarIconWithTitle(getResourceString(R.string.menu_dashboard)); setNavBarIconWithTitle(getResourceString(R.string.menu_dashboard));
// Setup ECR Service
if(SystemParamsOperation.getInstance().getECRStatus()){
setUpECR();
}
sharedViewModel.isEcrFinished.postValue(true); sharedViewModel.isEcrFinished.postValue(true);
sharedViewModel.isEcr.postValue(false); sharedViewModel.isEcr.postValue(false);
@ -196,7 +243,33 @@ public class MainFragment extends DataBindingFragment {
safeNavigateToRouteId(); 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 @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
@ -260,68 +333,8 @@ public class MainFragment extends DataBindingFragment {
// queryAidCAPKList(); // queryAidCAPKList();
queryAidCAPKList(); queryAidCAPKList();
// generateMockQR(); // 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 * @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() { 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<Transactions> result = ECRProcess.INSTANCE.parseECRRequest(ecrKey,pkgName,serialNo,msg);
if (result instanceof ResultOf.Success) {
Transactions trans = ((ResultOf.Success<Transactions>) result).getValue();
CoreUtils.getInstance(sharedViewModel).logTrans(trans);
sharedViewModel.ecrCMD.postValue(trans.getCMD());
sharedViewModel.ecrTrans.postValue(trans);
switch (Objects.requireNonNull(trans.getCMD())) {
case ECHO:
CoreUtils.getInstance(sharedViewModel).setUpECREchoTest();
break;
case SALE:
if (CoreUtils.getInstance(sharedViewModel).setUpECRSale(trans)) {
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
}
break;
case VOID:
if(!SystemParamsOperation.getInstance().getVoidStatus()) {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(trans,"Void is disabled!");
return;
}
if (CoreUtils.getInstance(sharedViewModel).setUpECRVoid(trans)) {
delayFunctionCall(() -> {
if(Objects.requireNonNull(getNavController(Constants.NAV_HOST_ID).getCurrentDestination()).getId() == R.id.nav_main) {
setToolBarTitle(getResourceString(R.string.menu_sale_void));
}
isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_inputPasswordFragment);
});
}
break;
case CASH_ADVANCE: {
if (CoreUtils.getInstance(sharedViewModel).setUpECRCashAdvance(trans)) {
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
}
break;
}
case QR_SALE: {
if (CoreUtils.getInstance(sharedViewModel).setUpECRQR(trans)) {
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_QRConnectingFragment));
}
break;
}
case SETTLEMENT: {
if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(trans,"Settlement is disabled!");
return;
}
CoreUtils.getInstance(sharedViewModel).setUpECRSettlement();
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_inputPasswordFragment));
break;
}
default:
showDeclineDialog("No Action found on \n" + trans.getCMD());
break;
}
} else {
String errorMsg = ((ResultOf.Failure) result).getMessage();
showDeclineDialog("No Action found on \n" + errorMsg);
}
}
private void 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 class ClickEvent {
public void onClickTrans() { public void onClickTrans() {

View File

@ -1,6 +1,7 @@
package com.utsmm.kbz; package com.utsmm.kbz;
import com.utsmyanmar.baselib.BaseApplication; import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.ecr.ECRHelper;
import dagger.hilt.android.HiltAndroidApp; import dagger.hilt.android.HiltAndroidApp;
@ -21,7 +22,7 @@ public class MyApplication extends BaseApplication {
super.onCreate(); super.onCreate();
app = this; app = this;
ECRHelper.INSTANCE.initSerialPort(getApplicationContext());
// emvParamOperation.loadDataFromJSON(); // emvParamOperation.loadDataFromJSON();
} }

View File

@ -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; }
}

View File

@ -7,6 +7,8 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; 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.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum;
import com.utsmm.kbz.ui.pinpad.PinPadViewModel; import com.utsmm.kbz.ui.pinpad.PinPadViewModel;
import com.utsmm.kbz.util.TransactionUtil; 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.readcard.ReadCardResultX;
import com.utsmyanmar.checkxread.sdk.NexGoSDK; import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.checkxread.util.CardTypeX; import com.utsmyanmar.checkxread.util.CardTypeX;
import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.paylibs.model.TradeData; 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.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType; import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR; import com.utsmm.kbz.BR;
@ -109,10 +113,25 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
private void finishECR() { private void finishECR() {
sharedViewModel.isEcr.postValue(false); sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getResourceString(R.string.txt_cancel_trans));
sharedViewModel.isEcrFinished.postValue(true); 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 { public class ClickEvent {
@ -362,8 +381,15 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
if (sharedViewModel.isEcr.getValue()) { if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false); sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.isEcrFinished.postValue(true); sharedViewModel.isEcrFinished.postValue(true);
if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
ECRHelper.INSTANCE.send(generateCHMLResponse());
// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
} else {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
}
} }
} }
} }

View File

@ -11,6 +11,8 @@ import androidx.appcompat.app.AlertDialog;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDestination; 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.core_viewmodel.CardReadViewModel;
import com.utsmm.kbz.ui.pinpad.PinPadViewModel; import com.utsmm.kbz.ui.pinpad.PinPadViewModel;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; 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.baselib.util.DataBindingConfig;
import com.utsmyanmar.checkxread.sdk.NexGoSDK; import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.checkxread.util.CardTypeX; import com.utsmyanmar.checkxread.util.CardTypeX;
import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData; import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.POSUtil; import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType; import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
@ -392,17 +396,36 @@ public class EmvTransactionFragment extends DataBindingFragment {
} }
ECRActionCancel(ecrErrorMsg);
navigateToError(); 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) { private void ECRActionCancel(String message) {
if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) { if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) {
LogUtil.d(TAG, "isECR true"); LogUtil.d(TAG, "isECR true");
sharedViewModel.isEcrFinished.postValue(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()) { if (isEmvTrans()) {
emvTransactionViewModel.onCancelEmvTransaction(); emvTransactionViewModel.onCancelEmvTransaction();
@ -411,6 +434,7 @@ public class EmvTransactionFragment extends DataBindingFragment {
} }
private boolean isEmvTrans() { private boolean isEmvTrans() {
return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue(); return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue();
} }

View File

@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDestination; import androidx.navigation.NavDestination;
import com.utsmm.kbz.util.ecr.ECRResultStatus;
import com.utsmm.kbz.util.tms.TMSUtil; import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptCardRequest; 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.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig; import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TimeoutCallback; import com.utsmyanmar.baselib.util.TimeoutCallback;
import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.BR; import com.utsmm.kbz.BR;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
@ -238,15 +240,26 @@ public class ProcessingFragment extends DataBindingFragment {
if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) { if (sharedViewModel.isEcr.getValue() != null && sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false); sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.isEcrFinished.postValue(true); sharedViewModel.isEcrFinished.postValue(true);
if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
ECRHelper.INSTANCE.send(getECRResponseCMHL());
// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
} else {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
}
if(isEmvTrans()) { if(isEmvTrans()) {
emvTransactionProcessViewModel.onCancelEmvTransaction(); emvTransactionProcessViewModel.onCancelEmvTransaction();
} }
} }
} }
private byte[] getECRResponseCMHL() {
return CoreUtils.getInstance(sharedViewModel).generateCMHLResponse(ECRResultStatus.TIME_OUT);
}
private void navigateToError() { private void navigateToError() {
routeId = R.id.action_processingFragment_to_errorFragment; routeId = R.id.action_processingFragment_to_errorFragment;

View File

@ -10,6 +10,7 @@ import androidx.appcompat.app.AppCompatActivity;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.MalformedJsonException; import com.google.gson.stream.MalformedJsonException;
import com.utsmm.kbz.util.ecr.ECRResultStatus;
import com.utsmyanmar.baselib.emv.EmvParamOperation; import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.sirius.SiriusError; import com.utsmyanmar.baselib.network.model.sirius.SiriusError;
@ -29,6 +30,7 @@ import com.utsmyanmar.paylibs.print.PaperRollStatusCallback;
import com.utsmyanmar.paylibs.print.PrintHelper; import com.utsmyanmar.paylibs.print.PrintHelper;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus; import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
import com.utsmyanmar.paylibs.utils.PrintStatus; 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.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType; import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR; import com.utsmm.kbz.BR;
@ -423,10 +425,23 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
return ECRProcess.INSTANCE.generateECRResponse(resp); return ECRProcess.INSTANCE.generateECRResponse(resp);
} }
private byte[] getECRResponseCMHL() {
return CoreUtils.getInstance(sharedViewModel).generateCMHLResponse(ECRResultStatus.RESPONSE_RECEIVED);
}
private void ecrAction() { private void ecrAction() {
LogUtil.d(TAG,"ECR Response :"+getECRResponseMessage()); if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
ECRHelper.INSTANCE.send(getECRResponseMessage().getBytes()); 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(() -> { ECRHelper.INSTANCE.setOnBindSuccess(() -> {
LogUtil.d(TAG, "Send Success!"); LogUtil.d(TAG, "Send Success!");
@ -435,6 +450,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
} }
@Override @Override
public void onBackPress() { public void onBackPress() {
isCardInside(); isCardInside();

View File

@ -7,6 +7,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.github.gcacace.signaturepad.BR; 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.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.DemoQRRequest; import com.utsmyanmar.baselib.network.model.DemoQRRequest;
import com.utsmyanmar.baselib.network.model.KPayQRRequest; 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.ecr.data.model.TransactionsResp;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData; import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.POSUtil; import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType; import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants; import com.utsmm.kbz.config.Constants;
@ -220,8 +224,11 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
private void ecrAction() { private void ecrAction() {
LogUtil.d(TAG,"ECR Response :"+getECRResponseMessage()); if(!SystemParamsOperation.getInstance().isCMHLEnabled()) {
ECRHelper.INSTANCE.send(getECRResponseMessage().getBytes()); LogUtil.d(TAG,"ECR Response :"+getECRResponseMessage());
ECRHelper.INSTANCE.send(getECRResponseMessage().getBytes());
}
ECRHelper.INSTANCE.setOnBindSuccess(() -> { ECRHelper.INSTANCE.setOnBindSuccess(() -> {
LogUtil.d(TAG, "Send Success!"); LogUtil.d(TAG, "Send Success!");
@ -237,7 +244,14 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
private void finishECR() { private void finishECR() {
sharedViewModel.isEcr.postValue(false); 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); sharedViewModel.isEcrFinished.postValue(true);
} }
@ -246,8 +260,15 @@ public class QRConnectingFragment extends DataBindingFragment implements DataBin
if (sharedViewModel.isEcr.getValue()) { if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false); sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.isEcrFinished.postValue(true); 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); 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 @Override
public void onBackPress() { public void onBackPress() {
if (sharedViewModel.isEcr.getValue() != null) { if (sharedViewModel.isEcr.getValue() != null) {

View File

@ -9,6 +9,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; 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.EReceiptUtil;
import com.utsmm.kbz.util.enums.TransResultStatus; import com.utsmm.kbz.util.enums.TransResultStatus;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
@ -21,6 +23,7 @@ import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.ecr.ECRProcess; import com.utsmyanmar.ecr.ECRProcess;
import com.utsmyanmar.ecr.data.model.TransactionsResp; import com.utsmyanmar.ecr.data.model.TransactionsResp;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
import com.utsmm.kbz.BR; import com.utsmm.kbz.BR;
@ -163,8 +166,24 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
private void finishECR() { private void finishECR() {
sharedViewModel.isEcr.postValue(false); sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(getResourceString(R.string.txt_cancel_trans));
sharedViewModel.isEcrFinished.postValue(true); 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) { private void ecrActionCancel(String msg) {
@ -476,6 +495,8 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
); );
} }
private String getECRResponseMessage() { private String getECRResponseMessage() {
sharedViewModel.payDetail.setValue(payDetail); sharedViewModel.payDetail.setValue(payDetail);
@ -485,7 +506,6 @@ public class QRTransactionFragment extends DataBindingFragment implements DataBi
return ECRProcess.INSTANCE.generateECRResponse(resp); return ECRProcess.INSTANCE.generateECRResponse(resp);
} }
private void ecrAction() { private void ecrAction() {
LogUtil.d(TAG, "ECR Response :" + getECRResponseMessage()); LogUtil.d(TAG, "ECR Response :" + getECRResponseMessage());

View File

@ -9,12 +9,14 @@ import androidx.annotation.Nullable;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import com.utsmm.kbz.util.ecr.ECRResultStatus;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig; import com.utsmyanmar.baselib.util.DataBindingConfig;
//import com.utsmyanmar.mpulib.readcard.ReadCardProcess; //import com.utsmyanmar.mpulib.readcard.ReadCardProcess;
import com.utsmyanmar.checkxread.sdk.NexGoSDK; import com.utsmyanmar.checkxread.sdk.NexGoSDK;
import com.utsmyanmar.ecr.ECRHelper;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData; import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.utils.POSUtil; 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.ui.core_viewmodel.TransProcessViewModel;
import com.utsmm.kbz.util.ecr.CoreUtils; import com.utsmm.kbz.util.ecr.CoreUtils;
import com.utsmm.kbz.util.enums.PinPadStatus; import com.utsmm.kbz.util.enums.PinPadStatus;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
public class PinPadFragment extends DataBindingFragment { 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) { private void ecrActionCancel(String msg) {
if (sharedViewModel.isEcr.getValue() != null) { if (sharedViewModel.isEcr.getValue() != null) {
if (sharedViewModel.isEcr.getValue()) { if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false); sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.payDetail.setValue(pinPadViewModel.getPayDetail());
sharedViewModel.isEcrFinished.postValue(true); sharedViewModel.isEcrFinished.postValue(true);
if(SystemParamsOperation.getInstance().isCMHLEnabled()) {
ECRHelper.INSTANCE.send(getECRResponseCMHL());
// CoreUtils.getInstance(sharedViewModel).responseACKCMHL();
} else {
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
}
} }
} }
} }

View File

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

View File

@ -4,12 +4,30 @@ import android.annotation.SuppressLint;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; 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.ECRHelper;
import com.utsmyanmar.ecr.ECRProcess; import com.utsmyanmar.ecr.ECRProcess;
import com.utsmyanmar.ecr.data.RespType; import com.utsmyanmar.ecr.data.RespType;
import com.utsmyanmar.ecr.data.model.Transactions; import com.utsmyanmar.ecr.data.model.Transactions;
import com.utsmyanmar.ecr.data.model.TransactionsResp; import com.utsmyanmar.ecr.data.model.TransactionsResp;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.POSUtil; import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.enums.TransMenu; import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType; import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
@ -25,7 +43,7 @@ import com.utsmyanmar.paylibs.utils.LogUtil;
//@Keep //@Keep
public class CoreUtils implements OldECRSetups,ECRSetups { public class CoreUtils implements OldECRSetups,ECRSetups,ECRSetupsCMHL {
private static final String TAG = CoreUtils.class.getSimpleName(); private static final String TAG = CoreUtils.class.getSimpleName();
@ -166,7 +184,9 @@ public class CoreUtils implements OldECRSetups,ECRSetups {
return resp; return resp;
} }
public void responseACKCMHL() {
ECRHelper.INSTANCE.send(new byte[]{0x06});
}
public void responseRejectMsg(String actionName) { public void responseRejectMsg(String actionName) {
@ -215,6 +235,183 @@ public class CoreUtils implements OldECRSetups,ECRSetups {
ECRResponseAction(msg); 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 @Override
public boolean setUpECRSale(Transactions trans) { 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); sharedViewModel.processCode.postValue(ProcessCode.REFUND + ProcessCode.SMART + ProcessCode.TO_ACCOUNT);
return true; 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;
}
} }

View File

@ -0,0 +1,12 @@
package com.utsmm.kbz.util.ecr;
public enum ECRResultStatus {
USER_CANCEL,
TIME_OUT,
RESPONSE_RECEIVED
}

View File

@ -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);
}

View File

@ -649,6 +649,8 @@ public class TMSSetupsImpl implements TMSSetups{
} }
else if(TextUtils.equals(name, "printer_enabled")){ else if(TextUtils.equals(name, "printer_enabled")){
SystemParamsOperation.getInstance().setPrinterEnabled(parseBoolean(data)); SystemParamsOperation.getInstance().setPrinterEnabled(parseBoolean(data));
} else if (TextUtils.equals(name,"cmhl_enabled")) {
SystemParamsOperation.getInstance().setCMHLEnable(parseBoolean(data));
} }
} }

View File

@ -316,8 +316,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
return; return;
} }
try { try {
LogUtil.d(TAG, "Selected :" + position); LogUtil.d(TAG, "Selected :" + position+1);
emvHandler.onSetSelAppResponse(position); emvHandler.onSetSelAppResponse(position+1);
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Exception during app selection: " + e.getMessage()); LogUtil.e(TAG, "Exception during app selection: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
@ -751,6 +751,10 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
byte[] tlv_50 = emvHandler.getTlv(new byte[]{(byte) 0x50}, EmvDataSourceEnum.FROM_KERNEL); byte[] tlv_50 = emvHandler.getTlv(new byte[]{(byte) 0x50}, EmvDataSourceEnum.FROM_KERNEL);
LogUtil.d(TAG, "tlv_50--" + ByteUtils.byteArray2HexString(tlv_50)); LogUtil.d(TAG, "tlv_50--" + ByteUtils.byteArray2HexString(tlv_50));
byte[] tlv_9B = emvHandler.getTlv(new byte[]{(byte) 0x9B}, EmvDataSourceEnum.FROM_KERNEL);
LogUtil.d(TAG, "tlv_9B--" + ByteUtils.byteArray2HexString(tlv_9B));
switch (retCode) { switch (retCode) {
case SdkResult.Emv_Success_Arpc_Fail: case SdkResult.Emv_Success_Arpc_Fail:
case SdkResult.Success: case SdkResult.Success:

View File

@ -34,7 +34,7 @@ dependencies {
// implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.6.0' implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.3.1'
implementation project(path: ':nexsdk-lib')
// implementation files('libs/ecr-service-lib-1.1.11.aar') // implementation files('libs/ecr-service-lib-1.1.11.aar')
implementation project(path: ':ecr-service-lib') implementation project(path: ':ecr-service-lib')
implementation project(path: ':paylibs') implementation project(path: ':paylibs')

View File

@ -1,19 +1,25 @@
package com.utsmyanmar.ecr package com.utsmyanmar.ecr
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.widget.Toast 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.ECRConnection
import com.pos.connection.bridge.ECRListener import com.pos.connection.bridge.ECRListener
import com.pos.connection.bridge.ECRRequestCallback import com.pos.connection.bridge.ECRRequestCallback
import com.pos.connection.bridge.ECRService import com.pos.connection.bridge.ECRService
import com.pos.hardware.connection.library.ECRServiceKernel import com.pos.hardware.connection.library.ECRServiceKernel
import com.utsmyanmar.paylibs.utils.LogUtil
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
object ECRHelper { object ECRHelper {
val TAG = ECRHelper::class.java.simpleName val TAG = ECRHelper::class.java.simpleName
private var ecrService: ECRService? = null private var ecrService: ECRService? = null
private var serialPort: SerialPortDriver? = null
var onBindSuccess: () -> Unit = { } var onBindSuccess: () -> Unit = { }
var onBindFailure: () -> Unit = { } var onBindFailure: () -> Unit = { }
@ -26,6 +32,70 @@ object ECRHelper {
var onECRReceive: (bytes: ByteArray) -> Unit = { } 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) { fun connect(bundle: Bundle) {
call { call {
anyExecute(ecrService) { anyExecute(ecrService) {
@ -51,59 +121,39 @@ object ECRHelper {
} }
private val ecrListener = object : ECRListener.Stub() { private val ecrListener = object : ECRListener.Stub() {
override fun onReceive(byteArray: ByteArray?) {
override fun onReceive(byteArray: ByteArray ? ) {
if (byteArray != null) { if (byteArray != null) {
val string = String(byteArray, StandardCharsets.UTF_8) val string = String(byteArray, StandardCharsets.UTF_8)
Logger.e(TAG, "onReceive string: $string") Logger.e(TAG, "onReceive string: $string")
onECRReceive(byteArray) 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() { private val requestCallback = object : ECRRequestCallback.Stub() {
override fun onSuccess() { override fun onSuccess() {
Logger.e(TAG, "onSuccess") Logger.e(TAG, "onSuccess")
onSendSuccess() onSendSuccess()
} }
override fun onFailure(code: Int, massage: String ? ) { override fun onFailure(code: Int, massage: String?) {
Logger.e(TAG, "onFailure code: $code massage: $massage") Logger.e(TAG, "onFailure code: $code massage: $massage")
onSendFailure(code, massage ?: "failure") onSendFailure(code, massage ?: "failure")
} }
} }
private val ecrConnection = object : ECRConnection.Stub() { private val ecrConnection = object : ECRConnection.Stub() {
override fun onConnected() { override fun onConnected() {
Logger.d(TAG, "onConnected") Logger.d(TAG, "onConnected")
ECRUtil.connected = true ECRUtil.connected = true
onECRConnected() onECRConnected()
} }
override fun onDisconnected(code: Int, massage: String ? ) { override fun onDisconnected(code: Int, massage: String?) {
Logger.d(TAG, "onDisconnected code: $code massage: $massage") Logger.d(TAG, "onDisconnected code: $code massage: $massage")
ECRUtil.connected = false ECRUtil.connected = false
onECRDisconnected(code, massage ?: "failure") onECRDisconnected(code, massage ?: "failure")
} }
} }
fun bindECRService() { fun bindECRService() {
@ -111,7 +161,6 @@ object ECRHelper {
} }
private val connectionCallback = object : ECRServiceKernel.ConnectionCallback { private val connectionCallback = object : ECRServiceKernel.ConnectionCallback {
override fun onServiceConnected() { override fun onServiceConnected() {
Logger.e(TAG, "onServiceConnected") Logger.e(TAG, "onServiceConnected")
ecrService = ECRServiceKernel.getInstance().ecrService ecrService = ECRServiceKernel.getInstance().ecrService
@ -124,7 +173,6 @@ object ECRHelper {
ecrService = null ecrService = null
onBindFailure() onBindFailure()
} }
} }
private fun call(block: () -> Unit) { private fun call(block: () -> Unit) {
@ -140,5 +188,4 @@ object ECRHelper {
onECRDisconnected(-200, ex.localizedMessage ?: "") onECRDisconnected(-200, ex.localizedMessage ?: "")
} }
} }
} }

View File

@ -9,7 +9,64 @@ import java.util.Map;
public class BaseErrorCode { public class BaseErrorCode {
private static final Map<String, String> 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) { public static String getCode(String code) {
if (instance == null) instance = new BaseErrorCode(); 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) { public static String getErrorMessage(String code) {
if (instance == null) instance = new BaseErrorCode(); if (instance == null) instance = new BaseErrorCode();
String errorMsg = instance.errorCode.get(code); String errorMsg = instance.errorCode.get(code);

View File

@ -154,7 +154,7 @@ public class AuthorizationProcessUtil {
hexValues[i] = value; hexValues[i] = value;
} }
int status; int status;
String f055Data = getF055Data();
LogUtil.d(TAG,"is equal:"+equals); LogUtil.d(TAG,"is equal:"+equals);
LogUtil.d(TAG,"Emv Online Result:"+emvOnlineResult); LogUtil.d(TAG,"Emv Online Result:"+emvOnlineResult);
if (equals) { if (equals) {
@ -177,7 +177,7 @@ public class AuthorizationProcessUtil {
LogUtil.e(Constant.TAG, "scriptResult: " + scriptResult); LogUtil.e(Constant.TAG, "scriptResult: " + scriptResult);
payDetail.setScriptResult(scriptResult); payDetail.setScriptResult(scriptResult);
String f055Data = getF055Data();
LogUtil.e(Constant.TAG, "f055Data: " + f055Data); LogUtil.e(Constant.TAG, "f055Data: " + f055Data);
// if (status >= 0) { // if (status >= 0) {
@ -205,6 +205,7 @@ public class AuthorizationProcessUtil {
private void importOnlineProcessStatus(int sdkResult,EmvOnlineResultEntity emvOnlineResult) { private void importOnlineProcessStatus(int sdkResult,EmvOnlineResultEntity emvOnlineResult) {
LogUtil.d(TAG, "importOnlineProcessStatus sdkResult:"+sdkResult); LogUtil.d(TAG, "importOnlineProcessStatus sdkResult:"+sdkResult);
LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+emvOnlineResult.toString()); LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+emvOnlineResult.toString());
PayLibNex.getInstance().deviceEngine.getEmvHandler2("app2").onSetOnlineProcResponse(sdkResult, emvOnlineResult); PayLibNex.getInstance().deviceEngine.getEmvHandler2("app2").onSetOnlineProcResponse(sdkResult, emvOnlineResult);
} }

View File

@ -6,9 +6,11 @@ import android.text.TextUtils;
import com.utsmyanmar.paylibs.Constant; import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.R; import com.utsmyanmar.paylibs.R;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.enums.TransCVM;
import com.utsmyanmar.paylibs.system.BaseErrorCode; import com.utsmyanmar.paylibs.system.BaseErrorCode;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.BaseCardType; 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.InvalidAmount;
import com.utsmyanmar.paylibs.utils.enums.TransMenu; import com.utsmyanmar.paylibs.utils.enums.TransMenu;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType; import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
@ -93,6 +95,33 @@ public class POSUtil {
return numberFormat.format(amount); 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() { public String getCurrentDateAndTime() {
SimpleDateFormat dfm = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault()); SimpleDateFormat dfm = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault());
String currentTime = dfm.format(new Date()); 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() { public String getMerchantName() {
return SystemParamsOperation.getInstance().getMerchantName(); return SystemParamsOperation.getInstance().getMerchantName();
} }
@ -135,6 +183,11 @@ public class POSUtil {
// return formatter.format(amt); // return formatter.format(amt);
} }
public String formatAmount(long amount) {
return String.format("%012d", amount/100);
}
public String currencyCodeToText(String currencyCode) { public String currencyCodeToText(String currencyCode) {
String currencyText = "MMK"; String currencyText = "MMK";
switch (currencyCode) { switch (currencyCode) {

View File

@ -1761,4 +1761,15 @@ public class SystemParamsOperation {
SystemParamsSettings paramsSettings = getSystemParamsSettings(); SystemParamsSettings paramsSettings = getSystemParamsSettings();
return paramsSettings.getPrinterEnabled(); 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();
}
} }

View File

@ -159,6 +159,8 @@ public class SystemParamsSettings implements Serializable {
private boolean fallbackEnabled = true; private boolean fallbackEnabled = true;
private boolean cmhlEnabled = false;
private boolean manualUpdate = false; private boolean manualUpdate = false;
private boolean emvEnabled = false; private boolean emvEnabled = false;
@ -484,6 +486,10 @@ public class SystemParamsSettings implements Serializable {
protected String getLastTransTime() { return lastTransTime; } protected String getLastTransTime() { return lastTransTime; }
protected boolean isClearBatch() {return isClearBatch;} 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 setClearBatch(boolean isClearBatch) {this.isClearBatch = isClearBatch;}
protected void setRandomPinPad(boolean randomPinPad) { this.isRandomPinPad = randomPinPad;} protected void setRandomPinPad(boolean randomPinPad) { this.isRandomPinPad = randomPinPad;}

View File

@ -2,19 +2,22 @@ package com.utsmyanmar.paylibs.utils.enums;
public enum CardScheme { public enum CardScheme {
VISA("VISA"), VISA("VISA",1),
MASTERCARD("MASTER"), MASTERCARD("MASTER",2),
UPI("UnionPay"), UPI("UnionPay",5),
JCB("JCB"), JCB("JCB",3),
AE("AmericanExpress"), AE("AmericanExpress",0),
MPU("MPU"), MPU("MPU",4),
RUPAY("RuPay"), RUPAY("RuPay",0),
PURE("Pure"), PURE("Pure",0),
MPU_CTLS("MPU Ctls"); MPU_CTLS("MPU Ctls",4);
public final String name; public final String name;
CardScheme(String name){ public final int value;
CardScheme(String name,int value){
this.name = name; this.name = name;
this.value = value;
} }
} }

View File

@ -39,3 +39,4 @@ include ':ecr-service-lib'
include ':link-service-lib' include ':link-service-lib'
include ':qrgen-lib' include ':qrgen-lib'
include ':nexdlkey-lib' include ':nexdlkey-lib'
include ':cmhl'