Compare commits

..

No commits in common. "cdb7bb73c5ee4fafe75a39c64d59d1c61982d0b3" and "3cb8fe218eceb05909d957c6e27709da491d9a1b" have entirely different histories.

34 changed files with 394 additions and 780 deletions

View File

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

View File

@ -204,7 +204,7 @@ dependencies {
// ECR Dependencies - Modern ECR Client Library // ECR Dependencies - Modern ECR Client Library
// implementation project(path: ':ecr-client-lib') // implementation project(path: ':ecr-client-lib')
// implementation project(path: ':ecr-service-lib') implementation project(path: ':ecr-service-lib')
// Core Libraries // Core Libraries
implementation project(path: ':paylibs') implementation project(path: ':paylibs')

View File

@ -4,7 +4,6 @@ import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil; import androidx.databinding.DataBindingUtil;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDestination; import androidx.navigation.NavDestination;
@ -472,87 +471,58 @@ public class MainActivity extends AppCompatActivity implements
private void handleAutoSettlementIntent(Intent intent) { private void handleAutoSettlementIntent(Intent intent) {
if (intent == null) return; if (intent == null) return;
boolean hasPOS = intent.getBooleanExtra("AUTO_SETTLEMENT", false); // Handle regular auto settlement
boolean hasQR = intent.getBooleanExtra("AUTO_QR_SETTLEMENT", false); boolean auto = intent.getBooleanExtra("AUTO_SETTLEMENT", false);
if (auto) {
if (hasPOS) {
PayDetail payDetail = (PayDetail) intent.getSerializableExtra("EXTRA_PAY_DETAIL"); PayDetail payDetail = (PayDetail) intent.getSerializableExtra("EXTRA_PAY_DETAIL");
if (payDetail != null) { if (payDetail != null) {
sharedViewModel.payDetail.setValue(payDetail); sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT); sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT);
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount())); sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.getAmount()));
try { try {
navController.navigate(R.id.transactionResultFragment); navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Navigation error: " + e.getMessage()); LogUtil.e(TAG, "Navigation error: " + e.getMessage());
} }
// If QR also exists, trigger it AFTER POS result is done
if (hasQR) {
navigateToQRSettlementAfterPOS(intent);
}
} else {
// POS had no data, go straight to QR if available
if (hasQR) {
handleQRSettlement(intent);
}
} }
return;
} else if (hasQR) {
// Only QR settlement, no POS
handleQRSettlement(intent);
} }
}
// Handle QR auto settlement
boolean autoQR = intent.getBooleanExtra("AUTO_QR_SETTLEMENT", false);
if (autoQR) {
int qrSaleCount = intent.getIntExtra("QR_SALE_COUNT", 0);
long qrSaleAmount = intent.getLongExtra("QR_SALE_AMOUNT", 0L);
int qrRefundCount = intent.getIntExtra("QR_REFUND_COUNT", 0);
long qrRefundAmount = intent.getLongExtra("QR_REFUND_AMOUNT", 0L);
long totalAmount = intent.getLongExtra("QR_TOTAL_AMOUNT", 0L);
List<PayDetail> qrTransList = (List<PayDetail>) intent.getSerializableExtra("QR_TRANS_LIST");
private void navigateToQRSettlementAfterPOS(Intent intent) { // Create QR settlement PayDetail
// Observe transactionResultFragment's completion via ViewModel SettleData settleData = new SettleData(
// When POS result screen signals "done" (print complete / user dismissed), qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
// then navigate to QR result
sharedViewModel.onSettlementResultDone.observe(this, new Observer<Boolean>() { TradeData tradeData = Params.newTrade(false);
@Override PayDetail payDetail = tradeData.getPayDetail();
public void onChanged(Boolean done) { payDetail.setSettleDataObj(settleData);
if (done != null && done) { payDetail.setTransactionType(TransactionsType.MMQR_SETTLEMENT.value);
// Remove observer so it only fires once payDetail.setTransType(TransactionsType.MMQR_SETTLEMENT.name);
sharedViewModel.onSettlementResultDone.removeObserver(this); payDetail.setAmount(totalAmount);
// Reset flag payDetail.setTradeAnswerCode("000");
sharedViewModel.onSettlementResultDone.postValue(false);
// Now navigate to QR
handleQRSettlement(intent); sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount));
} sharedViewModel.payDetails.setValue(qrTransList);
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR_SETTLEMENT);
try {
navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) {
LogUtil.e(TAG, "QR Auto Settlement navigation error: " + e.getMessage());
} }
});
}
private void handleQRSettlement(Intent intent) {
int qrSaleCount = intent.getIntExtra("QR_SALE_COUNT", 0);
long qrSaleAmount = intent.getLongExtra("QR_SALE_AMOUNT", 0L);
int qrRefundCount = intent.getIntExtra("QR_REFUND_COUNT", 0);
long qrRefundAmount = intent.getLongExtra("QR_REFUND_AMOUNT", 0L);
long totalAmount = intent.getLongExtra("QR_TOTAL_AMOUNT", 0L);
List<PayDetail> qrTransList = (List<PayDetail>) intent.getSerializableExtra("QR_TRANS_LIST");
SettleData settleData = new SettleData(
qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
TradeData tradeData = Params.newTrade(false);
PayDetail payDetail = tradeData.getPayDetail();
payDetail.setSettleDataObj(settleData);
payDetail.setTransactionType(TransactionsType.MMQR_SETTLEMENT.value);
payDetail.setTransType(TransactionsType.MMQR_SETTLEMENT.name);
payDetail.setAmount(totalAmount);
payDetail.setTradeAnswerCode("000");
sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount));
sharedViewModel.payDetails.setValue(qrTransList);
sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR_SETTLEMENT);
try {
navController.navigate(R.id.transactionResultFragment);
} catch (Exception e) {
LogUtil.e(TAG, "QR Auto Settlement navigation error: " + e.getMessage());
} }
} }

View File

@ -29,11 +29,9 @@ import com.denzcoskun.imageslider.constants.ScaleTypes;
import com.denzcoskun.imageslider.models.SlideModel; import com.denzcoskun.imageslider.models.SlideModel;
import com.nexgo.oaf.apiv3.emv.AidEntity; import com.nexgo.oaf.apiv3.emv.AidEntity;
import com.nexgo.oaf.apiv3.emv.CapkEntity; import com.nexgo.oaf.apiv3.emv.CapkEntity;
//import com.pos.connection.bridge.binder.ECRConstant; import com.pos.connection.bridge.binder.ECRConstant;
import com.utsmm.kbz.util.MockData; import com.utsmm.kbz.util.MockData;
//import com.utsmm.kbz.util.ecr.ModernECRFactory;
//import com.utsmm.kbz.util.ecr.ModernECRManager;
import com.utsmyanmar.baselib.BaseApplication; import com.utsmyanmar.baselib.BaseApplication;
import com.utsmyanmar.baselib.emv.EmvParamOperation; import com.utsmyanmar.baselib.emv.EmvParamOperation;
import com.utsmyanmar.baselib.fragment.DataBindingFragment; import com.utsmyanmar.baselib.fragment.DataBindingFragment;
@ -318,8 +316,8 @@ public class MainFragment extends DataBindingFragment {
if (checkECRServiceAppExistOrNot()) { if (checkECRServiceAppExistOrNot()) {
// Initialize Modern ECR Manager // Initialize Modern ECR Manager
// modernECRManager.init(); // modernECRManager.init();
//// //
//// // Observe navigation requests // // Observe navigation requests
// modernECRManager.getNavigationRequest().observe(getViewLifecycleOwner(), destinationId -> { // modernECRManager.getNavigationRequest().observe(getViewLifecycleOwner(), destinationId -> {
// if (destinationId != null) { // if (destinationId != null) {
// delayFunctionCall(() -> isRouteValidAndNavigateToRoute(destinationId)); // delayFunctionCall(() -> isRouteValidAndNavigateToRoute(destinationId));

View File

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

View File

@ -328,17 +328,6 @@ public class SettingsFragment extends DataBindingFragment {
} }
} }
public void onClearReversalClick() {
try {
sharedViewModel.transactionsType.postValue(TransactionsType.CLEAR_REVERSAL);
sharedViewModel.setTransMenu(TransMenu.CLEAR_REVERSAL);
Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)
.navigate(R.id.inputPasswordFragment);
} catch (Exception e) {
LogUtil.e(TAG, "Error in clear reversal click: " + e.getMessage());
}
}
public void onTmsConfigClick() { public void onTmsConfigClick() {
try { try {
LogUtil.d(TAG, "TMS Config clicked"); LogUtil.d(TAG, "TMS Config clicked");

View File

@ -262,7 +262,6 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
} else { } else {
allType.add(CardSlotTypeEnum.ICC1); allType.add(CardSlotTypeEnum.ICC1);
allType.add(CardSlotTypeEnum.RF); allType.add(CardSlotTypeEnum.RF);
allType.add(CardSlotTypeEnum.SWIPE);
} }
// int allType = AidlConstants.CardType.IC.getValue() | AidlConstants.CardType.MAGNETIC.getValue(); // int allType = AidlConstants.CardType.IC.getValue() | AidlConstants.CardType.MAGNETIC.getValue();
@ -290,7 +289,7 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
} else if (isFallback && cardType == CardTypeX.MAG) { } else if (isFallback && cardType == CardTypeX.MAG) {
/* do fallback transactions */ /* do fallback transactions */
sharedViewModel.isEmv.postValue(false); sharedViewModel.isEmv.setValue(false);
cardReadViewModel.setCardTransactionType(CardTransactionType.FALLBACK); cardReadViewModel.setCardTransactionType(CardTransactionType.FALLBACK);
} else if (cardType == CardTypeX.IC || cardType == CardTypeX.NFC) { } else if (cardType == CardTypeX.IC || cardType == CardTypeX.NFC) {

View File

@ -3,7 +3,6 @@ package com.utsmm.kbz.ui.core_ui;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -159,7 +158,6 @@ public class EmvTransactionFragment extends DataBindingFragment {
} }
observeEmvResultStatus(); observeEmvResultStatus();
observePinWarning();
} }
private boolean isNotManualTransaction() { private boolean isNotManualTransaction() {
@ -246,7 +244,7 @@ public class EmvTransactionFragment extends DataBindingFragment {
isCardTaped("Please try again",new CardDetectCallback() { isCardTaped("Please try again",new CardDetectCallback() {
@Override @Override
public void onComplete() { public void onComplete() {
sharedViewModel.setIsSeePhone(false); sharedViewModel.setIsSeePhone(true);
navigateToCheckCard(); navigateToCheckCard();
} }
}); });
@ -351,15 +349,6 @@ public class EmvTransactionFragment extends DataBindingFragment {
}); });
} }
private void observePinWarning() {
emvTransactionViewModel.pinRemainingCount.observe(getViewLifecycleOwner(), msg -> {
if (!TextUtils.isEmpty(msg)) {
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show();
emvTransactionViewModel.pinRemainingCount.setValue("");
}
});
}
private void observeEmvErrorCode() { private void observeEmvErrorCode() {
dismissLoadingDialog(); dismissLoadingDialog();
emvTransactionViewModel.errorCodeMsg.observe(getViewLifecycleOwner(), pair -> { emvTransactionViewModel.errorCodeMsg.observe(getViewLifecycleOwner(), pair -> {

View File

@ -6,8 +6,6 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDestination; import androidx.navigation.NavDestination;
@ -19,9 +17,6 @@ import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest; import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig; import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.util.TimeoutCallback; import com.utsmyanmar.baselib.util.TimeoutCallback;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.reversal.ReversalAction;
import com.utsmyanmar.paylibs.reversal.ReversalListener;
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;
@ -109,17 +104,6 @@ public class ProcessingFragment extends DataBindingFragment {
setToolBarTitleWithoutBackIcon(getResourceString(R.string.title_processing)); setToolBarTitleWithoutBackIcon(getResourceString(R.string.title_processing));
checkReversal();
// disableNavigationBar();
getNavController(Constants.NAV_HOST_ID).addOnDestinationChangedListener(listener);
}
private void startTransactionProcess() {
if(isEmvTrans()) { if(isEmvTrans()) {
startTransactionProcess(emvTransactionProcessViewModel); startTransactionProcess(emvTransactionProcessViewModel);
} else { } else {
@ -127,55 +111,13 @@ public class ProcessingFragment extends DataBindingFragment {
} }
sharedViewModel.loadingMsg(getResourceString(R.string.txt_sending)); sharedViewModel.loadingMsg(getResourceString(R.string.txt_sending));
// disableNavigationBar();
getNavController(Constants.NAV_HOST_ID).addOnDestinationChangedListener(listener);
} }
private void checkReversal() {
observeOnce(sharedViewModel.getLastReversalTransaction(), payDetail -> {
if (payDetail != null) {
TradeData tradeData = new TradeData();
tradeData.setPayDetail(payDetail);
LogUtil.d(TAG, "Sending Reversal!");
sharedViewModel.loadingMsg(getResourceString(R.string.txt_sending_reversal));
ReversalAction.getInstance().setData(tradeData).enqueue().startReversal(new ReversalListener() {
@Override
public void onSuccessReversal() {
LogUtil.d(TAG, "Reversal Success!");
payDetail.setIsNeedReversal(false);
sharedViewModel.updatePayDetail(payDetail);
delayFunctionCall(()->startTransactionProcess());
}
@Override
public void onNetworkFail(String msg) {
LogUtil.d(TAG, "Reversal Network Fail!" + msg);
startTransactionProcess();
}
@Override
public void onFailReversal(String msg) {
LogUtil.d(TAG, "Reversal Fail!" + msg);
startTransactionProcess();
}
});
} else {
LogUtil.d(TAG,"No reversal found!");
startTransactionProcess();
}
});
}
private <T> void observeOnce(LiveData<T> liveData, Observer<T> observer) {
liveData.observe(getViewLifecycleOwner(), new Observer<T>() {
@Override
public void onChanged(T t) {
liveData.removeObserver(this);
observer.onChanged(t);
}
});
}
private boolean isEmvTrans() { private boolean isEmvTrans() {
return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue(); return sharedViewModel.isEmv.getValue() != null && sharedViewModel.isEmv.getValue();
} }

View File

@ -335,7 +335,6 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
sharedViewModel.startPrintSettlement(new PrintXStatus() { sharedViewModel.startPrintSettlement(new PrintXStatus() {
@Override @Override
public void onSuccess() { public void onSuccess() {
sharedViewModel.onSettlementResultDone.postValue(true);
isCardInside(); isCardInside();
} }

View File

@ -2,7 +2,6 @@ package com.utsmm.kbz.ui.core_viewmodel;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.util.Log; import android.util.Log;
import android.widget.ListView;
import dagger.hilt.android.lifecycle.HiltViewModel; import dagger.hilt.android.lifecycle.HiltViewModel;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
@ -74,8 +73,7 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent<String> transactionName = new SingleLiveEvent<>(); public SingleLiveEvent<String> transactionName = new SingleLiveEvent<>();
// In SharedViewModel
public MutableLiveData<Boolean> onSettlementResultDone = new MutableLiveData<>(false);
/*May 16 2022*/ /*May 16 2022*/
public SingleLiveEvent<Boolean> isEcr = new SingleLiveEvent<>(); public SingleLiveEvent<Boolean> isEcr = new SingleLiveEvent<>();
@ -448,14 +446,6 @@ public class SharedViewModel extends ViewModel {
return repository.getReversalTransaction(voucherNo); return repository.getReversalTransaction(voucherNo);
} }
public LiveData<PayDetail> getLastReversalTransaction() {
return repository.getLastReversalTransaction();
}
public LiveData<List<PayDetail>> getAllReversalTransaction() {
return repository.getAllReversalTransactions();
}
public void updatePayDetail(PayDetail payDetail){ public void updatePayDetail(PayDetail payDetail){
repository.updatePayDetail(payDetail); repository.updatePayDetail(payDetail);
} }

View File

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

View File

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

View File

@ -37,7 +37,6 @@ public class InjectKeyFragment extends DataBindingFragment {
private DownloadFlow mDownloadFlow; private DownloadFlow mDownloadFlow;
private int keyIndexTmp = 8; // Default key index private int keyIndexTmp = 8; // Default key index
private final List<HostSelectionItem> hostSelectionItems = new ArrayList<>(); private final List<HostSelectionItem> hostSelectionItems = new ArrayList<>();
private HostSelectionItem selectedHostSelectionItem;
@Override @Override
protected void initViewModel() { protected void initViewModel() {
@ -129,7 +128,6 @@ public class InjectKeyFragment extends DataBindingFragment {
} }
private void applyHostSelection(@NonNull HostSelectionItem selectionItem) { private void applyHostSelection(@NonNull HostSelectionItem selectionItem) {
selectedHostSelectionItem = selectionItem;
binding.terminalIdValue.setText(getDisplayValue(selectionItem.terminalId)); binding.terminalIdValue.setText(getDisplayValue(selectionItem.terminalId));
binding.merchantIdValue.setText(getDisplayValue(selectionItem.merchantId)); binding.merchantIdValue.setText(getDisplayValue(selectionItem.merchantId));
} }
@ -158,14 +156,14 @@ public class InjectKeyFragment extends DataBindingFragment {
mDownloadFlow = DownloadFlow.getInstance(); mDownloadFlow = DownloadFlow.getInstance();
String terminalId = selectedHostSelectionItem != null ? selectedHostSelectionItem.terminalId : null; String terminalId = SystemParamsOperation.getInstance().getTerminalId();
String merchantId = selectedHostSelectionItem != null ? selectedHostSelectionItem.merchantId : null; String merchantId = SystemParamsOperation.getInstance().getMerchantId();
String serialNo = TMSUtil.getInstance().getSerialNumber(); String serialNo = TMSUtil.getInstance().getSerialNumber();
// Validate configuration // Validate configuration
if (TextUtils.isEmpty(terminalId) || TextUtils.isEmpty(merchantId) || TextUtils.isEmpty(serialNo)) { if (TextUtils.isEmpty(terminalId) || TextUtils.isEmpty(merchantId) || TextUtils.isEmpty(serialNo)) {
dismissLoadingDialog(); dismissLoadingDialog();
showDeclineDialog("Please configure the selected Terminal ID and Merchant ID first in TMS Configuration"); showDeclineDialog("Please configure Terminal ID, Merchant ID first in TMS Configuration");
return; return;
} }

View File

@ -462,7 +462,11 @@ public class SettlementViewModel extends ViewModel {
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) { } else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
//reversal //reversal
// if (!flag && isNoData.getValue()) { // if (!flag && isNoData.getValue()) {
payDetail.setIsNeedReversal(!flag); if (!flag ) {
payDetail.setIsNeedReversal(true);
} else {
payDetail.setIsNeedReversal(false);
}
} }
} else { } else {

View File

@ -6,7 +6,6 @@ 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;
@ -99,8 +98,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

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

View File

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

View File

@ -23,7 +23,6 @@ public final class TerminalKeyUtil {
public static final String TAG = TerminalKeyUtil.class.getSimpleName(); public static final String TAG = TerminalKeyUtil.class.getSimpleName();
private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("875f63741753d18811a3449090d1777b".toUpperCase()); // KBZ UAT private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("875f63741753d18811a3449090d1777b".toUpperCase()); // KBZ UAT
// private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("875f63741753d18811a3449090d1777b".toUpperCase());
// private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("e121249099a677e8b7d4f6a9d49fe8d1".toUpperCase()); // MPU // private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("e121249099a677e8b7d4f6a9d49fe8d1".toUpperCase()); // MPU
private static final byte[] work_key_data = new byte[16]; private static final byte[] work_key_data = new byte[16];
@ -40,7 +39,7 @@ public final class TerminalKeyUtil {
Arrays.fill(work_key_data, (byte) 0x31); Arrays.fill(work_key_data, (byte) 0x31);
PinPad pinPad = BaseApplication.getInstance().deviceEngine.getPinPad(); PinPad pinPad = BaseApplication.getInstance().deviceEngine.getPinPad();
int result = pinPad.writeMKey(9, main_key_data, main_key_data.length); int result = pinPad.writeMKey(9, main_key_data, main_key_data.length);
// //
// int resultPINKEY = pinPad.writeWKey(0, WorkKeyTypeEnum.PINKEY, work_key_data, work_key_data.length); // int resultPINKEY = pinPad.writeWKey(0, WorkKeyTypeEnum.PINKEY, work_key_data, work_key_data.length);

View File

@ -97,12 +97,6 @@ public interface PayDetailDao {
@Query("SELECT * FROM paydetail WHERE transactionType = 10 AND isNeedReversal = 1 AND voucherNo IN(:voucherNo)") @Query("SELECT * FROM paydetail WHERE transactionType = 10 AND isNeedReversal = 1 AND voucherNo IN(:voucherNo)")
LiveData<PayDetail> getReversalTransaction(String voucherNo); LiveData<PayDetail> getReversalTransaction(String voucherNo);
@Query("SELECT * FROM PayDetail WHERE isNeedReversal = 1 ORDER BY PID DESC LIMIT 1")
LiveData<PayDetail> getLastReversalTransactionLive();
@Query("SELECT * FROM PayDetail WHERE isNeedReversal = 1 ORDER BY PID DESC")
LiveData<List<PayDetail>> getAllReversalTransactionsLive();
// @Query("SELECT * FROM paydetail WHERE transactionType != 10 ORDER BY PID DESC") // @Query("SELECT * FROM paydetail WHERE transactionType != 10 ORDER BY PID DESC")
@Query("SELECT * FROM paydetail ORDER BY PID DESC") @Query("SELECT * FROM paydetail ORDER BY PID DESC")
LiveData<List<PayDetail>> getTransactionHistory(); LiveData<List<PayDetail>> getTransactionHistory();

View File

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

View File

@ -146,8 +146,6 @@ public class Repository {
public void updatePayDetail(PayDetail payDetail){payDetailDao.update(payDetail);} public void updatePayDetail(PayDetail payDetail){payDetailDao.update(payDetail);}
public LiveData<PayDetail> getReversalTransaction(String voucherNo) { return payDetailDao.getReversalTransaction(voucherNo);} public LiveData<PayDetail> getReversalTransaction(String voucherNo) { return payDetailDao.getReversalTransaction(voucherNo);}
public LiveData<PayDetail> getLastReversalTransaction() { return payDetailDao.getLastReversalTransactionLive();}
public LiveData<List<PayDetail>> getAllReversalTransactions() { return payDetailDao.getAllReversalTransactionsLive();}
public LiveData<List<PayDetail>> getTransactionHistory(){ return payDetailDao.getTransactionHistory();} public LiveData<List<PayDetail>> getTransactionHistory(){ return payDetailDao.getTransactionHistory();}

View File

@ -1,15 +1,12 @@
package com.utsmyanmar.baselib.viewModel; package com.utsmyanmar.baselib.viewModel;
import android.app.AlertDialog;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
@ -108,7 +105,6 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
public MutableLiveData<Integer> pinPadVisibility = new MutableLiveData<>(8); public MutableLiveData<Integer> pinPadVisibility = new MutableLiveData<>(8);
protected int pinEnterCount; protected int pinEnterCount;
private int offlinePinIncorrectPromptCount;
public CustomPinPadKeyboard customPinPadKeyboard; public CustomPinPadKeyboard customPinPadKeyboard;
private int mWidth = 239; // Single item width of password keyboard private int mWidth = 239; // Single item width of password keyboard
@ -249,7 +245,6 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
transData.setTransTime(new SimpleDateFormat("hhmmss", Locale.getDefault()).format(new Date())); transData.setTransTime(new SimpleDateFormat("hhmmss", Locale.getDefault()).format(new Date()));
transData.setTraceNo(mPayDetail.getVoucherNo()); transData.setTraceNo(mPayDetail.getVoucherNo());
transData.setEmvProcessFlowEnum(EmvProcessFlowEnum.EMV_PROCESS_FLOW_STANDARD); transData.setEmvProcessFlowEnum(EmvProcessFlowEnum.EMV_PROCESS_FLOW_STANDARD);
if (mPayDetail.getCardType() == CardTypeX.NFC.value) { if (mPayDetail.getCardType() == CardTypeX.NFC.value) {
transData.setEmvEntryModeEnum(EmvEntryModeEnum.EMV_ENTRY_MODE_CONTACTLESS); transData.setEmvEntryModeEnum(EmvEntryModeEnum.EMV_ENTRY_MODE_CONTACTLESS);
@ -265,8 +260,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
unionPayTransDataEntity.setSupportCDCVM(true); unionPayTransDataEntity.setSupportCDCVM(true);
//if support QPS, please enable below lines //if support QPS, please enable below lines
unionPayTransDataEntity.setSupportContactlessQps(true); unionPayTransDataEntity.setSupportContactlessQps(true);
unionPayTransDataEntity.setContactlessQpsLimit("000000030000"); unionPayTransDataEntity.setContactlessQpsLimit("000090000000");
transData.setUnionPayTransDataEntity(unionPayTransDataEntity); transData.setUnionPayTransDataEntity(unionPayTransDataEntity);
@ -275,8 +269,6 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
emvHandler.contactlessAppendAidIntoKernel(EmvCardBrandEnum.EMV_CARD_BRAND_MASTER, (byte) 0x08, ByteUtils.hexString2ByteArray("A000000732100123")); emvHandler.contactlessAppendAidIntoKernel(EmvCardBrandEnum.EMV_CARD_BRAND_MASTER, (byte) 0x08, ByteUtils.hexString2ByteArray("A000000732100123"));
LogUtil.d(TAG, "TransData :" + transData.getTransAmount()); LogUtil.d(TAG, "TransData :" + transData.getTransAmount());
LogUtil.d(TAG, "start emv "); LogUtil.d(TAG, "start emv ");
// emvHandler.emvDebugLog(true);
emvHandler.emvProcess(transData, emvProcessListener); emvHandler.emvProcess(transData, emvProcessListener);
@ -284,7 +276,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
private void initData() { private void initData() {
try { try {
emvHandler = BaseApplication.getInstance().deviceEngine.getEmvHandler2("app2"); emvHandler = BaseApplication.getInstance().deviceEngine.getEmvHandler2("app2");
if (emvHandler == null) { if (emvHandler == null) {
LogUtil.e(TAG, "Failed to initialize EMV handler - emvHandler is null"); LogUtil.e(TAG, "Failed to initialize EMV handler - emvHandler is null");
// Post error status to inform UI // Post error status to inform UI
@ -316,8 +308,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
return; return;
} }
try { try {
LogUtil.d(TAG, "Selected :" + position + 1); LogUtil.d(TAG, "Selected :" + position);
emvHandler.onSetSelAppResponse(position + 1); emvHandler.onSetSelAppResponse(position);
} 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();
@ -433,142 +425,213 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
initKeyboard(isOnlinePin == 1); initKeyboard(isOnlinePin == 1);
} }
private void initKeyboard(boolean isOnlinePin) { private void initKeyboard(boolean isOnlinePin) {
LogUtil.d(TAG, "init keyboard!");
LogUtil.d(TAG,"init keyboard!");
pinPadVisibility.setValue(0); pinPadVisibility.setValue(0);
LogUtil.d(TAG, "pin pad is visible now!"); LogUtil.d(TAG,"pin pad is visible now!");
customPinPadKeyboard.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
customPinPadKeyboard.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Check if the view is already laid out LogUtil.d(TAG,"inside the global layout!");
if (customPinPadKeyboard.getWidth() > 0 && customPinPadKeyboard.getHeight() > 0) { PinpadLayoutEntity pinpadLayout = new PinpadLayoutEntity();
// View already laid out call setup directly int[] location = new int[2];
setupPinPadLayout(isOnlinePin); Rect r;
} else { customPinPadKeyboard.getKey_1().getLocationOnScreen(location);
// View not yet laid out wait for layout r = new Rect();
customPinPadKeyboard.getViewTreeObserver().addOnGlobalLayoutListener( r.left = location[0];
new ViewTreeObserver.OnGlobalLayoutListener() { r.top = location[1];
@Override r.right = customPinPadKeyboard.getKey_1().getWidth() + r.left;
public void onGlobalLayout() { r.bottom = customPinPadKeyboard.getKey_1().getHeight() + r.top;
if (customPinPadKeyboard.getWidth() > 0 && customPinPadKeyboard.getHeight() > 0) { pinpadLayout.setKey1(r);
customPinPadKeyboard.getViewTreeObserver().removeOnGlobalLayoutListener(this);
setupPinPadLayout(isOnlinePin); customPinPadKeyboard.getKey_2().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_2().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_2().getHeight() + r.top;
pinpadLayout.setKey2(r);
customPinPadKeyboard.getKey_3().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_3().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_3().getHeight() + r.top;
pinpadLayout.setKey3(r);
customPinPadKeyboard.getKey_4().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_4().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_4().getHeight() + r.top;
pinpadLayout.setKey4(r);
customPinPadKeyboard.getKey_5().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_5().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_5().getHeight() + r.top;
pinpadLayout.setKey5(r);
customPinPadKeyboard.getKey_6().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_6().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_6().getHeight() + r.top;
pinpadLayout.setKey6(r);
customPinPadKeyboard.getKey_7().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_7().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_7().getHeight() + r.top;
pinpadLayout.setKey7(r);
customPinPadKeyboard.getKey_8().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_8().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_8().getHeight() + r.top;
pinpadLayout.setKey8(r);
customPinPadKeyboard.getKey_9().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_9().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_9().getHeight() + r.top;
pinpadLayout.setKey9(r);
customPinPadKeyboard.getKey_0().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_0().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_0().getHeight() + r.top;
pinpadLayout.setKey10(r);
customPinPadKeyboard.getKey_cancel().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_cancel().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_cancel().getHeight() + r.top;
pinpadLayout.setKeyCancel(r);
customPinPadKeyboard.getKey_clear().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_clear().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_clear().getHeight() + r.top;
pinpadLayout.setKeyClear(r);
customPinPadKeyboard.getKey_ok().getLocationOnScreen(location);
r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = customPinPadKeyboard.getKey_ok().getWidth() + r.left;
r.bottom = customPinPadKeyboard.getKey_ok().getHeight() + r.top;
pinpadLayout.setKeyConfirm(r);
byte[] number = pinPad.setPinpadLayout(pinpadLayout);
OnPinPadInputListener pinPadInputListener = new OnPinPadInputListener() {
@Override
public void onInputResult(final int retCode, final byte[] data) {
if (retCode == SdkResult.Success) {
LogUtil.d(TAG, "Success");
if(isOnlinePin) {
mPayDetail.setPINCipher(ByteUtil.bytes2HexStr(data));
}
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else if (retCode == SdkResult.Fail) {
LogUtil.d(TAG, "Failure");
} else if (retCode == SdkResult.PinPad_Input_Cancel) {
LogUtil.d(TAG, "Cancel");
mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
} else if (retCode == SdkResult.PinPad_Input_Timeout) {
mHandler.obtainMessage(PIN_TIME_OUT,-7009).sendToTarget();
} else if (retCode == SdkResult.PinPad_No_Pin_Input) {
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else {
mHandler.obtainMessage(PIN_ERROR).sendToTarget();
}
LogUtil.d(TAG, "RetCode:" + retCode);
LogUtil.d(TAG, "data bytes:" + ByteUtil.bytes2HexStr(data));
} }
}
}
);
}
}
private void setupPinPadLayout(boolean isOnlinePin) { @Override
LogUtil.d(TAG, "inside the global layout!"); public void onSendKey(byte keyCode) {
PinpadLayoutEntity pinpadLayout = new PinpadLayoutEntity(); increaseCount();
if (keyCode == PinPadKeyCode.KEYCODE_CLEAR) {
LogUtil.d(TAG, "on clear");
mHandler.obtainMessage(PIN_CLICK_CLEAR).sendToTarget();
} else if (keyCode == PinPadKeyCode.KEYCODE_CANCEL) {
LogUtil.d(TAG, "on click cancel");
mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
} else if (keyCode == PinPadKeyCode.KEYCODE_CONFIRM) {
LogUtil.d(TAG, "on click confirm");
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else {
LogUtil.d(TAG, "on click number");
mHandler.obtainMessage(PIN_CLICK_NUMBER, pinEnterCount, 0).sendToTarget();
}
LogUtil.d(TAG, "SendKey: " + ByteUtil.byte2HexStr(keyCode));
}
};
// Helper to avoid repetition if (number != null) {
pinpadLayout.setKey1(getRectForView(customPinPadKeyboard.getKey_1())); customPinPadKeyboard.setKeyBoard(number);
pinpadLayout.setKey2(getRectForView(customPinPadKeyboard.getKey_2()));
pinpadLayout.setKey3(getRectForView(customPinPadKeyboard.getKey_3()));
pinpadLayout.setKey4(getRectForView(customPinPadKeyboard.getKey_4()));
pinpadLayout.setKey5(getRectForView(customPinPadKeyboard.getKey_5()));
pinpadLayout.setKey6(getRectForView(customPinPadKeyboard.getKey_6()));
pinpadLayout.setKey7(getRectForView(customPinPadKeyboard.getKey_7()));
pinpadLayout.setKey8(getRectForView(customPinPadKeyboard.getKey_8()));
pinpadLayout.setKey9(getRectForView(customPinPadKeyboard.getKey_9()));
pinpadLayout.setKey10(getRectForView(customPinPadKeyboard.getKey_0()));
pinpadLayout.setKeyCancel(getRectForView(customPinPadKeyboard.getKey_cancel()));
pinpadLayout.setKeyClear(getRectForView(customPinPadKeyboard.getKey_clear()));
pinpadLayout.setKeyConfirm(getRectForView(customPinPadKeyboard.getKey_ok()));
byte[] number = pinPad.setPinpadLayout(pinpadLayout);
OnPinPadInputListener pinPadInputListener = new OnPinPadInputListener() {
@Override
public void onInputResult(final int retCode, final byte[] data) {
if (retCode == SdkResult.Success) {
LogUtil.d(TAG, "Success");
if(isOnlinePin) {
mPayDetail.setPINCipher(ByteUtil.bytes2HexStr(data));
}
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else if (retCode == SdkResult.Fail) {
LogUtil.d(TAG, "Failure");
} else if (retCode == SdkResult.PinPad_Input_Cancel) {
LogUtil.d(TAG, "Cancel");
mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
} else if (retCode == SdkResult.PinPad_Input_Timeout) {
mHandler.obtainMessage(PIN_TIME_OUT,-7009).sendToTarget();
} else if (retCode == SdkResult.PinPad_No_Pin_Input) {
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else {
mHandler.obtainMessage(PIN_ERROR).sendToTarget();
}
LogUtil.d(TAG, "RetCode:" + retCode);
LogUtil.d(TAG, "data bytes:" + ByteUtil.bytes2HexStr(data));
}
@Override
public void onSendKey(byte keyCode) {
increaseCount();
if (keyCode == PinPadKeyCode.KEYCODE_CLEAR) {
LogUtil.d(TAG, "on clear");
mHandler.obtainMessage(PIN_CLICK_CLEAR).sendToTarget();
} else if (keyCode == PinPadKeyCode.KEYCODE_CANCEL) {
LogUtil.d(TAG, "on click cancel");
mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
} else if (keyCode == PinPadKeyCode.KEYCODE_CONFIRM) {
LogUtil.d(TAG, "on click confirm");
mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
} else {
LogUtil.d(TAG, "on click number");
mHandler.obtainMessage(PIN_CLICK_NUMBER, pinEnterCount, 0).sendToTarget();
}
LogUtil.d(TAG, "SendKey: " + ByteUtil.byte2HexStr(keyCode));
}
};
if (number != null) {
customPinPadKeyboard.setKeyBoard(number);
// customPinPadKeyboard.setKeyBoard(ByteUtil.bytes2HexStr(number)); // customPinPadKeyboard.setKeyBoard(ByteUtil.bytes2HexStr(number));
LogUtil.d(TAG, "PinPad: " + ByteUtil.bytes2HexStr(number)); LogUtil.d(TAG, "PinPad: " + ByteUtil.bytes2HexStr(number));
int[] supperLen = new int[]{0x00, 0x04, 0x06, 0x0c}; int[] supperLen = new int[]{0x00, 0x04, 0x06, 0x0c};
pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT); pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT);
pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED); pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED);
// pinPad.setAlgorithmMode(AlgorithmModeEnum.DES); // pinPad.setAlgorithmMode(AlgorithmModeEnum.DES);
if(cardNo == null){ if(cardNo == null){
cardNo = emvHandler.getEmvCardDataInfo().getCardNo(); cardNo = emvHandler.getEmvCardDataInfo().getCardNo();
} }
int length = cardNo.length(); int length = cardNo.length();
byte[] panBytes = cardNo.substring( length- 13).getBytes(StandardCharsets.US_ASCII); byte[] panBytes = cardNo.substring( length- 13).getBytes(StandardCharsets.US_ASCII);
LogUtil.d(TAG,"card num :"+cardNo); LogUtil.d(TAG,"card num :"+cardNo);
LogUtil.d(TAG,"Is Online Pin:"+isOnlinePin); LogUtil.d(TAG,"Is Online Pin:"+isOnlinePin);
// pinPad.inputOnlinePin(supperLen, 60, pan, 0, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener); // pinPad.inputOnlinePin(supperLen, 60, pan, 0, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener);
if (isOnlinePin) { if (isOnlinePin) {
pinPad.inputOnlinePin(supperLen, 60, panBytes, pinIndex, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener); pinPad.inputOnlinePin(supperLen, 60, panBytes, pinIndex, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener);
} else {
mPayDetail.transCVM = TransCVM.OFFLINE_PIN;
pinPad.inputOfflinePin(supperLen, 60, pinPadInputListener);
}
}
}
}
);
} else {
mPayDetail.transCVM = TransCVM.OFFLINE_PIN;
pinPad.inputOfflinePin(supperLen, 60, pinPadInputListener);
}
}
}
// Reusable rect helper
private Rect getRectForView(View view) {
int[] location = new int[2];
view.getLocationOnScreen(location);
Rect r = new Rect();
r.left = location[0];
r.top = location[1];
r.right = view.getWidth() + r.left;
r.bottom = view.getHeight() + r.top;
return r;
} }
private void increaseCount() { private void increaseCount() {
@ -613,11 +676,11 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
} }
} else { } else {
//contact terminal capability ; if different card brand(depend on aid) have different terminal capability //contact terminal capability ; if different card brand(depend on aid) have different terminal capability
// if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000004")) { if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000004")) {
// emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, ByteUtil.hexStr2Bytes(terminalCapability)); emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, ByteUtil.hexStr2Bytes(terminalCapability));
// emvHandler.setTlv(new byte[]{(byte) 0xE0, (byte) 0x1D}, ByteUtils.hexString2ByteArray("6C00800000000000"));//terminal risk emvHandler.setTlv(new byte[]{(byte) 0xE0, (byte) 0x1D}, ByteUtils.hexString2ByteArray("6C00800000000000"));//terminal risk
//
// } }
} }
emvHandler.onSetTransInitBeforeGPOResponse(true); emvHandler.onSetTransInitBeforeGPOResponse(true);
@ -642,9 +705,6 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
public void onCardHolderInputPin(boolean isOnlinePin, int leftTimes) { public void onCardHolderInputPin(boolean isOnlinePin, int leftTimes) {
LogUtil.d(TAG, "onCardHolderInputPin isOnlinePin = " + isOnlinePin); LogUtil.d(TAG, "onCardHolderInputPin isOnlinePin = " + isOnlinePin);
LogUtil.d(TAG, "onCardHolderInputPin leftTimes = " + leftTimes); LogUtil.d(TAG, "onCardHolderInputPin leftTimes = " + leftTimes);
if (isOnlinePin) {
pinRemainingCount.postValue("");
}
// startPinProcess(isOnlinePin ? 1 : 0); // startPinProcess(isOnlinePin ? 1 : 0);
mProcessStep = EMV_SHOW_PIN_PAD; mProcessStep = EMV_SHOW_PIN_PAD;
// mHandler.obtainMessage(EMV_SHOW_PIN_PAD, isOnlinePin ? 1 : 0).sendToTarget(); // mHandler.obtainMessage(EMV_SHOW_PIN_PAD, isOnlinePin ? 1 : 0).sendToTarget();
@ -683,17 +743,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
@Override @Override
public void onPrompt(PromptEnum promptEnum) { public void onPrompt(PromptEnum promptEnum) {
LogUtil.d(TAG, "onPrompt->" + promptEnum); LogUtil.d(TAG, "onPrompt->" + promptEnum);
if( promptEnum == PromptEnum.OFFLINE_PIN_INCORRECT_TRY_AGAIN) { emvHandler.onSetPromptResponse(true);
offlinePinIncorrectPromptCount++;
pinEnterCount = 0;
pinText.postValue("");
int attemptLeft = Math.max(0, 3 - offlinePinIncorrectPromptCount);
pinRemainingCount.postValue("Please try again!\n" + attemptLeft + " attempt left!");
emvHandler.onSetPromptResponse(false);
} else {
emvHandler.onSetPromptResponse(true);
}
} }
@Override @Override
@ -751,9 +801,6 @@ 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:
@ -920,7 +967,6 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
emvCardType.postValue(""); emvCardType.postValue("");
pinText.setValue(""); pinText.setValue("");
pinEnterCount = 0; pinEnterCount = 0;
offlinePinIncorrectPromptCount = 0;
} }
protected void getCardInfo() { protected void getCardInfo() {
@ -1210,7 +1256,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
kernelTTQ[1] = TTQ[1]; kernelTTQ[1] = TTQ[1];
kernelTTQ[2] = TTQ[2]; kernelTTQ[2] = TTQ[2];
kernelTTQ[3] = TTQ[3]; kernelTTQ[3] = TTQ[3];
// FIXME: 2019/3/20
//If there is no special requirements, do not change TTQ byte1 //If there is no special requirements, do not change TTQ byte1
//if online force required , can set byte2 bit 8 = 1 //if online force required , can set byte2 bit 8 = 1
emvHandler.setTlv(ByteUtils.hexString2ByteArray("9F66"), kernelTTQ); emvHandler.setTlv(ByteUtils.hexString2ByteArray("9F66"), kernelTTQ);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -154,6 +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) {
@ -176,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) {
@ -204,9 +205,6 @@ 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());
LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+emvOnlineResult.getAuthCode());
LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+emvOnlineResult.getRejCode());
LogUtil.d(TAG, "importOnlineProcessStatus emvOnlineResult:"+ ByteUtil.bytes2HexStr(emvOnlineResult.getRecvField55()));
PayLibNex.getInstance().deviceEngine.getEmvHandler2("app2").onSetOnlineProcResponse(sdkResult, emvOnlineResult); PayLibNex.getInstance().deviceEngine.getEmvHandler2("app2").onSetOnlineProcResponse(sdkResult, emvOnlineResult);
} }

View File

@ -2,10 +2,7 @@ package com.utsmyanmar.paylibs.utils.core_utils;
import android.text.TextUtils; import android.text.TextUtils;
import com.nexgo.oaf.apiv3.emv.EmvDataSourceEnum;
import com.nexgo.oaf.apiv3.emv.EmvHandler2;
import com.utsmyanmar.paylibs.Constant; import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.PayLibNex;
import com.utsmyanmar.paylibs.model.BaseCardInfo; import com.utsmyanmar.paylibs.model.BaseCardInfo;
import com.utsmyanmar.paylibs.model.CardInfo; import com.utsmyanmar.paylibs.model.CardInfo;
import com.utsmyanmar.paylibs.model.ICCardInfo; import com.utsmyanmar.paylibs.model.ICCardInfo;
@ -673,42 +670,43 @@ public class KernelDataProcessUtil {
} }
LogUtil.d(TAG,"9F6E data :"+hexStr); LogUtil.d(TAG,"9F6E data :"+hexStr);
byte[] dataOut = new byte[1024]; // byte[] dataOut = new byte[1024];
EmvHandler2 emvHandler = PayLibNex.getInstance().deviceEngine.getEmvHandler2("app2"); //
try { // try {
// int len = PayLibsUtils.getInstance().emvOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYWAVE, tagList, dataOut);
byte[] dateValue = emvHandler.getTlv(ByteUtil.hexStr2Bytes("9F6E"), EmvDataSourceEnum.FROM_CARD); // if (len > 0) {
if (dateValue != null) { // byte[] dataOutBytes = Arrays.copyOf(dataOut, len);
// hexStr = ByteUtil.bytes2HexStr(dataOutBytes);
hexStr = ByteUtil.bytes2HexStr(dateValue); // LogUtil.d(TAG, "get 9F6E Data :" + hexStr);
LogUtil.d(TAG, "get 9F6E Data :" + hexStr); // Map<String, TLV> map = TLVUtil.buildTLVMap(hexStr);
// LogUtil.d(TAG, "get 9F6E Data :" + map);
//
} else { // } else {
LogUtil.e(TAG, "Get the data length of payWave is null = " ); // LogUtil.e(TAG, "Get the data length of payWave is negative = " + len);
} // }
} catch (Exception e) { // } catch (Exception e) {
e.printStackTrace(); // e.printStackTrace();
} // }
//
// if (hexStr.equals("9F6E00")) { // if (hexStr.equals("9F6E00")) {
// try { // try {
// byte[] dateValue = emvHandler.getTlv(ByteUtil.hexStr2Bytes("9F6E"), EmvDataSourceEnum.FROM_CARD); // int len = PayLibsUtils.getInstance().emvOptV2.getTlvList(AidlConstantsV2.EMV.TLVOpCode.OP_PAYPASS, tagList, dataOut);
// if (dateValue != null) { // if (len > 0) {
// hexStr = ByteUtil.bytes2HexStr(dateValue); // byte[] dataOutBytes = Arrays.copyOf(dataOut, len);
// hexStr = ByteUtil.bytes2HexStr(dataOutBytes);
// LogUtil.d(TAG, "get 9F6E Data :" + hexStr); // LogUtil.d(TAG, "get 9F6E Data :" + hexStr);
// Map<String, TLV> map = TLVUtil.buildTLVMap(hexStr); // Map<String, TLV> map = TLVUtil.buildTLVMap(hexStr);
// LogUtil.d(TAG, "get 9F6E Data :" + map); // LogUtil.d(TAG, "get 9F6E Data :" + map);
// //
// } else { // } else {
// LogUtil.e(TAG, "Get the data length of payPass is null = "); // LogUtil.e(TAG, "Get the data length of payPass is negative = " + len);
// } // }
// } catch (Exception e) { // } catch (Exception e) {
// e.printStackTrace(); // e.printStackTrace();
// } // }
// } // }
// if (!hexStr.isEmpty()) { // if (!hexStr.equals("9F6E00")) {
// f55WaveDataStr += "9F6E04"+hexStr; // f55WaveDataStr += hexStr;
// } // }
icCardInfo.setICC55(f55WaveDataStr); icCardInfo.setICC55(f55WaveDataStr);
payDetail.setICC55(f55WaveDataStr); payDetail.setICC55(f55WaveDataStr);

View File

@ -69,8 +69,7 @@ public class BitmapConfig {
// public static final String BPC_VOID = "3230058028C08000"; // public static final String BPC_VOID = "3230058028C08000";
// commented on Nov 13,2024 // commented on Nov 13,2024
// public static final String BPC_VOID = "3230058028C18000"; // original public static final String BPC_VOID = "3230058028C18000"; // original
public static final String BPC_VOID = "3230058028C08000"; // original March 25, 2026
// public static final String BPC_VOID = "3230058028C08000"; // 16-May-2025 removed DE48 requested by KoAAT added DE2 // public static final String BPC_VOID = "3230058028C08000"; // 16-May-2025 removed DE48 requested by KoAAT added DE2
// public static final String BPC_VOID = "3230058028C08000"; // 16-May-2025 removed DE48 requested by KoAAT // public static final String BPC_VOID = "3230058028C08000"; // 16-May-2025 removed DE48 requested by KoAAT
// public static final String BPC_VOID = "3230058028C18200"; // public static final String BPC_VOID = "3230058028C18200";
@ -109,9 +108,8 @@ public class BitmapConfig {
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7230058028C19800"; // added DE 2 // public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7230058028C19800"; // added DE 2
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7234058008C09000"; // for tmk MPU // public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7234058008C09000"; // for tmk MPU
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7230058008C09000"; // for KBZ MPU // public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7230058008C09000"; // for KBZ MPU
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7234058008C09000"; // for KBZ MPU added DE 14 Mar 25, 26 public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "7234058008C09000"; // for KBZ MPU added DE 14
public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "3230058028C08000"; // from log March 25 // public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "3230058028C19800";
// public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "3230058028C19A00"; //DE55 // public static final String BPC_PRE_AUTH_SALE_VOID_REVERSAL = "3230058028C19A00"; //DE55
// //
// public static final String BPC_PRE_AUTH_SALE_COMPLETE_VOID = "3230058028C09200"; // public static final String BPC_PRE_AUTH_SALE_COMPLETE_VOID = "3230058028C09200";

View File

@ -341,8 +341,7 @@ public class FieldUtils {
} else if (BaseCardType.IC.getValue() == cardType) { // IC } else if (BaseCardType.IC.getValue() == cardType) { // IC
value = "05"; value = "05";
} else if (FALLBACK == cardType){ // Fallback } else if (FALLBACK == cardType){ // Fallback
value = "72"; value = "08";
// value = "08";
} else { // Hand-in card number } else { // Hand-in card number
value = "01"; value = "01";
} }
@ -351,16 +350,11 @@ public class FieldUtils {
if(payDetail.getTransCVM() == TransCVM.OFFLINE_PIN) { if(payDetail.getTransCVM() == TransCVM.OFFLINE_PIN) {
value += "9"; value += "9";
} else { } else {
if(payDetail.getTransactionType() == VOID.value) { if (payDetail.getPINCipher() != null && !payDetail.getPINCipher().trim().isEmpty()) {
value += "0"; value += "1";
} else { } else {
if (payDetail.getPINCipher() != null && !payDetail.getPINCipher().trim().isEmpty()) { value += "2";
value += "1";
} else {
value += "2";
}
} }
} }

View File

@ -32,7 +32,7 @@ include ':baselib'
include ':mpulib' include ':mpulib'
//include ':ecr-client-lib' //include ':ecr-client-lib'
//include ':ecr-service' include ':ecr-service'
include ':xpay' include ':xpay'
include ':ecr' include ':ecr'
include ':ecr-service-lib' include ':ecr-service-lib'