Compare commits

..

No commits in common. "8cd56777cc3d32989d19f6a215d35ebe527b0720" and "9502ee7a045149773a473fd2a6c0eb60d95b291a" have entirely different histories.

99 changed files with 491 additions and 4379 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
<bytecodeTargetLevel target="17" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AskMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Ask2AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EditMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@ -4,6 +4,14 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-10-28T19:40:02.148831Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=0123456789ABCDEF" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>

View File

@ -6,7 +6,7 @@
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="gradleJvm" value="17 (2)" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />

View File

@ -1,4 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@ -90,6 +90,7 @@ dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
def nav_version = "2.3.2"
def lottieVersion = "3.5.0"
def fragment_version = "1.2.0"
@ -195,10 +196,6 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
androidTestImplementation 'androidx.test:core:1.5.0'
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
// Add Mockito dependency for mocking
testImplementation 'org.mockito:mockito-core:3.12.4'
androidTestImplementation 'org.mockito:mockito-android:3.12.4'

Binary file not shown.

View File

@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 7,
"versionName": "1.07",
"versionCode": 6,
"versionName": "1.06",
"outputFile": "app-release.apk"
}
],

View File

@ -10,29 +10,6 @@ import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import com.sunmi.pay.hardware.aidl.AidlConstants;
import com.utsmm.kbz.util.MockData;
import com.utsmm.kbz.util.TransactionUtil;
import com.utsmyanmar.checkxread.model.CardDataX;
import com.utsmyanmar.checkxread.util.CardTypeX;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.isobuilder.ISOMode;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.model.enums.TransCVM;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.MessageType;
import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.HostName;
import com.utsmyanmar.paylibs.utils.iso_utils.BitmapConfig;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.params.Params;
import java.util.Locale;
/**
* Instrumented test, which will execute on an Android device.
*
@ -46,131 +23,4 @@ public class ExampleInstrumentedTest {
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.utsmm.kbz", appContext.getPackageName());
}
@Test
public void testVoidPacket() {
CardDataX cardDataX = MockData.getInstance().generateMPUCard();
TradeData tradeData = TransactionUtil.getInstance().initMPUTransaction(cardDataX, CardTypeX.IC);
String bitmap = BitmapConfig.MPU_NEW_VOID;
MessageType messageType = MessageType.FINANCIAL;
ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1987, ISOMode.ONLY_HEADER, HostName.FINEXUS)
.build();
TradeData transTradeData = setUpRebuildTransactions(tradeData, TransactionsType.VOID, HostName.FINEXUS);
transTradeData.getPayDetail().setAmount(50000);
PayDetail transPayDetail = transTradeData.getPayDetail();
byte[] sendBytes;
try {
sendBytes = isoMsgX.buildISOPackets(transTradeData, bitmap, messageType);
System.out.println("Hex Str : "+ ByteUtil.bytes2HexStr(sendBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
private TradeData setUpRebuildTransactions(TradeData tradeData, TransactionsType transactionsType, HostName hostName) {
LogUtil.d(Constant.TAG, "Starting Online Transaction--" + hostName + "--" + transactionsType);
TradeData newTrade = Params.newTrade(true);
PayDetail newPay = newTrade.getPayDetail();
PayDetail oldPay = tradeData.getPayDetail();
newPay.setCardType(100);
newPay.setPINCipher("");
newPay.setHostName(hostName.name);
newPay.setTransType(transactionsType.name);
newPay.setProcessCode(transactionsType.processCode);
newPay.setCardNo(oldPay.getCardNo());
newPay.setCardHolderName(oldPay.getCardHolderName());
newPay.setEXPDate(oldPay.getEXPDate());
newPay.setTradeDate(oldPay.getTradeDate());
newPay.setTradeTime(oldPay.getTradeTime());
newPay.setAmount(oldPay.getAmount());
newPay.setTransactionType(transactionsType.value);
newPay.setAccountType(oldPay.getAccountType());
newPay.setCardInfo(oldPay.getCardInfo());
newPay.setSettlementEnabled(SystemParamsOperation.getInstance().getSettlementStatus());
// added on Nov, 13 2024
newPay.setICC55(oldPay.getICC55());
if(newPay.getICC55() != null && !newPay.getICC55().isEmpty()) {
newPay.setAppLabel(oldPay.getAppLabel());
newPay.setAppName(oldPay.getAppName());
newPay.setTSI(oldPay.getTSI());
newPay.setAID(oldPay.getAID());
newPay.setArqC(oldPay.getArqC());
newPay.setTVR(oldPay.getTVR());
}
if(transactionsType != TransactionsType.PRE_AUTH_COMPLETE) {
newPay.setTradeDateTime(oldPay.getTradeDateTime());
}
if (transactionsType == TransactionsType.VOID || transactionsType == TransactionsType.REFUND) {
String field60;
if(hostName == HostName.BPC) {
field60 = String.format(Locale.getDefault(), "%010d00", oldPay.getAmount());
} else {
field60 = String.format(Locale.getDefault(), "%012d", oldPay.getAmount());
}
// String field60 = String.format(Locale.getDefault(), "%010d00", oldPay.getAmount());
newPay.setReferNo(oldPay.getReferNo());
newPay.setTransCVM(TransCVM.SIGNATURE);
newTrade.setField60(field60);
} else if (transactionsType == TransactionsType.PRE_AUTH_VOID) {
newPay.setCardType(oldPay.getCardType());
newPay.setCustomOrderNo(oldPay.getVoucherNo());
newPay.setReferNo(oldPay.getReferNo());
newPay.setCardInfo(oldPay.getCardInfo());
newPay.setPINCipher(oldPay.getPINCipher());
newPay.setTempKSN(oldPay.getTempKSN());
newPay.setTransCVM(TransCVM.SIGNATURE);
// for manual entry reversal which need de 35
} else if (transactionsType == TransactionsType.TIP_ADJUSTMENT ) {
newPay.setReferNo(oldPay.getReferNo());
newPay.setApprovalCode(oldPay.getApprovalCode());
} else if (transactionsType == TransactionsType.PRE_AUTH_COMPLETE) {
newPay.setCardType(oldPay.getCardType());
newPay.setCardInfo(oldPay.getCardInfo());
newPay.setPINCipher(oldPay.getPINCipher());
newPay.setReferNo(oldPay.getReferNo());
newPay.setTempKSN(oldPay.getTempKSN());
} else if (transactionsType == TransactionsType.PRE_AUTH_COMPLETE_VOID) {
newPay.setVoucherNo(oldPay.getVoucherNo());
newPay.setCustomOrderNo(oldPay.getVoucherNo());
newPay.setReferNo(oldPay.getReferNo());
newPay.setCardInfo(oldPay.getCardInfo());
/*
* new requirements */
newPay.setCardType(AidlConstants.CardType.IC.getValue());
newPay.setPINCipher("55");
newPay.setTransCVM(TransCVM.SIGNATURE);
}
if(oldPay.getAccountType().equals("MPU")){
// newPay.setIsFreeSign(true);
newPay.setTransCVM(TransCVM.SIGNATURE);
}
newTrade.setPayDetail(newPay);
return newTrade;
}
}

View File

@ -55,11 +55,10 @@
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.journeyapps.barcodescanner.CaptureActivity"

View File

@ -849,12 +849,6 @@ public class MainFragment extends DataBindingFragment {
}
}
public void onClickQR(){
// navigate to new QR Pay fragment
routeId = R.id.action_nav_main_to_qrFragment;
safeNavigateToRouteId();
}
public void onClickQRPay() {
String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress();

View File

@ -1,76 +0,0 @@
package com.utsmm.kbz.ui.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.ItemQrPayButtonBinding;
import com.utsmm.kbz.ui.qr_pay.QRPayItem;
import java.util.List;
public class QRPayAdapter extends RecyclerView.Adapter<QRPayAdapter.ViewHolder> {
public interface OnItemClickListener {
void onItemClick(int position);
}
private final List<QRPayItem> items;
private final OnItemClickListener listener;
public QRPayAdapter(List<QRPayItem> item, OnItemClickListener listener) {
this.items = item;
this.listener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemQrPayButtonBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_qr_pay_button,
parent,
false
);
return new ViewHolder(binding);
}
private final int[] colors = new int[]{
R.color.colorPrimary,
R.color.amber,
R.color.forestGreen
};
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
QRPayItem item = items.get(position);
holder.binding.setText(item.title);
holder.binding.setIcon(item.icon);
holder.binding.btnItem.setOnClickListener(v -> {
if(listener != null){
listener.onItemClick(position);
}
});
}
@Override
public int getItemCount() {
return items == null ? 0 : items.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
final ItemQrPayButtonBinding binding;
public ViewHolder(@NonNull ItemQrPayButtonBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}

View File

@ -142,10 +142,6 @@ public class InputPasswordFragment extends DataBindingFragment implements DataBi
private void checkRoute() {
switch (Objects.requireNonNull(sharedViewModel.transactionsType.getValue())) {
case MMQR_REFUND:
inputPasswordViewModel.passwordType.setValue(InputPasswordType.SYSTEM);
routeId = R.id.action_inputPasswordFragment_to_QRRefundProcessFragment;
break;
case PRE_AUTH_COMPLETE_VOID:
inputPasswordViewModel.passwordType.setValue(InputPasswordType.SYSTEM);
sharedViewModel.transactionName.postValue(getResourceString(R.string.title_pre_auth_complete));

View File

@ -254,6 +254,7 @@ public class ProcessingFragment extends DataBindingFragment {
case FAIL:
case SUCCESS:
case OFFLINE_SUCCESS:
LogUtil.d(TAG,"This was called!");
if(SystemParamsOperation.getInstance().getDemoStatus()) {
delayFunctionCall(()->{
// updateData();

View File

@ -49,6 +49,7 @@ public class CardReadViewModel extends ViewModel {
public SingleLiveEvent<PayDetail> payDetail = new SingleLiveEvent<>();
public SingleLiveEvent<String> checkCardAlertMsg = new SingleLiveEvent<>();
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
@ -104,4 +105,5 @@ public class CardReadViewModel extends ViewModel {
NexGoSDK.getInstance().cancelCheckCard();
}
}

View File

@ -185,15 +185,6 @@ public class SharedViewModel extends ViewModel {
printReceiptButtons.postValue(value);
}
public void setTransactionsType(TransactionsType transactionsType) {
this.transactionsType.setValue(transactionsType);
}
public SingleLiveEvent<TransactionsType> getTransactionsType() {
return transactionsType;
}
public void setPrintReceiptMsg(String msg) { this.printReceiptMsg.setValue(msg);}
public void postPrintReceiptMsg(String msg) { this.printReceiptMsg.postValue(msg);}
public void setPrintStatus(PrintStatus printStatus) { this.printStatus.setValue(printStatus); }
public void postPrintStatus(PrintStatus printStatus) { this.printStatus.postValue(printStatus); }

View File

@ -135,7 +135,7 @@ public class DashboardTransFragment extends DataBindingFragment {
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
sharedViewModel.setTransactionsType(TransactionsType.VOID);
sharedViewModel.transactionsType.setValue(TransactionsType.VOID);
// sharedViewModel.transMenu.postValue(TransMenu.TRANSACTIONS);
sharedViewModel.setTransMenu(TransMenu.TRANSACTIONS);
@ -147,15 +147,16 @@ public class DashboardTransFragment extends DataBindingFragment {
public void onClickSettlement() {
sharedViewModel.settlementType.setValue(SettlementType.NORMAL);
sharedViewModel.transactionsType.setValue(TransactionsType.SETTLEMENT);
sharedViewModel.setTransMenu(TransMenu.SETTLEMENT);
sharedViewModel.setTransactionsType(TransactionsType.SETTLEMENT);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickRefund() {
sharedViewModel.setTransactionsType(TransactionsType.REFUND);
sharedViewModel.transactionsType.setValue(TransactionsType.REFUND);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
@ -166,7 +167,8 @@ public class DashboardTransFragment extends DataBindingFragment {
} else if (checkTid()) {
showDeclineDialog("Please Download Config!");
} else {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_SALE);
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_SALE);
routeId = R.id.action_dashboardTransFragment_to_inputAmountFragment;
safeRouteTo(currentId,routeId,hostId);
}
@ -174,7 +176,7 @@ public class DashboardTransFragment extends DataBindingFragment {
}
public void onClickPreAuthCancel () {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_VOID);
sharedViewModel.setTransMenu(TransMenu.PRE_AUTH_FULL_VOID);
sharedViewModel.amount.postValue(null);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
@ -183,14 +185,14 @@ public class DashboardTransFragment extends DataBindingFragment {
}
public void onClickPreAuthComp () {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_COMPLETE);
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_COMPLETE);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
}
public void onClickPreAuthCompCancel () {
sharedViewModel.setTransactionsType(TransactionsType.PRE_AUTH_COMPLETE_VOID);
sharedViewModel.transactionsType.setValue(TransactionsType.PRE_AUTH_COMPLETE_VOID);
routeId = R.id.action_dashboardTransFragment_to_inputPasswordFragment;
safeRouteTo(currentId,routeId,hostId);
@ -198,8 +200,7 @@ public class DashboardTransFragment extends DataBindingFragment {
public void onClickCashAdvance() {
sharedViewModel.setTransactionsType(TransactionsType.CASH_OUT);
sharedViewModel.setTransMenu(TransMenu.CASH_OUT);
sharedViewModel.transactionsType.setValue(TransactionsType.CASH_OUT);
routeId = R.id.action_dashboardTransFragment_to_inputAmountFragment;
safeRouteTo(currentId,routeId,hostId);

View File

@ -13,7 +13,6 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.kizzy.xpay.util.Sign;
import com.utsmm.kbz.ui.qr_pay.QRRefund;
import com.utsmyanmar.baselib.network.model.DemoQRRequest;
import com.utsmyanmar.baselib.network.model.DemoQRResponse;
import com.utsmyanmar.baselib.network.model.DemoQRReturnRequest;
@ -297,7 +296,6 @@ public class KPayViewModel extends ViewModel {
private TradeData tradeData;
private PayDetail payDetail;
private QRRefund qrRefund;
public void setTradeData(TradeData tradeData){
this.tradeData = tradeData;
@ -311,12 +309,6 @@ public class KPayViewModel extends ViewModel {
public void setPayDetail(PayDetail payDetail) {
this.payDetail = payDetail;
}
public void setQrRefund(QRRefund qrRefund) {
this.qrRefund = qrRefund;
}
public QRRefund getQrRefund() {
return qrRefund;
}
public PayDetail getPayDetail() { return payDetail; }

View File

@ -13,7 +13,6 @@ import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.pinpad.AlgorithmModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.OnPinPadInputListener;
import com.nexgo.oaf.apiv3.device.pinpad.PinAlgorithmModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.PinKeyboardModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.PinKeyboardViewModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.PinPad;
import com.nexgo.oaf.apiv3.device.pinpad.PinPadKeyCode;
@ -323,8 +322,6 @@ public class PinPadViewModel extends ViewModel {
r.bottom = customPinPadKeyboard.getKey_ok().getHeight() + r.top;
pinpadLayout.setKeyConfirm(r);
pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED);
byte[] number = pinPad.setPinpadLayout(pinpadLayout);
if(number != null) {
@ -339,8 +336,6 @@ public class PinPadViewModel extends ViewModel {
byte[] panBytes = pan.substring(length - 13).getBytes(StandardCharsets.US_ASCII);
// byte[] panBytes = pan.substring(length - 13, length - 1).getBytes(StandardCharsets.US_ASCII);
pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT);
pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED);
// pinPad.setAlgorithmMode(AlgorithmModeEnum.DES);

View File

@ -1,61 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.ItemQrHistoryBinding;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.ArrayList;
import java.util.List;
public class QRHistoryAdapter extends RecyclerView.Adapter<QRHistoryAdapter.ViewHolder> {
private List<PayDetail> items = new ArrayList<>();
public void setItems(List<PayDetail> data){
items = data;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemQrHistoryBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_qr_history,
parent,
false
);
return new ViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.bind(items.get(position));
}
@Override
public int getItemCount() {
return items.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private final ItemQrHistoryBinding binding;
public ViewHolder(@NonNull ItemQrHistoryBinding binding){
super(binding.getRoot());
this.binding = binding;
}
public void bind(PayDetail item){
binding.setPayDetail(item);
binding.executePendingBindings();
}
}
}

View File

@ -1,78 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
public class QRHistoryFragment extends DataBindingFragment {
private QRHistoryAdapter adapter;
private QRHistoryViewModel viewModel;
@Override
protected void initViewModel() {
viewModel = new ViewModelProvider(this).get(QRHistoryViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
DataBindingConfig bindingConfig = new DataBindingConfig(R.layout.fragment_qr_history, BR.viewModel, viewModel);
bindingConfig.addBindingParam(BR.adapter, adapter);
return bindingConfig;
}
@Override
protected int currentId() {
return 0;
}
@Override
protected int hostId() {
return 0;
}
@Override
protected int routeId() {
return 0;
}
@Override
public void onResume(){
super.onResume();
setToolBarTitleWithBackIcon("History");
observeData();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstance){
super.onViewCreated(view, savedInstance);
RecyclerView rvHistory = view.findViewById(R.id.qrRvHistory);
rvHistory.setLayoutManager(new LinearLayoutManager(getContext()));
adapter = new QRHistoryAdapter();
rvHistory.setAdapter(adapter);
observeData();
}
private void observeData(){
viewModel.getAllQrHistory().observe(getViewLifecycleOwner(), list -> {
adapter.setItems(list);
});
}
}

View File

@ -1,35 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@HiltViewModel
public class QRHistoryViewModel extends ViewModel {
private final Repository repository;
private final LiveData<List<PayDetail>> history;
private final LiveData<List<PayDetail>> refundList;
@Inject
public QRHistoryViewModel(Repository repository){
this.repository = repository;
this.history = repository.getAllQRHistory();
this.refundList = repository.getRefundableQRHistory();
}
public LiveData<List<PayDetail>> getAllQrHistory(){
return history;
}
public LiveData<List<PayDetail>> getRefundableQrHistory(){
return refundList;
}
}

View File

@ -1,400 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.MainViewModel;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.adapters.QRPayAdapter;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.management.ManagementViewModel;
import com.utsmm.kbz.ui.settlement.SettlementViewModel;
import com.utsmm.kbz.util.Connectivity;
import com.utsmm.kbz.util.tms.TMSUtil;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.utils.POSUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
import com.utsmyanmar.paylibs.utils.enums.HostType;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import java.util.Date;
import java.util.List;
public class QRPayFragment extends DataBindingFragment {
private MainViewModel mainViewModel;
private SharedViewModel sharedViewModel;
private static final int hostId = Constants.NAV_HOST_ID;
private int routeId;
private static final int currentId = R.id.qrFragment;
private Observer<PayDetail> observeLastTrans;
private PayDetail lastPay;
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon("MMQR PAY");
}
@Override
protected void initViewModel() {
mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
// sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
List<QRPayItem> features = List.of(
new QRPayItem("Sale", R.drawable.ic_qr_pay),
new QRPayItem("Refund", R.drawable.ic_refund),
new QRPayItem("History", R.drawable.ic_history)
);
QRPayAdapter adapter = new QRPayAdapter(features, position -> {
QRPayItem selectedBtn = features.get(position);
switch (selectedBtn.title){
case "Sale":
onClickQRPay();
break;
case "Refund":
onClickRefund();
break;
case "History":
onClickHistory();
break;
}
});
DataBindingConfig config = new DataBindingConfig(R.layout.fragment_qr_pay, BR.mainViewModel, mainViewModel);
config.addBindingParam(BR.sharedViewModel,sharedViewModel);
config.addBindingParam(BR.adapter, adapter);
return config;
}
@Override
protected int currentId() {
return currentId;
}
@Override
protected int hostId() {
return hostId;
}
@Override
protected int routeId() {
return routeId;
}
public void onClickQRPay() {
String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress();
if (mainViewModel.payDetailSingle.getValue() != null) {
mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue());
}
// else if (TMSUtil.getInstance().checkSecHostParams().isStatus() == ValidityStatus.FAILURE) {
// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkSecHostParams().getMessage());
// }
else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
}
// else if (!isValidDomain(mmqrIp)) {
// showDeclineDialog(getResourceString(R.string.txt_please_check_mmqr_ip));
// }
else {
CurrencyType currencyType = TMSUtil.getInstance().currencyTextToCurrencyType(SystemParamsOperation.getInstance().getSecHostCurrency());
sharedViewModel.set_currencyText(currencyType.name);
processBatch();
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR);
navigateToAmount();
}
}
private void onClickHistory(){
sharedViewModel.hostType.setValue(HostType.QR);
routeId = R.id.action_qrFragment_to_qrHistory;
safeNavigateToRouteId();
}
private void onClickRefund(){
// sharedViewModel.setTransactionsType(TransactionsType.MMQR_REFUND);
routeId = R.id.action_qrFragment_to_qr_refund_list;
// routeId = R.id.action_qrFragment_to_inputPasswordFragment;
safeNavigateToRouteId();
}
private void navigateToAmount() {
routeId = R.id.action_qrFragment_to_inputAmountFragment;
safeNavigateToRouteId();
}
private void processBatch() {
calculateLastTransaction();
mainViewModel.observeSettlementPOS();
observeLastTrans = payDetail -> {
if(payDetail == null) {
return;
}
// SystemParamsOperation.getInstance().saveSerialNumber(payDetail.getVoucherNo());
// SystemParamsOperation.getInstance().saveInvoiceNumber(payDetail.getInvoiceNo());
if(lastPay != null) {
Date lastPayDate = POSUtil.getInstance().getDateByString(lastPay.getTransDate());
Date observePayDate = POSUtil.getInstance().getDateByString(payDetail.getTransDate());
if(lastPayDate.compareTo(observePayDate) < 0) {
payDetail = lastPay;
}
}
// LogUtil.d(TAG,"TransDetail :"+payDetail.getTransType() + "- Trans Time :"+payDetail.getTransDate());
if(payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value){
return;
}
/*
* saving for api post request, to send in next time.
* */
SystemParamsOperation.getInstance().setLastTransTime(String.valueOf(payDetail.getTransNum()));
SystemParamsOperation.getInstance().setLastTransName(payDetail.getTransType());
String lastTransDate = payDetail.getTransDate();
String lastTransTime = payDetail.getTransTime();
Date today = POSUtil.getInstance().getCurrentDate();
Date transDate;
Date current = new Date(System.currentTimeMillis());
String configTimer = SystemParamsOperation.getInstance().getClearBatchTime();
// LogUtil.d(TAG,"Config Time :" + configTimer);
String configTime = "23:00";
int configDay = 10;
String configRawDay = SystemParamsOperation.getInstance().getClearBatchDay();
if(configRawDay != null && !configRawDay.trim().isEmpty()) {
try {
configDay = Integer.parseInt(configRawDay);
} catch (Exception e) {
e.printStackTrace();
}
}
if(configTimer != null && !configTimer.trim().isEmpty() && checkValidTime(configTimer.trim())) {
configTime = configTimer.trim();
}
Date configDateTime = POSUtil.getInstance().getDateTime(configTime);
Date yesterdayConfigDateTime = POSUtil.getInstance().getYesterdayConfigDateTime(configTime);
transDate = POSUtil.getInstance().getDateByString(lastTransDate);
Date yesterdayDate = POSUtil.getInstance().getYesterdayDate();
if(today.compareTo(transDate) == 0) {
// LogUtil.d(TAG,"Last Trans is Today!");
// LogUtil.d(TAG,"date current :!"+current);
// LogUtil.d(TAG,"date config :!"+configDateTime);
// Today
if(current.compareTo(configDateTime) > 0) {
// clear batch and force update param
// LogUtil.d(TAG,"Last Trans is Today! Config time is passed!");
// if (!SystemParamsOperation.getInstance().isClearBatch()) {
if (checkSyncTrans() || !SystemParamsOperation.getInstance().isClearBatch() ) {
// LogUtil.d(TAG,"Clearing....");
if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
clearBatchAndDownload(configDay,payDetail);
}
}
} else {
// LogUtil.d(TAG,"Last Trans is Today! Config time is not passed yet.....");
SystemParamsOperation.getInstance().setClearBatch(false);
}
} else {
// LogUtil.d(TAG,"Last Trans is Before Today!");
Date yest;
if(configTime.equals("00:00")) {
yest = configDateTime;
} else {
yest = yesterdayConfigDateTime;
}
Date lastTransDateTime = POSUtil.getInstance().getDateByTransDateTime(lastTransDate,lastTransTime);
// LogUtil.d(TAG,"Compare Result : "+lastTransDateTime.compareTo(yest));
if(yest.compareTo(lastTransDateTime) < 0) {
// LogUtil.d(TAG,"Trans is yesterday, but after config time, no action!");
} else {
// LogUtil.d(TAG,"Trans is yesterday, before config time,");
// if(!checkSyncTrans()) {
// LogUtil.d(TAG,"Clearing....");
if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
clearBatchAndDownload(configDay,payDetail);
}
// }
}
}
};
if(mainViewModel.lastTrans.hasActiveObservers()) {
mainViewModel.lastTrans.removeObserver(observeLastTrans);
}
mainViewModel.lastTrans.observe(getViewLifecycleOwner(),observeLastTrans);
}
private void calculateLastTransaction() {
mainViewModel.allTrans.observe(getViewLifecycleOwner(), new Observer<List<PayDetail>>() {
@Override
public void onChanged(List<PayDetail> payDetails) {
if(payDetails == null || payDetails.isEmpty()) {
return;
}
PayDetail tempPay = payDetails.get(0);
for (int i = 0; i < payDetails.size() ; i++) {
Date tempDate = POSUtil.getInstance().getDateByString(tempPay.getTransDate());
Date indexDate = POSUtil.getInstance().getDateByString(payDetails.get(i).getTransDate());
if(tempDate.compareTo(indexDate) > 0) {
// if before
tempPay = payDetails.get(i);
}
}
lastPay = tempPay;
// LogUtil.d(TAG,"Transaction Name : "+tempPay.getTransType());
// LogUtil.d(TAG,"Transaction Type : "+tempPay.getTransactionType());
// LogUtil.d(TAG,"Transaction Amount : "+tempPay.getAmount());
// LogUtil.d(TAG,"Transaction Date/Time : "+tempPay.getTransDate()+"/"+tempPay.getTransTime());
// LogUtil.d(TAG,"RRN/Trace : "+tempPay.getReferNo()+"/"+tempPay.getVoucherNo());
// LogUtil.d(TAG,"Transaction is canceled : "+tempPay.isCanceled());
// LogUtil.d(TAG,"Transaction settlement config : "+tempPay.isSettlementEnabled());
// LogUtil.d(TAG,"----------------------------------------------------------");
}
});
}
private boolean checkSyncTrans() {
String transDateString = SystemParamsOperation.getInstance().getSyncTransDate();
Date today = POSUtil.getInstance().getCurrentDate();
if(transDateString == null || transDateString.isEmpty()) {
return true;
}
Date transDate = POSUtil.getInstance().getDateByString(transDateString);
return today.compareTo(transDate) == 0;
}
private void clearBatchAndDownload(int configDay,PayDetail payDetail) {
Date yesterday = POSUtil.getInstance().getYesterdayDate();
Date lastInputDay = POSUtil.getInstance().getLastInputDay(configDay);
mainViewModel.settlementPOS.observe(getViewLifecycleOwner(), list -> {
Date transDate;
if(list == null || list.size() == 0) {
return;
}
for (PayDetail pay:list) {
/*
* To Hold One day transaction!
* */
transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
if (pay.getTransactionType() == TransactionsType.SALE.value) {
if(lastInputDay.compareTo(transDate) > 0) {
mainViewModel.deletePayDetail(pay);
}
} else {
if(yesterday.compareTo(transDate) > 0 ) {
mainViewModel.deletePayDetail(pay);
}
}
}
});
mainViewModel.deleteTrans.observe(getViewLifecycleOwner(), lists -> {
Date transDate;
if(lists == null || lists.size() == 0) {
return;
}
for (PayDetail pay:lists) {
/*
* To Hold One day transaction!
* */
transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
// LogUtil.d(TAG,"Trans Type : "+pay.getTransType()+"<=====> Trans Date :"+pay.getTransDate());
// LogUtil.d(TAG,"Yesterday Date: "+yesterday.toString());
// LogUtil.d(TAG,"Compare result :"+yesterday.compareTo(transDate));
if(yesterday.compareTo(transDate) > 0) {
mainViewModel.deletePayDetail(pay);
}
}
});
mainViewModel.preAuthTrans.observe(getViewLifecycleOwner(), lists -> {
Date transDate;
if(lists == null || lists.size() == 0) {
return;
}
for (PayDetail pay:lists) {
transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
if (lastInputDay.compareTo(transDate) > 0) {
mainViewModel.deletePayDetail(pay);
}
}
});
/*
*
* Need to think about his problem .... Nov 7, 2024
* */
if(!SystemParamsOperation.getInstance().isClearBatch()) {
// downloadParams(payDetail.getTransType(),String.valueOf(payDetail.getTransNum()),TMSUpdate.UPDATE,false);
}
}
}

View File

@ -1,11 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
public class QRPayItem {
public String title;
public int icon;
public QRPayItem(String title, int icon) {
this.title = title;
this.icon = icon;
}
}

View File

@ -1,42 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.utsmyanmar.baselib.repo.Repository;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@HiltViewModel
public class QRPayViewModel extends ViewModel {
private final Repository repository;
private final LiveData<List<PayDetail>> refundableHistory;
private final MutableLiveData<PayDetail> _payDetail = new MutableLiveData<>();
public LiveData<PayDetail> payDetail = _payDetail;
@Inject
public QRPayViewModel(Repository repository){
this.repository = repository;
this.refundableHistory = repository.getRefundableQRHistory();
}
public LiveData<List<PayDetail>> getRefundableQrHistory(){
return refundableHistory;
}
public void setPayDetail(PayDetail payDetail){
_payDetail.setValue(payDetail);
}
public Runnable onCancel;
public Runnable onConfirm;
}

View File

@ -1,49 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
public class QRRefund {
private String referenceNo;
private String refundAmount;
private String originalAmount;
private String reason;
public QRRefund(String referenceNo, String refundAmount, String originalAmount, String reason) {
this.referenceNo = referenceNo;
this.refundAmount = refundAmount;
this.originalAmount = originalAmount;
this.reason = reason;
}
public String getReferenceNo() {
return referenceNo;
}
public void setReferenceNo(String referenceNo) {
this.referenceNo = referenceNo;
}
public String getRefundAmount() {
return refundAmount;
}
public void setRefundAmount(String refundAmount) {
this.refundAmount = refundAmount;
}
public String getOriginalAmount() {
return originalAmount;
}
public void setOriginalAmount(String originalAmount) {
this.originalAmount = originalAmount;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}

View File

@ -1,221 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.os.Bundle;
import android.text.InputFilter;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmm.kbz.ui.kpay.KPayViewModel;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.util.DecimalDigitsInputFilter;
import com.utsmm.kbz.util.TransactionUtil;
public class QRRefundDetailFragment extends DataBindingFragment {
private SharedViewModel sharedViewModel;
private KPayViewModel kPayViewModel;
private int routeId;
private TradeData tradeData;
private PayDetail payDetail;
// UI Elements
private RadioGroup radioGroupRefundType;
private RadioButton radioOriginal, radioPartial;
private EditText etReferenceNo, etOriginalAmount, etRefundAmount, etRefundReason;
private LinearLayout originalAmountLayout, refundAmountLayout;
private boolean isPartialRefund = false;
private static final String TAG = com.utsmm.kbz.ui.kpay.QRRefundFragment.class.getSimpleName();
private static final int hostId = Constants.NAV_HOST_ID;
private static final int currentId = R.id.qrRefundDetail;
@Override
protected void initViewModel() {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
kPayViewModel = getFragmentScopeViewModel(KPayViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_qr_refund_detail, BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.kPayViewModel, kPayViewModel)
.addBindingParam(BR.click, new ClickEvent());
}
@Override
protected int currentId() {
return currentId;
}
@Override
protected int hostId() {
return hostId;
}
@Override
protected int routeId() {
return routeId;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if(getArguments() != null){
payDetail = (PayDetail) getArguments().getSerializable("payDetail");
}
}
@Override
public void onResume() {
super.onResume();
setToolBarTitleWithBackIcon("QR Refund");
kPayViewModel.invalidAmountMsg.setValue("");
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initViews();
initData();
setupRadioGroupListener();
}
private void initViews() {
radioGroupRefundType = mBinding.getRoot().findViewById(R.id.radio_group_refund_type);
radioOriginal = mBinding.getRoot().findViewById(R.id.radio_original);
radioPartial = mBinding.getRoot().findViewById(R.id.radio_partial);
etReferenceNo = mBinding.getRoot().findViewById(R.id.et_reference_no);
etOriginalAmount = mBinding.getRoot().findViewById(R.id.et_original_amount);
etRefundAmount = mBinding.getRoot().findViewById(R.id.et_refund_amount);
etRefundReason = mBinding.getRoot().findViewById(R.id.et_refund_reason);
originalAmountLayout = mBinding.getRoot().findViewById(R.id.original_amount_layout);
refundAmountLayout = mBinding.getRoot().findViewById(R.id.refund_amount_layout);
// Set input filters for amount fields
etOriginalAmount.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(11, 2)});
etRefundAmount.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(11, 2)});
}
private void initData() {
payDetail = TransactionUtil.getInstance().initWalletTransaction(TransactionsType.MMQR_REFUND);
payDetail.setInvoiceNo(SystemParamsOperation.getInstance().getIncrementInvoiceNum());
if(getArguments() != null){
PayDetail passData = (PayDetail) getArguments().getSerializable("payDetail");
if(passData != null && passData.getReferNo() != null){
etReferenceNo.setText(passData.getReferNo());
etReferenceNo.setEnabled(false);
}
}
}
private void setupRadioGroupListener() {
radioGroupRefundType.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.radio_partial) {
// Show both amount fields for partial refund
isPartialRefund = true;
originalAmountLayout.setVisibility(View.VISIBLE);
refundAmountLayout.setVisibility(View.VISIBLE);
} else {
// Hide amount fields for original refund
isPartialRefund = false;
originalAmountLayout.setVisibility(View.GONE);
refundAmountLayout.setVisibility(View.GONE);
}
});
}
public class ClickEvent {
public void onCancel() {
safePopBackStack();
}
public void onConfirm() {
kPayViewModel.invalidAmountMsg.setValue("");
String referenceNo = etReferenceNo.getText().toString().trim();
String refundReason = etRefundReason.getText().toString().trim();
// Validate reference number
if (referenceNo.isEmpty()) {
kPayViewModel.invalidAmountMsg.setValue("Enter reference number");
return;
}
if (isPartialRefund) {
// Partial refund validation
String originalAmountStr = etOriginalAmount.getText().toString().trim();
String refundAmountStr = etRefundAmount.getText().toString().trim();
if (originalAmountStr.isEmpty()) {
kPayViewModel.invalidAmountMsg.setValue("Enter original amount");
return;
}
if (refundAmountStr.isEmpty()) {
kPayViewModel.invalidAmountMsg.setValue("Enter refund amount");
return;
}
double originalAmount = Double.parseDouble(originalAmountStr);
double refundAmount = Double.parseDouble(refundAmountStr);
if (originalAmount <= 0) {
kPayViewModel.invalidAmountMsg.setValue("Enter valid original amount");
return;
}
if (refundAmount <= 0) {
kPayViewModel.invalidAmountMsg.setValue("Enter valid refund amount");
return;
}
if (refundAmount > originalAmount) {
kPayViewModel.invalidAmountMsg.setValue("Refund amount cannot exceed original amount");
return;
}
QRRefund qrRefund = new QRRefund(referenceNo, refundAmountStr, originalAmountStr, refundReason);
kPayViewModel.setQrRefund(qrRefund);
} else {
QRRefund qrRefund = new QRRefund(referenceNo, "0", etOriginalAmount.getText().toString().trim(), refundReason);
kPayViewModel.setQrRefund(qrRefund);
}
sharedViewModel.transactionsType.setValue(TransactionsType.MMQR_REFUND);
kPayViewModel.setPayDetail(payDetail);
routeId = R.id.action_qrRefundDetail_inputPasswordFragment;
safeNavigateToRouteId();
}
}
}

View File

@ -1,142 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.kpay.KPayViewModel;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.ArrayList;
import java.util.List;
public class QRRefundFragment extends DataBindingFragment {
private static final int hostId = Constants.NAV_HOST_ID;
private int routeId;
private static final int currentId = R.id.qrRefundList;
private QRPayViewModel qrPayViewModel;
private SharedViewModel sharedViewModel;
private QRRefundViewAdapter adapter;
private LinearLayout emptyStateView;
@Override
protected int currentId() {
return currentId;
}
@Override
protected int hostId() {return hostId;}
@Override
protected int routeId() {return routeId;}
@Override
protected void initViewModel() {
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
qrPayViewModel = new ViewModelProvider(requireActivity()).get(QRPayViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
adapter = new QRRefundViewAdapter(this::onRefundItemClicked);
return new DataBindingConfig(R.layout.fragment_qr_refund, BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.adapter, adapter)
.addBindingParam(BR.click, new ClickEvent());
}
@Override
public void onResume(){
super.onResume();
setToolBarTitleWithBackIcon("QR Refund");
}
@Override
public void onCreate(@Nullable Bundle savedInstance){
super.onCreate(savedInstance);
adapter = new QRRefundViewAdapter(this::onRefundItemClicked);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
RecyclerView recyclerView = view.findViewById(R.id.qrRefundHistory);
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
recyclerView.setAdapter(adapter);
emptyStateView = view.findViewById(R.id.emptyStateSectionRefund);
observeData();
}
private void observeData(){
qrPayViewModel.getRefundableQrHistory().observe(getViewLifecycleOwner(), this::updateList);
}
private void updateList(List<PayDetail> list){
if (adapter == null) {
return;
}
if(list == null || list.isEmpty()){
emptyStateView.setVisibility(View.VISIBLE);
getView().findViewById(R.id.qrRefundHistory).setVisibility(View.GONE);
}else{
emptyStateView.setVisibility(View.GONE);
getView().findViewById(R.id.qrRefundHistory).setVisibility(View.VISIBLE);
adapter.setData(list);
}
}
public class ClickEvent {
public void onCancel(){
safeNavigateToRouteId();
}
public void onSearch(){
searchById();
}
}
private void onRefundItemClicked(PayDetail payDetail) {
Bundle bundle = new Bundle();
bundle.putSerializable("payDetail", payDetail);
routeId = R.id.action_qrRefundList_to_qrRefundDetail;
NavHostFragment.findNavController(this).navigate(routeId, bundle);
}
private void searchById(){
EditText editText = getView().findViewById(R.id.rnn_trace_id);
String keyword = editText.getText().toString().trim();
if(keyword.isEmpty()){
updateList(qrPayViewModel.getRefundableQrHistory().getValue());
return;
}
List<PayDetail> originalList = qrPayViewModel.getRefundableQrHistory().getValue();
if(originalList == null) return;
List<PayDetail> filteredList = new ArrayList<>();
for(PayDetail item: originalList){
if(item.getReferNo() != null && item.getReferNo().contains(keyword)){
filteredList.add(item);
}
}
updateList(filteredList);
}
}

View File

@ -1,215 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.config.Constants;
import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
import com.utsmm.kbz.ui.kpay.KPayViewModel;
import com.utsmm.kbz.ui.kpay.QRRefundFragment;
import com.utsmm.kbz.util.TransactionUtil;
import com.utsmm.kbz.util.ecr.CoreUtils;
import com.utsmyanmar.baselib.fragment.DataBindingFragment;
import com.utsmyanmar.baselib.network.model.KPayRefund;
import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.system.SystemDateTime;
import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.POSUtil;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class QRRefundProcessFragment extends DataBindingFragment {
private static final String TAG = QRRefundProcessFragment.class.getSimpleName();
private SharedViewModel sharedViewModel;
private KPayViewModel kPayViewModel;
private PayDetail payDetail;
private QRRefund qrRefund;
private static final int hostId = Constants.NAV_HOST_ID;
private int routeId;
private static final int currentId = R.id.QRRefundProcessFragment;
CompositeDisposable retrieveUpdateDisposable = new CompositeDisposable();
CompositeDisposable refundDisposable = new CompositeDisposable();
@Override
protected void initViewModel() {
sharedViewModel = getFragmentScopeViewModel(SharedViewModel.class);
kPayViewModel = getFragmentScopeViewModel(KPayViewModel.class);
}
@Override
protected DataBindingConfig getDataBindingConfig() {
return new DataBindingConfig(R.layout.fragment_qr_refund_process, BR.sharedViewModel, sharedViewModel)
.addBindingParam(BR.kPayViewModel, kPayViewModel);
}
@Override
public void onDestroyView() {
super.onDestroyView();
retrieveUpdateDisposable.dispose();
refundDisposable.dispose();
}
@Override
protected int currentId() {
return currentId;
}
@Override
protected int hostId() {
return hostId;
}
@Override
protected int routeId() {
return routeId;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initData();
processKPayRefund(qrRefund.getReferenceNo(), qrRefund.getRefundAmount(), qrRefund.getOriginalAmount(), qrRefund.getReason());
}
private void initData() {
payDetail = kPayViewModel.getPayDetail();
qrRefund = kPayViewModel.getQrRefund();
}
private void processKPayRefund(String referenceNo, String refundAmount, String originalAmount, String reason) {
String merchantId = TransactionUtil.getInstance().getQRMerchantId();
// Generate unique refund request ID
String refundRequestId = referenceNo + "R";
// Create KPay refund request
KPayRefund.RefundRequest refundRequest = kPayViewModel.createRefundRequest(
refundRequestId,
referenceNo,
merchantId,
refundAmount,
reason != null ? reason : "Refund request"
);
Disposable refundDi = kPayViewModel.kPayRefund(refundRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> {
handleRefundResponse(response, referenceNo);
},
throwable -> {
LogUtil.e(TAG, "Refund error: " + throwable.getMessage());
showDeclineDialog("Refund failed!\nCommunication Error!");
ecrActionCancel("Refund failed");
navigateToMain();
},
() -> LogUtil.d(TAG, "Refund request completed")
);
refundDisposable.add(refundDi);
}
private void handleRefundResponse(KPayRefund.RefundResponse response, String referenceNo) {
if (response != null && response.getResponse() != null && "REFUND_SUCCESS".equalsIgnoreCase(response.getResponse().getRefundStatus())) {
LogUtil.d(TAG, "Refund successful!");
String refundAmount = response.getResponse().getRefundAmount();
String dateTime = SystemDateTime.getTodayDateFormat() + " " + SystemDateTime.getTodayTimeFormat();
payDetail.setAmount(refundAmount == null ? 0 : POSUtil.getInstance().convertAmount(refundAmount));
payDetail.setOriginalTransDate(dateTime);
payDetail.setQrTransStatus(1);
payDetail.setQrReferNo(referenceNo);
payDetail.setReferNo(referenceNo);
payDetail.setIsCanceled(true);
retrievedUpdatePayDetail(referenceNo);
} else {
LogUtil.d(TAG, "Refund failed!");
payDetail.setQrTransStatus(-1);
payDetail.setQrReferNo(referenceNo);
payDetail.setReferNo(referenceNo);
String errorMsg = "Refund failed";
if (response != null && response.getResponse() != null && response.getResponse().getMsg() != null) {
errorMsg = response.getResponse().getMsg();
}
payDetail.setTradeResultDes(errorMsg);
sharedViewModel.payDetail.setValue(payDetail);
navigateToNext();
}
}
private void retrievedUpdatePayDetail(String refNum) {
LogUtil.d(TAG, "Trying to update Database!");
retrieveUpdateDisposable.add(kPayViewModel.searchPayByRefNum(refNum)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(oldPay -> {
LogUtil.d(TAG, "Inside the subscribe!");
if (oldPay != null) {
oldPay.setIsCanceled(true);
payDetail.setQrTransId(oldPay.getQrTransId());
payDetail.setCustomerMobile(oldPay.getCustomerMobile());
sharedViewModel.updatePayDetail(oldPay);
}
updateData();
navigateToNext();
},
onError -> {
LogUtil.d(TAG, "On error Unable to retrieve PayDetail");
updateData();
navigateToNext();
},
() -> {
LogUtil.d(TAG, "No data found! navigating to Result Page!");
updateData();
navigateToNext();
}
));
}
private void updateData() {
kPayViewModel.insertPayDetail(payDetail);
sharedViewModel.payDetail.postValue(payDetail);
}
private void navigateToNext() {
routeId = R.id.action_QRRefundProcessFragment_to_transactionResultFragment;
safeNavigateToRouteId();
}
private void navigateToMain() {
routeId = R.id.action_QRRefundProcessFragment_to_nav_main;
safeNavigateToRouteId();
}
private void ecrActionCancel(String msg) {
if (sharedViewModel.isEcr.getValue() != null) {
if (sharedViewModel.isEcr.getValue()) {
sharedViewModel.isEcr.postValue(false);
CoreUtils.getInstance(sharedViewModel).responseRejectMsg(msg);
sharedViewModel.isEcrFinished.postValue(true);
}
}
}
}

View File

@ -1,84 +0,0 @@
package com.utsmm.kbz.ui.qr_pay;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.utsmm.kbz.BR;
import com.utsmm.kbz.R;
import com.utsmm.kbz.databinding.ItemQrRefundBinding;
import com.utsmm.kbz.ui.adapters.QRPayAdapter;
import com.utsmyanmar.paylibs.model.PayDetail;
import java.util.ArrayList;
import java.util.List;
public class QRRefundViewAdapter extends RecyclerView.Adapter<QRRefundViewAdapter.ViewHolder> {
private List<PayDetail> payDetailList = new ArrayList<>();
private final OnRefundItemClick listener;
public interface OnRefundItemClick {
void onClick(PayDetail payDetail);
}
public QRRefundViewAdapter(OnRefundItemClick listener){
this.listener = listener;
}
// public QRRefundViewAdapter(List<PayDetail> payDetailList, OnRefundItemClick listener){
// this.payDetailList = payDetailList;
// this.listener = listener;
// }
public void setData(List<PayDetail> data){
this.payDetailList = data != null ? data : new ArrayList<>();
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemQrRefundBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_qr_refund,
parent,
false
);
return new ViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
PayDetail payDetail = payDetailList.get(position);
holder.bind(payDetail, listener);
}
@Override
public int getItemCount() {
return payDetailList == null ? 0 : payDetailList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
private final ItemQrRefundBinding binding;
public ViewHolder(ItemQrRefundBinding binding){
super(binding.getRoot());
this.binding = binding;
}
public void bind(PayDetail payDetail, OnRefundItemClick listener){
binding.setVariable(BR.payDetail, payDetail);
binding.executePendingBindings();
binding.getRoot().setOnClickListener( v -> {
if(listener != null) listener.onClick(payDetail);
});
}
}
}

View File

@ -52,25 +52,14 @@ public class MockData {
// .cardHolderName("KBZ Debit")
// .iccData("9503051034047056=30021015930000000000")
// .build();
// mockCardData = new MockCardData.Builder()
// .cardNo("9505050161133125")
// .expDate("0127")
// .cardScheme("MPU")
// .cardHolderName("KBZ Credit")
// .iccData("9505050161133125=27011017250000000000")
// .build();
mockCardData = new MockCardData.Builder()
.cardNo("9503712156912514")
.expDate("1229")
.cardNo("9505050161133125")
.expDate("0127")
.cardScheme("MPU")
.cardHolderName("Htin Kyaw Win")
.iccData("9503712156912514=29121010000000000000")
.cardHolderName("KBZ Credit")
.iccData("9505050161133125=27011017250000000000")
.build();
// mockCardData = new MockCardData.Builder()
// .cardNo("9503742975107251")
// .expDate("0629")

View File

@ -171,7 +171,7 @@ public class TMSSetupsImpl implements TMSSetups{
for (SiriusHost siriusHost: siriusHosts) {
if( siriusHost.getName().toLowerCase().contains("mmqr") || siriusHost.getName().toLowerCase().contains("kbzpay") || siriusHost.getName().toLowerCase().contains("mmqr") || siriusHost.getName().toLowerCase().contains("qr")) {
if( siriusHost.getName().toLowerCase().contains("mmqr") || siriusHost.getName().toLowerCase().contains("kbzpay") || siriusHost.getDescription().toLowerCase().contains("mmqr") || siriusHost.getDescription().toLowerCase().contains("qr")) {
SystemParamsOperation.getInstance().setSecHostName(siriusHost.getName());
SystemParamsOperation.getInstance().setSecHostTerminalId(siriusHost.getTid());
@ -688,7 +688,7 @@ public class TMSSetupsImpl implements TMSSetups{
return value == 1;
} catch (Exception e) {
e.printStackTrace();
return Boolean.parseBoolean(data);
return false;
}
}
}

View File

@ -147,8 +147,7 @@ public class TMSUtil {
siriusRequest.setApplicationVersion(BuildConfig.VERSION_NAME);
siriusRequest.setCurrentNetwork(getNetworkType(context));
siriusRequest.setLastTransaction(lastTransName);
siriusRequest.setLastTranTime(Long.parseLong(lastTransTime));
siriusRequest.setValue("YourValueHere");
siriusRequest.setLastTranTime(lastTransTime);
return siriusRequest;
}

View File

@ -1,22 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="200"
android:viewportHeight="200">
<path
android:fillColor="@color/colorPrimary"
android:strokeColor="@color/colorPrimary"
android:strokeWidth="2"
android:pathData="
M 24 0
H 140
A 60 60 0 0 0 200 60
V 176
Q 200 200 176 200
H 24
Q 0 200 0 176
V 24
Q 0 0 24 0
Z" />
</vector>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="200"
android:viewportHeight="200">
<path
android:fillColor="@color/colorPrimary"
android:strokeColor="@color/colorPrimary"
android:strokeWidth="2"
android:pathData="
M 60 0
H 176
Q 200 0 200 24
V 176
Q 200 200 176 200
H 24
Q 0 200 0 176
V 60
A 60 60 0 0 1 60 0
Z" />
</vector>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="200"
android:viewportHeight="200">
<path
android:fillColor="@color/colorPrimary"
android:strokeColor="@color/colorPrimary"
android:strokeWidth="2"
android:pathData="
M 24 0
H 176
Q 200 0 200 24
V 176
Q 200 200 176 200
H 60
A 60 60 0 0 0 0 140
V 24
Q 0 0 24 0
Z" />
</vector>

View File

@ -1,22 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="200"
android:viewportHeight="200">
<path
android:fillColor="@color/colorPrimary"
android:strokeColor="@color/colorPrimary"
android:strokeWidth="2"
android:pathData="
M 24 0
H 176
Q 200 0 200 24
V 140
A 60 60 0 0 0 140 200
H 24
Q 0 200 0 176
V 24
Q 0 0 24 0
Z" />
</vector>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/colorPrimary"
android:pathData="M7.41,8.59L12,13.17l4.59,-4.58L18,10l-6,6 -6,-6z" />
</vector>

View File

@ -8,285 +8,326 @@
<import type="android.view.View"/>
<import type="com.utsmm.kbz.R"/>
<import type="com.utsmm.kbz.util.layout.LayoutDataUtil"/>
<variable name="shareViewModel" type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel"/>
<variable name="mainViewModel" type="com.utsmm.kbz.MainViewModel"/>
<variable name="click" type="com.utsmm.kbz.MainFragment.ClickEvent"/>
<variable name="carouselAdapter" type="androidx.recyclerview.widget.RecyclerView.Adapter"/>
<variable name="myAdapter" type="com.utsmm.kbz.ui.adapters.MainAdapter"/>
<variable
name="shareViewModel"
type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" />
<variable
name="mainViewModel"
type="com.utsmm.kbz.MainViewModel" />
<variable
name="click"
type="com.utsmm.kbz.MainFragment.ClickEvent" />
<variable
name="carouselAdapter"
type="androidx.recyclerview.widget.RecyclerView.Adapter" />
<variable
name="myAdapter"
type="com.utsmm.kbz.ui.adapters.MainAdapter" />
</data>
<!-- ======== ROOT ======== -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:padding="16dp">
<!-- ====================== BANNER ====================== -->
android:background="@color/colorBackground">
<!-- Banner Section (25% of screen) -->
<androidx.cardview.widget.CardView
android:id="@+id/bannerCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="4dp"
app:cardElevation="6dp"
android:layout_margin="16dp"
app:cardCornerRadius="16dp"
app:cardElevation="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="16:6">
app:layout_constraintHeight_percent="0.25">
<com.denzcoskun.imageslider.ImageSlider
android:id="@+id/image_slider"
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:iss_auto_cycle="true"
app:iss_period="5000"
app:iss_delay="5000"
app:iss_no_dots="true"
app:iss_title_background="@color/transparent" />
android:layout_height="match_parent">
<com.denzcoskun.imageslider.ImageSlider
android:id="@+id/image_slider"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:iss_auto_cycle="true"
app:iss_period="5000"
app:iss_delay="5000"
app:iss_no_dots="true"
app:iss_title_background="@color/transparent" />
<!-- Gradient overlay for better text visibility -->
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/gradient_overlay" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
<!-- ====================== GRID AREA ====================== -->
<!-- Main Menu Grid (3+2 layout for 5 functions) -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/menuGrid"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/bannerCard"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_margin="16dp"
app:layout_constraintTop_toBottomOf="@+id/bannerCard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:paddingTop="12dp">
app:layout_constraintBottom_toBottomOf="parent">
<!-- ===== FULL WIDTH SALE BUTTON ===== -->
<!-- First Row - 3 cards -->
<!-- Sale Card -->
<androidx.cardview.widget.CardView
android:id="@+id/cardMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardCornerRadius="18dp"
app:cardElevation="4dp"
android:layout_margin="6dp"
android:foreground="?attr/selectableItemBackground"
android:layout_marginEnd="4dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickCard()}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="1:0.4">
app:layout_constraintEnd_toStartOf="@+id/signOnMenuCard"
app:layout_constraintBottom_toTopOf="@+id/qrPayMenuCard"
app:layout_constraintWidth_percent="0.32"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="20dp"
android:background="@color/white">
android:background="@drawable/primary_card_bg"
android:padding="12dp">
<ImageView
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_sale"
app:tint="@color/colorPrimary"
android:layout_marginBottom="6dp" />
android:layout_marginBottom="6dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_sale"
android:textColor="@color/colorPrimary"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- ===== ROW 1 ===== -->
<!-- Settlement -->
<androidx.cardview.widget.CardView
android:id="@+id/settlementMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardCornerRadius="18dp"
app:cardElevation="4dp"
android:layout_margin="6dp"
android:foreground="?attr/selectableItemBackground"
android:onClick="@{() -> click.onClickSettlement()}"
app:disableBtn="@{mainViewModel.settlementStatus}"
app:layout_constraintTop_toBottomOf="@id/cardMenuCard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/signOnMenuCard"
app:layout_constraintDimensionRatio="1:0.8">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center"
android:orientation="vertical"
android:padding="18dp">
<ImageView
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_marginBottom="6dp"
android:src="@drawable/ic_settlement"
app:tint="@color/colorPrimary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_settlement"
android:textColor="@color/colorPrimary"
android:textSize="14sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Sign On -->
<!-- Sign On Card -->
<androidx.cardview.widget.CardView
android:id="@+id/signOnMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardCornerRadius="18dp"
app:cardElevation="4dp"
android:layout_margin="6dp"
android:foreground="?attr/selectableItemBackground"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickSignOn()}"
app:layout_constraintTop_toBottomOf="@id/cardMenuCard"
app:layout_constraintStart_toEndOf="@id/settlementMenuCard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="1:0.8">
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/cardMenuCard"
app:layout_constraintEnd_toStartOf="@+id/settlementMenuCard"
app:layout_constraintBottom_toTopOf="@+id/otherFeaturesCard"
app:layout_constraintWidth_percent="0.32"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center"
android:orientation="vertical"
android:padding="18dp">
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="12dp">
<ImageView
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_signon"
app:tint="@color/colorPrimary"
android:layout_marginBottom="6dp" />
android:layout_marginBottom="6dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_sign_on"
android:textColor="@color/colorPrimary"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- ===== ROW 2 ===== -->
<!-- Transactions -->
<!-- Settlement Card -->
<androidx.cardview.widget.CardView
android:id="@+id/otherFeaturesCard"
android:id="@+id/settlementMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardCornerRadius="18dp"
app:cardElevation="4dp"
android:layout_margin="6dp"
android:foreground="?attr/selectableItemBackground"
android:onClick="@{() -> click.onClickTrans()}"
app:layout_constraintTop_toBottomOf="@id/settlementMenuCard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/qrPayMenuCard"
app:layout_constraintDimensionRatio="1:0.8">
android:layout_marginStart="4dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickSettlement()}"
app:disableBtn="@{mainViewModel.settlementStatus}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/signOnMenuCard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@+id/otherFeaturesCard"
app:layout_constraintWidth_percent="0.32"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/white"
android:orientation="vertical"
android:padding="18dp">
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="12dp">
<ImageView
android:layout_width="46dp"
android:layout_height="46dp"
android:src="@drawable/ic_other_features"
app:tint="@color/colorPrimary"
android:layout_marginBottom="6dp" />
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_settlement"
android:layout_marginBottom="6dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_transactions"
android:textColor="@color/colorPrimary"
android:text="@string/menu_settlement"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- QR Pay -->
<!-- Second Row - 2 cards centered -->
<!-- QR Pay Card -->
<androidx.cardview.widget.CardView
android:id="@+id/qrPayMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardCornerRadius="18dp"
app:cardElevation="4dp"
android:layout_margin="6dp"
android:foreground="?attr/selectableItemBackground"
android:onClick="@{() -> click.onClickQR()}"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickQRPay()}"
app:disableBtn="@{mainViewModel.kPayStatus}"
app:layout_constraintTop_toBottomOf="@id/signOnMenuCard"
app:layout_constraintStart_toEndOf="@id/otherFeaturesCard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="1:0.8">
app:layout_constraintTop_toBottomOf="@+id/cardMenuCard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/otherFeaturesCard"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintWidth_percent="0.48"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center"
android:orientation="vertical"
android:padding="18dp">
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="16dp">
<ImageView
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_pay"
app:tint="@color/colorPrimary"
android:layout_marginBottom="6dp" />
android:layout_marginBottom="8dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_qrpay"
android:textColor="@color/colorPrimary"
android:textSize="14sp"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Transactions Card -->
<androidx.cardview.widget.CardView
android:id="@+id/otherFeaturesCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickTrans()}"
app:layout_constraintTop_toBottomOf="@+id/signOnMenuCard"
app:layout_constraintStart_toEndOf="@+id/qrPayMenuCard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintWidth_percent="0.48"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="16dp">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_other_features"
android:layout_marginBottom="8dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_transactions"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
</layout>

View File

@ -1,333 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.utsmm.kbz.util.ecr.ECRConnectionStatus"/>
<import type="android.view.View"/>
<import type="com.utsmm.kbz.R"/>
<import type="com.utsmm.kbz.util.layout.LayoutDataUtil"/>
<variable
name="shareViewModel"
type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" />
<variable
name="mainViewModel"
type="com.utsmm.kbz.MainViewModel" />
<variable
name="click"
type="com.utsmm.kbz.MainFragment.ClickEvent" />
<variable
name="carouselAdapter"
type="androidx.recyclerview.widget.RecyclerView.Adapter" />
<variable
name="myAdapter"
type="com.utsmm.kbz.ui.adapters.MainAdapter" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBackground">
<!-- Banner Section (25% of screen) -->
<androidx.cardview.widget.CardView
android:id="@+id/bannerCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="16dp"
app:cardCornerRadius="16dp"
app:cardElevation="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.25">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.denzcoskun.imageslider.ImageSlider
android:id="@+id/image_slider"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:iss_auto_cycle="true"
app:iss_period="5000"
app:iss_delay="5000"
app:iss_no_dots="true"
app:iss_title_background="@color/transparent" />
<!-- Gradient overlay for better text visibility -->
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
<!-- Main Menu Grid (3+2 layout for 5 functions) -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="16dp"
app:layout_constraintTop_toBottomOf="@+id/bannerCard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<!-- First Row - 3 cards -->
<!-- Sale Card -->
<androidx.cardview.widget.CardView
android:id="@+id/cardMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickCard()}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/signOnMenuCard"
app:layout_constraintBottom_toTopOf="@+id/qrPayMenuCard"
app:layout_constraintWidth_percent="0.32"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="12dp">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_sale"
android:layout_marginBottom="6dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_sale"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Sign On Card -->
<androidx.cardview.widget.CardView
android:id="@+id/signOnMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickSignOn()}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/cardMenuCard"
app:layout_constraintEnd_toStartOf="@+id/settlementMenuCard"
app:layout_constraintBottom_toTopOf="@+id/otherFeaturesCard"
app:layout_constraintWidth_percent="0.32"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="12dp">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_signon"
android:layout_marginBottom="6dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_sign_on"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Settlement Card -->
<androidx.cardview.widget.CardView
android:id="@+id/settlementMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="4dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickSettlement()}"
app:disableBtn="@{mainViewModel.settlementStatus}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/signOnMenuCard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@+id/otherFeaturesCard"
app:layout_constraintWidth_percent="0.32"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="12dp">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_settlement"
android:layout_marginBottom="6dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_settlement"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Second Row - 2 cards centered -->
<!-- QR Pay Card -->
<androidx.cardview.widget.CardView
android:id="@+id/qrPayMenuCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickQR()}"
app:disableBtn="@{mainViewModel.kPayStatus}"
app:layout_constraintTop_toBottomOf="@+id/cardMenuCard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/otherFeaturesCard"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintWidth_percent="0.48"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="16dp">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_pay"
android:layout_marginBottom="8dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_qrpay"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Transactions Card -->
<androidx.cardview.widget.CardView
android:id="@+id/otherFeaturesCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> click.onClickTrans()}"
app:layout_constraintTop_toBottomOf="@+id/signOnMenuCard"
app:layout_constraintStart_toEndOf="@+id/qrPayMenuCard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintWidth_percent="0.48"
app:layout_constraintHeight_percent="0.48">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="16dp">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_other_features"
android:layout_marginBottom="8dp"
app:tint="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_transactions"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="@font/rubik_medium"
android:textAlignment="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -41,7 +41,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:spanCount="3"
app:spanCount="2"
bind:setAdapter="@{adapter}"
tools:itemCount="6"
tools:listitem="@layout/item_view_dashboard" />

View File

@ -32,21 +32,21 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
android:paddingTop="14dp"
android:padding="16dp"
android:paddingTop="24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!-- Trace Number Icon -->
<ImageView
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="8dp"
android:layout_marginBottom="12dp"
android:src="@drawable/ic_txn_history"
app:tint="@color/colorPrimary"
android:alpha="0.88"
android:padding="6dp"
android:alpha="0.9"
android:padding="8dp"
android:background="@drawable/bg_oval" />
<!-- Compact Title -->
@ -56,10 +56,10 @@
android:text="@string/enter_trace_text"
android:textAlignment="center"
android:textColor="@color/colorPrimary"
android:textSize="17sp"
android:textSize="22sp"
android:textStyle="bold"
android:fontFamily="sans-serif-medium"
android:layout_marginBottom="2dp" />
android:layout_marginBottom="4dp" />
<!-- Compact Subtitle -->
<TextView
@ -68,18 +68,18 @@
android:text="Enter the transaction trace number"
android:textAlignment="center"
android:textColor="@color/colorPrimary"
android:textSize="12sp"
android:alpha="0.7"
android:textSize="14sp"
android:alpha="0.75"
android:fontFamily="sans-serif"
android:layout_marginBottom="10dp" />
android:layout_marginBottom="16dp" />
<!-- Compact Trace Number Display Card -->
<androidx.cardview.widget.CardView
android:id="@+id/traceCard"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginHorizontal="4dp"
app:cardCornerRadius="12dp"
android:layout_height="70dp"
android:layout_marginHorizontal="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
app:cardBackgroundColor="@color/white">
@ -87,11 +87,11 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="1dp"
android:layout_margin="2dp"
android:background="@drawable/bg_edittext_primary_border"
android:orientation="horizontal"
android:gravity="center"
android:padding="8dp">
android:padding="16dp">
<!-- Trace number display -->
<TextView
@ -102,22 +102,22 @@
android:gravity="center"
android:text="@{inputTraceViewModel.invoiceNo}"
android:textColor="@color/colorPrimary"
android:textSize="20sp"
android:textSize="28sp"
android:textStyle="bold"
android:letterSpacing="0.07"
android:letterSpacing="0.1"
android:fontFamily="monospace"
android:hint="000000"
android:textColorHint="@color/colorPrimary"
android:alpha="0.5"
android:alpha="0.6"
tools:text="123456" />
<!-- Transaction indicator -->
<View
android:layout_width="5dp"
android:layout_height="5dp"
android:layout_width="6dp"
android:layout_height="6dp"
android:background="@drawable/bg_oval"
android:backgroundTint="@color/colorPrimary"
android:alpha="0.5" />
android:alpha="0.6" />
</LinearLayout>
@ -125,14 +125,14 @@
</LinearLayout>
<!-- Number Keyboard - guaranteed space, more compact -->
<!-- Number Keyboard - guaranteed space -->
<com.utsmyanmar.baselib.ui.NumberKeyboard
android:id="@+id/passwordKeyboard"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginHorizontal="8dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:KeyClickCallback="@{inputTraceViewModel.onKeyClick}"
app:layout_constraintBottom_toTopOf="@+id/actionButtonsContainer"
app:layout_constraintEnd_toEndOf="parent"
@ -146,8 +146,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp"
android:paddingBottom="12dp"
android:padding="16dp"
android:paddingBottom="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent">
@ -155,34 +155,34 @@
<Button
android:id="@+id/btnCancel"
android:layout_width="0dp"
android:layout_height="42dp"
android:layout_height="52dp"
android:layout_weight="1"
android:layout_marginEnd="6dp"
android:layout_marginEnd="8dp"
android:text="@string/layout_cancel"
android:textColor="@color/colorPrimary"
android:textSize="12sp"
android:textSize="15sp"
android:textStyle="bold"
android:background="@drawable/bg_rounded_btn_cancel_cv"
android:fontFamily="sans-serif-medium"
android:onClick="@{()->click.onCancel()}"
android:elevation="1dp"
android:elevation="2dp"
android:textAllCaps="false" />
<!-- Confirm Button -->
<Button
android:id="@+id/btnConfirm"
android:layout_width="0dp"
android:layout_height="42dp"
android:layout_height="52dp"
android:layout_weight="1"
android:layout_marginStart="6dp"
android:layout_marginStart="8dp"
android:text="@string/layout_confirm"
android:textColor="@color/white"
android:textSize="12sp"
android:textSize="15sp"
android:textStyle="bold"
android:background="@drawable/bg_rounded_btn_cv"
android:fontFamily="sans-serif-medium"
android:onClick="@{()->click.onConfirm()}"
android:elevation="3dp"
android:elevation="8dp"
android:textAllCaps="false" />
</LinearLayout>

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="vm"
type="com.utsmm.kbz.ui.qr_pay.QRHistoryViewModel" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/qrRvHistory"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- No Data Message -->
<!-- <TextView-->
<!-- android:id="@+id/tvNoData"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:gravity="center"-->
<!-- android:text="No history available"-->
<!-- android:textSize="18sp"-->
<!-- android:padding="16dp"-->
<!-- android:visibility="@{vm.refundList.size() == 0 ? View.VISIBLE : View.GONE}" />-->
</FrameLayout>
</layout>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:bind="http://schemas.android.com/tools">
<data>
<variable
name="adapter"
type="androidx.recyclerview.widget.RecyclerView.Adapter" />
<variable
name="sharedViewModel"
type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBackground">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewFeatures"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:clipToPadding="false"
android:nestedScrollingEnabled="false"
android:background="@color/transparent"
android:padding="16dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:spanCount="3"
bind:setAdapter="@{adapter}"
tools:itemCount="3"
tools:listitem="@layout/item_qr_pay_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -1,172 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="sharedViewModel"
type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" />
<variable
name="adapter"
type="androidx.recyclerview.widget.RecyclerView.Adapter" />
<variable
name="manageViewModel"
type="com.utsmm.kbz.ui.management.ManagementViewModel" />
<variable
name="click"
type="com.utsmm.kbz.ui.qr_pay.QRRefundFragment.ClickEvent" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<!-- SEARCH SECTION -->
<LinearLayout
android:id="@+id/refundSearchSection"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:gravity="center_vertical"
android:visibility="@{manageViewModel.reprintLayoutTopVisibility}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<!-- Search Card -->
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginEnd="12dp"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
app:cardBackgroundColor="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
android:background="@drawable/bg_edittext_primary_border"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_txn_history"
app:tint="@color/colorPrimary"
android:alpha="0.6"/>
<EditText
android:id="@+id/rnn_trace_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="@string/txt_search_rrn_trace"
android:text="@={manageViewModel.txtRRNTrace}"
android:textColor="@color/colorPrimary"
android:textColorHint="@color/colorPrimary"
android:alpha="0.9"
android:textSize="14sp"
android:inputType="number"
android:singleLine="true"
android:imeOptions="actionSearch" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- SEARCH BUTTON -->
<androidx.cardview.widget.CardView
android:id="@+id/btnSearch"
android:onClick="@{() -> click.onSearch()}"
android:layout_width="80dp"
android:layout_height="52dp"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/colorPrimary"
app:cardCornerRadius="8dp"
app:cardElevation="3dp"
android:foreground="?android:attr/selectableItemBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Search"
android:textSize="14sp"
android:textColor="@color/white"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<!-- RECYCLER VIEW -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/qrRefundHistory"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="4dp"
app:adapter="@{adapter}"
app:layout_constraintTop_toBottomOf="@id/refundSearchSection"
app:layout_constraintBottom_toBottomOf="parent"
tools:listitem="@layout/item_qr_refund" />
<!-- Empty State Section -->
<LinearLayout
android:id="@+id/emptyStateSectionRefund"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:visibility="@{manageViewModel.reprintLayoutBtmVisibility}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lav_no_trans"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginBottom="24dp"
app:lottie_autoPlay="true"
app:lottie_fileName="lottie_no_trans.json"
app:lottie_loop="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_history"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/colorPrimary"
android:layout_marginBottom="8dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No transactions found for the selected criteria"
android:textSize="14sp"
android:textColor="@color/colorPrimary"
android:alpha="0.7"
android:paddingHorizontal="32dp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -1,349 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="sharedViewModel"
type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" />
<variable
name="kPayViewModel"
type="com.utsmm.kbz.ui.kpay.KPayViewModel" />
<variable
name="click"
type="com.utsmm.kbz.ui.qr_pay.QRRefundDetailFragment.ClickEvent" />
</data>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<!-- Refund Type Selection -->
<LinearLayout
android:id="@+id/refund_type_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Refund Type"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/radio_group_refund_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radio_original"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="Original Amount"
android:textSize="16sp" />
<RadioButton
android:id="@+id/radio_partial"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Partial Amount"
android:textSize="16sp" />
</RadioGroup>
</LinearLayout>
<!-- Reference Number Input -->
<LinearLayout
android:id="@+id/reference_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/refund_type_layout">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Reference Number *"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<EditText
android:id="@+id/et_reference_no"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="Enter reference number"
android:inputType="text"
android:maxLength="20"
android:padding="16dp"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="18sp"
tools:text="NEX000011" />
</androidx.cardview.widget.CardView>
</LinearLayout>
<!-- Original Amount Input (for partial refunds) -->
<LinearLayout
android:id="@+id/original_amount_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/reference_layout">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Original Amount *"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_amount_title"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mmk"
android:textSize="18sp" />
</LinearLayout>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="4dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<EditText
android:id="@+id/et_original_amount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="0.00"
android:inputType="numberDecimal"
android:padding="16dp"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
tools:text="1000.00" />
</androidx.cardview.widget.CardView>
</LinearLayout>
</LinearLayout>
<!-- Refund Amount Input (for partial refunds) -->
<LinearLayout
android:id="@+id/refund_amount_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/original_amount_layout">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Refund Amount *"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_amount_title"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mmk"
android:textSize="18sp" />
</LinearLayout>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="4dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<EditText
android:id="@+id/et_refund_amount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="0.00"
android:inputType="numberDecimal"
android:padding="16dp"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
tools:text="400.00" />
</androidx.cardview.widget.CardView>
</LinearLayout>
</LinearLayout>
<!-- Refund Reason Input -->
<LinearLayout
android:id="@+id/refund_reason_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/refund_amount_layout">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Refund Reason"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<EditText
android:id="@+id/et_refund_reason"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="Enter refund reason (optional)"
android:inputType="textMultiLine"
android:lines="3"
android:padding="16dp"
android:textColor="@color/black"
android:textSize="16sp"
tools:text="Customer requested refund" />
</androidx.cardview.widget.CardView>
</LinearLayout>
<!-- Error Message -->
<TextView
android:id="@+id/error_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@{kPayViewModel.invalidAmountMsg}"
android:textAlignment="center"
android:textColor="@color/red"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/refund_reason_layout"
tools:text="Invalid amount entered" />
<!-- Action Buttons -->
<LinearLayout
android:id="@+id/button_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/error_message">
<Button
android:id="@+id/btn_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_weight="1"
android:background="@drawable/bg_rounded_btn_cancel_cv"
android:onClick="@{()->click.onCancel()}"
android:text="@string/layout_cancel"
android:textColor="@color/colorPrimary"
android:textSize="16sp" />
<Button
android:id="@+id/btn_confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_weight="1"
android:background="@drawable/bg_rounded_btn_cv"
android:onClick="@{()->click.onConfirm()}"
android:text="Process Refund"
android:textColor="@color/white"
android:textSize="16sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</layout>

View File

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="sharedViewModel"
type="com.utsmm.kbz.ui.core_viewmodel.SharedViewModel" />
<variable
name="kPayViewModel"
type="com.utsmm.kbz.ui.kpay.KPayViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/rubik_regular"
android:text="@string/txt_processing_refund"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="@+id/lav_thumbUp"
app:layout_constraintStart_toStartOf="@+id/lav_thumbUp"
app:layout_constraintTop_toBottomOf="@+id/lav_thumbUp" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lav_thumbUp"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_margin="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:lottie_autoPlay="true"
app:lottie_fileName="lottie_processing_card.json"
app:lottie_loop="true" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -91,7 +91,7 @@
app:layout_constraintBottom_toTopOf="@+id/actionButtonsContainer">
<!-- Card with border -->
<FrameLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
@ -477,18 +477,13 @@
tools:text="12/12/2024 12:12:12" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>
<ImageView
android:id="@+id/scroll_hint"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="8dp"
android:src="@drawable/ic_down_arrow"
android:alpha="0.6" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Action Buttons Container -->

View File

@ -1,160 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<import type="com.utsmyanmar.paylibs.utils.POSUtil"/>
<variable
name="payDetail"
type="com.utsmyanmar.paylibs.model.PayDetail" />
<variable
name="onItemClick"
type="com.utsmm.kbz.ui.management.ItemClickListener" />
</data>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_marginVertical="6dp"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
app:cardBackgroundColor="@color/colorPrimary"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:onClick="@{() -> onItemClick.onClickCard(payDetail)}">
<!-- Card with border -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:background="@drawable/bg_edittext_primary_border"
android:orientation="horizontal"
android:padding="16dp">
<!-- Transaction Icon -->
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_custom_pos"
app:tint="@color/white"
android:alpha="0.8"
android:layout_marginEnd="12dp"
android:layout_gravity="top" />
<!-- Transaction Details -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<!-- Transaction Type and Amount Row -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp">
<!-- Transaction Type -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{POSUtil.getInstance().getTransName(payDetail)}"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="sans-serif-medium"
tools:text="SALE" />
<!-- Transaction Amount -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{POSUtil.getInstance().checkMinusSign(payDetail.transactionType)+POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.amount) + ` `+POSUtil.getInstance().currencyCodeToText(payDetail.currencyCode)}"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="sans-serif-medium"
tools:text="1,000.00 MMK" />
</LinearLayout>
<!-- Transaction Date -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{POSUtil.getInstance().convertDateFormatByDateString(payDetail.transDate)}"
android:textColor="@color/white"
android:textSize="14sp"
android:alpha="0.8"
android:fontFamily="sans-serif"
android:layout_marginBottom="6dp"
tools:text="2022-11-26" />
<!-- Card Number -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{POSUtil.getInstance().getCardNumMasking(payDetail.cardNo)}"
android:textColor="@color/white"
android:textSize="14sp"
android:alpha="0.8"
android:fontFamily="monospace"
android:layout_marginBottom="8dp"
tools:text="468785******9564" />
<!-- Trace and RRN Row -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!-- Trace Number -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:isTrace="@{payDetail}"
android:textColor="@color/white"
android:textSize="13sp"
android:alpha="0.7"
android:fontFamily="monospace"
tools:text="TRC:000050" />
<!-- RRN -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{`RRN:`+payDetail.referNo}"
android:textColor="@color/white"
android:textSize="13sp"
android:alpha="0.7"
android:fontFamily="monospace"
android:textAlignment="textEnd"
tools:text="RRN:233001786242" />
</LinearLayout>
</LinearLayout>
<!-- Arrow Icon -->
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_right_arrow"
app:tint="@color/white"
android:alpha="0.6"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.utsmm.kbz.R"/>
<import type="com.utsmm.kbz.util.enums.FeaturesType" />
<variable
name="text"
type="String" />
<variable
name="icon"
type="Integer" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
>
<androidx.cardview.widget.CardView
android:id="@+id/btnItem"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardCornerRadius="20dp"
app:cardElevation="6dp"
android:layout_margin="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:background="@color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="1:1"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp">
<ImageView
android:id="@+id/btnIcon"
android:layout_width="38dp"
android:layout_height="38dp"
android:layout_marginBottom="8dp"
app:srcUrl="@{icon}"
app:tint="@color/colorPrimary"
tools:src="@drawable/ic_sale"
tools:tint="@color/colorPrimary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@font/rubik_medium"
android:gravity="center"
android:maxLines="2"
android:text="@{text}"
tools:text="button title"
android:textAlignment="center"
android:textColor="@color/colorPrimary"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -1,159 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
>
<data>
<import type="com.utsmyanmar.paylibs.utils.POSUtil"/>
<variable
name="payDetail"
type="com.utsmyanmar.paylibs.model.PayDetail" />
<variable
name="onItemClick"
type="com.utsmm.kbz.ui.qr_pay.QRRefundFragment.ClickEvent" />
</data>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_margin="8dp"
android:layout_marginVertical="6dp"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
app:cardBackgroundColor="@color/white"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:onClick="@{() -> onItemClick.onCancel()}">
<!-- Card with border -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:orientation="horizontal"
android:background="@drawable/bg_edittext_primary_border"
android:padding="16dp">
<!-- Transaction Icon -->
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/ic_custom_pos"
app:tint="@color/colorPrimary"
android:alpha="0.8"
android:layout_marginEnd="12dp"
android:layout_gravity="top" />
<!-- Transaction Details -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<!-- Transaction Type and Amount Row -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp">
<!-- Transaction Type -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{POSUtil.getInstance().getTransName(payDetail)}"
android:textColor="@color/colorPrimary"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="sans-serif-medium"
tools:text="SALE" />
<!-- Transaction Amount -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{POSUtil.getInstance().checkMinusSign(payDetail.transactionType)+POSUtil.getInstance().getDecimalAmountSeparatorFormat(payDetail.amount) + ` `+POSUtil.getInstance().currencyCodeToText(payDetail.currencyCode)}"
android:textColor="@color/colorPrimary"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="sans-serif-medium"
tools:text="1,000.00 MMK" />
</LinearLayout>
<!-- Transaction Date -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{POSUtil.getInstance().convertDateFormatByDateString(payDetail.transDate)}"
android:textColor="@color/colorPrimary"
android:textSize="14sp"
android:alpha="0.8"
android:fontFamily="sans-serif"
android:layout_marginBottom="6dp"
tools:text="2022-11-26" />
<!-- Card Number -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{POSUtil.getInstance().getCardNumMasking(payDetail.cardNo)}"
android:textColor="@color/colorPrimary"
android:textSize="14sp"
android:alpha="0.8"
android:fontFamily="monospace"
android:layout_marginBottom="8dp"
tools:text="468785******9564" />
<!-- Trace and RRN Row -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!-- Trace Number -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:isTrace="@{payDetail}"
android:textColor="@color/colorPrimary"
android:textSize="13sp"
android:alpha="0.7"
android:fontFamily="monospace"
tools:text="TRC:000050" />
<!-- RRN -->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{`RRN:`+payDetail.referNo}"
android:textColor="@color/colorPrimary"
android:textSize="13sp"
android:alpha="0.7"
android:fontFamily="monospace"
android:textAlignment="textEnd"
tools:text="RRN:233001786242" />
</LinearLayout>
</LinearLayout>
<!-- Arrow Icon -->
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_right_arrow"
app:tint="@color/colorPrimary"
android:alpha="0.6"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>

View File

@ -5,61 +5,58 @@
<data>
<import type="com.utsmm.kbz.R"/>
<import type="com.utsmm.kbz.util.enums.FeaturesType" />
<variable
name="item"
type="com.utsmm.kbz.config.data.model.Features" />
</data>
<androidx.cardview.widget.CardView
android:id="@+id/trans_card"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="20dp"
app:cardElevation="6dp"
app:disableBtn="@{item.isActive}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="1:1">
<androidx.cardview.widget.CardView
android:id="@+id/trans_card"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_margin="8dp"
app:cardCornerRadius="20dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
app:disableBtn="@{item.isActive}"
android:focusable="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="16dp">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginBottom="8dp"
app:srcUrl="@{item.drawable}"
app:tint="@color/white"
tools:tint="@color/white"
tools:src="@drawable/ic_sale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/rubik_medium"
android:textSize="16sp"
android:textStyle="bold"
android:textAlignment="center"
android:textColor="@color/white"
android:text="@{item.name}"
tools:text="SALE"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
android:background="@color/white">
android:maxLines="2"
android:ellipsize="end" />
<ImageView
android:id="@+id/btnIcon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginBottom="8dp"
app:srcUrl="@{item.drawable}"
app:tint="@color/colorPrimary"
tools:src="@drawable/ic_sale"
tools:tint="@color/colorPrimary" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:gravity="center"
android:text="@{item.name}"
tools:text="button title"
android:textAlignment="center"
android:textColor="@color/colorPrimary"
android:textSize="12sp"
android:textStyle="bold" />
</androidx.cardview.widget.CardView>
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>
</layout>

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.utsmm.kbz.R"/>
<import type="com.utsmm.kbz.util.enums.FeaturesType" />
<variable
name="item"
type="com.utsmm.kbz.config.data.model.Features" />
</data>
<androidx.cardview.widget.CardView
android:id="@+id/trans_card"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_margin="8dp"
app:cardCornerRadius="20dp"
app:cardElevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
app:disableBtn="@{item.isActive}"
android:focusable="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/primary_card_bg"
android:padding="16dp">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginBottom="8dp"
app:srcUrl="@{item.drawable}"
app:tint="@color/white"
tools:tint="@color/white"
tools:src="@drawable/ic_sale" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/rubik_medium"
android:textSize="16sp"
android:textStyle="bold"
android:textAlignment="center"
android:textColor="@color/white"
android:text="@{item.name}"
tools:text="SALE"
android:gravity="center"
android:maxLines="2"
android:ellipsize="end" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>

View File

@ -141,9 +141,6 @@
<action
android:id="@+id/action_nav_main_to_QRConnectingFragment"
app:destination="@id/QRConnectingFragment" />
<action
android:id="@+id/action_nav_main_to_qrFragment"
app:destination="@id/qrFragment" />
<action
app:launchSingleTop="true"
app:popUpTo="@+id/nav_main"
@ -341,18 +338,6 @@
app:popUpToInclusive="true"
android:id="@+id/action_inputPasswordFragment_to_inputTraceFragment"
app:destination="@id/inputTraceFragment" />
<action
app:launchSingleTop="true"
app:popUpTo="@+id/inputPasswordFragment"
app:popUpToInclusive="true"
android:id="@+id/action_inputPasswordFragment_to_qrRefundList"
app:destination="@id/qrRefundList" />
<action
app:launchSingleTop="true"
app:popUpTo="@+id/inputPasswordFragment"
app:popUpToInclusive="true"
android:id="@+id/action_inputPasswordFragment_to_QRRefundProcessFragment"
app:destination="@id/QRRefundProcessFragment" />
</fragment>
@ -1091,72 +1076,6 @@
android:id="@+id/action_receiptFragment_to_nav_main"
app:destination="@id/nav_main" />
</fragment>
<!-- qr menu-->
<fragment
android:id="@+id/qrFragment"
tools:layout="@layout/fragment_qr_pay"
android:name="com.utsmm.kbz.ui.qr_pay.QRPayFragment"
android:label="QRPayFragment" >
<action
android:id="@+id/action_qrFragment_to_inputAmountFragment"
app:destination="@id/inputAmountFragment" />
<action
android:id="@+id/action_qrFragment_to_qrHistory"
app:destination="@id/reprintAnyTransactionFragment"
/>
<action
android:id="@+id/action_qrFragment_to_qr_refund_list"
app:destination="@id/qrRefundList"
/>
</fragment>
<fragment
android:id="@+id/qrRefundList"
tools:layout="@layout/fragment_qr_refund"
android:name="com.utsmm.kbz.ui.qr_pay.QRRefundFragment"
>
<action
android:id="@+id/action_qrRefundList_to_qrRefundDetail"
app:destination="@id/qrRefundDetail"
/>
</fragment>
<fragment
android:id="@+id/qrRefundDetail"
tools:layout="@layout/fragment_qr_refund_detail"
android:name="com.utsmm.kbz.ui.qr_pay.QRRefundDetailFragment"
>
<action
app:launchSingleTop="true"
app:popUpToInclusive="true"
app:popUpTo="@id/mobile_navigation"
android:id="@+id/action_qrRefundDetail_to_nav_main"
app:destination="@id/nav_main" />
<action
android:id="@+id/action_qrRefundDetail_inputPasswordFragment"
app:destination="@id/inputPasswordFragment"
/>
<!-- <action-->
<!-- app:launchSingleTop="true"-->
<!-- app:popUpTo="@id/qrRefundList"-->
<!-- app:popUpToInclusive="false"-->
<!-- android:id="@+id/action_qrRefundDetail_to_password"-->
<!-- app:destination="@id/QRRefundProcessFragment" />-->
</fragment>
<fragment
tools:layout="@layout/fragment_qr_refund_process"
android:id="@+id/QRRefundProcessFragment"
android:name="com.utsmm.kbz.ui.qr_pay.QRRefundProcessFragment"
android:label="QRRefundProcessFragment" >
<action
app:launchSingleTop="true"
app:popUpTo="@+id/QRRefundProcessFragment"
app:popUpToInclusive="true"
android:id="@+id/action_QRRefundProcessFragment_to_transactionResultFragment"
app:destination="@id/transactionResultFragment" />
<action
app:launchSingleTop="true"
app:popUpTo="@+id/QRRefundProcessFragment"
app:popUpToInclusive="true"
android:id="@+id/action_QRRefundProcessFragment_to_nav_main"
app:destination="@id/nav_main" />
</fragment>
</navigation>

View File

@ -308,7 +308,7 @@
<string name="title_processing">Processing</string>
<string name="enter_trans_id_text">Enter Transaction Id</string>
<string name="title_trans_id">Transaction Id</string>
<string name="title_wave_pay">MMQR Pay(title)</string>
<string name="title_wave_pay">Wave Pay</string>
<string name="title_qr_scan">QR Scan</string>
<string name="txt_wave_pay_description">Please scan here to complete your payment.</string>
<string name="txt_title_papaer_roll">Paper roll not found!</string>
@ -362,7 +362,6 @@
<string name="alert_sound_title">Alert Sound</string>
<string name="title_echo">Echo Test</string>
<string name="txt_processing_card">Processing card, please wait...</string>
<string name="txt_processing_refund">Processing refund, please wait...</string>
<string name="title_processing_card">Processing Card</string>
<string name="title_log_on">Log-On</string>
<string name="title_log_off">Log-Off</string>
@ -516,7 +515,6 @@
<string name="txt_error_occurred">Error Occured</string>
<string name="error_occurred">Error Occured</string>
<string name="nav_app_bar_open_drawer_description">Open navigation drawer</string>
<string name="no_history">No History yet</string>
<string-array name="pref_bank_name">
<item>UTS</item>
<item>YOMA Bank</item>

View File

@ -6,6 +6,5 @@
<domain includeSubdomains="true">128.199.170.203</domain>
<domain includeSubdomains="true">152.42.199.193</domain>
<domain includeSubdomains="true">api.kbzpay.com</domain>
<domain includeSubdomains="true">sirius-nest.utsmyanmar.com</domain>
</domain-config>
</network-security-config>

View File

@ -14,7 +14,4 @@ public class ExampleUnitTest {
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

View File

@ -11,7 +11,6 @@ import com.sunmi.pay.hardware.aidl.AidlConstants;
import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.sunmi.pay.hardware.aidlv2.security.SecurityOptV2;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.PayLibNex;
import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.secure.TriDes;
@ -25,11 +24,8 @@ public final class TerminalKeyUtil {
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("e121249099a677e8b7d4f6a9d49fe8d1".toUpperCase()); // MPU
private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("875f63741753d18811a3449090d1777b".toUpperCase());
private static final byte[] work_key_data = new byte[16];
public static void initNexKey() {
byte[] IPEKByte = ByteUtil.hexStr2Bytes("5A4CFF6DE93F0488926166F3317EFD2F"); // IPEK
byte[] IPEKKCVByte = ByteUtil.hexStr2Bytes("1F0C18");
@ -40,8 +36,6 @@ public final class TerminalKeyUtil {
Arrays.fill(work_key_data, (byte) 0x31);
PinPad pinPad = BaseApplication.getInstance().deviceEngine.getPinPad();
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 resultTDKEY = pinPad.writeWKey(0, WorkKeyTypeEnum.TDKEY, work_key_data, work_key_data.length);
@ -53,12 +47,6 @@ public final class TerminalKeyUtil {
// int result = pinPad.dukptKeyInject(9, DukptKeyTypeEnum.BDK,IPEKByte,16,ksn);
LogUtil.d(TAG, "save tmk key result: "+result);
byte[] encryptedPIK = SystemParamsOperation.getInstance().getKeyPIK().get(0);
result = pinPad.writeWKey(9, WorkKeyTypeEnum.PINKEY,encryptedPIK,encryptedPIK.length);
LogUtil.d(TAG, "save PIK key result: "+result);
// LogUtil.d(TAG, "save pin key result: "+resultPINKEY);
// LogUtil.d(TAG, "save tdk key result: "+resultTDKEY);
// LogUtil.d(TAG, "save tek key result: "+resultTEK);

View File

@ -149,10 +149,4 @@ public interface PayDetailDao {
@Query("SELECT * FROM paydetail ORDER BY PID DESC")
LiveData<List<PayDetail>> getAllTrans();
@Query("SELECT * FROM paydetail WHERE transactionType = 20 ORDER BY PID DESC")
LiveData<List<PayDetail>> getAllQRHistory();
@Query("SELECT * FROM paydetail WHERE transactionType = 20 AND qrTransStatus = 1 AND isCanceled = 0 ORDER BY PID DESC")
LiveData<List<PayDetail>> getRefundableQRHistory();
}

View File

@ -34,12 +34,10 @@ public class SiriusInterceptor implements Interceptor {
String hashed = "";
String nonce = TerminalUtil.getInstance().generateRandomNumbers();
// String nonce = "1234567";
try {
// hashed = TerminalUtil.getInstance().generateHashedString(nonce); // old tms
hashed = TerminalUtil.getInstance().generateHashedString(nonce).toLowerCase(); // new tms
hashed = TerminalUtil.getInstance().generateHashedString(nonce);
LogUtil.d(TAG,"hashed :"+ hashed);
// LogUtil.d(TAG,"hashed :"+ hashed);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
@ -49,7 +47,6 @@ public class SiriusInterceptor implements Interceptor {
// .addHeader("content-type", "application/json")
.addHeader("request-id", hashed)
.addHeader("request-code",nonce)
// .addHeader("x-api-key","8f4df38d1001bcc4620b5c736c66a03eef4653eb3ba31105faa2f2ee294c4a46")
.build();
return chain.proceed(newRequest);

View File

@ -15,12 +15,10 @@ public class SiriusRequest {
private String lastTransaction;
private Long lastTranTime;
private String value;
private String lastTranTime;
public SiriusRequest() {}
public SiriusRequest(String serial, String appPackage, String androidVersion, String firmwareVersion, String applicationVersion, String currentNetwork, String lastTransaction, Long lastTranTime, String value) {
public SiriusRequest(String serial, String appPackage, String androidVersion, String firmwareVersion, String applicationVersion, String currentNetwork, String lastTransaction, String lastTranTime) {
this.serial = serial;
this.appPackage = appPackage;
this.androidVersion = androidVersion;
@ -29,7 +27,6 @@ public class SiriusRequest {
this.currentNetwork = currentNetwork;
this.lastTransaction = lastTransaction;
this.lastTranTime = lastTranTime;
this.value = value;
}
public void setSerial(String serial) {
@ -60,7 +57,7 @@ public class SiriusRequest {
this.lastTransaction = lastTransaction;
}
public void setLastTranTime(Long lastTranTime) {
public void setLastTranTime(String lastTranTime) {
this.lastTranTime = lastTranTime;
}
@ -92,15 +89,7 @@ public class SiriusRequest {
return lastTransaction;
}
public Long getLastTranTime() {
public String getLastTranTime() {
return lastTranTime;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -226,8 +226,4 @@ public class Repository {
}
public LiveData<List<PayDetail>> getAllTrans() { return payDetailDao.getAllTrans(); }
public LiveData<List<PayDetail>> getAllQRHistory(){ return payDetailDao.getAllQRHistory();}
public LiveData<List<PayDetail>> getRefundableQRHistory(){ return payDetailDao.getRefundableQRHistory(); }
}

View File

@ -56,15 +56,9 @@ public class TerminalUtilsImpl implements TerminalUtils{
@Override
public String generateRandom() {
Random rnd = new Random();
StringBuilder sb = new StringBuilder();
sb.append(1000000 + rnd.nextInt(9000000));
StringBuilder sb = new StringBuilder((1000000 + rnd.nextInt(9000000)));
return sb.toString();
// Random rnd = new Random();
// StringBuilder sb = new StringBuilder((1000000 + rnd.nextInt(9000000)));
// return sb.toString();
}
@Override

View File

@ -4,13 +4,6 @@ import org.junit.Test;
import static org.junit.Assert.*;
import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
/**
* Example local unit test, which will execute on the development machine (host).
*
@ -27,63 +20,10 @@ public class ExampleUnitTest {
@Test
public void testUpperCase() {
// String keys = "875f63741753d18811a3449090d1777b".toUpperCase();
String keys = "e121249099a677e8b7d4f6a9d49fe8d1".toUpperCase();
String keys = "875f63741753d18811a3449090d1777b".toUpperCase();
System.out.println("Key: "+keys);
String pan = "4216862078830572";
System.out.println("sub pan: "+pan.substring(pan.length()-13));
}
@Test
public void hashString() {
String sn = "N86PW400005";
String snPN = "com.utsmm.kbz";
String nonce = "1234567";
String text = sn + snPN + nonce;
// LogUtil.d(TAG,"Plain Text: "+text);
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
String hashStr = ByteUtil.bytes2HexStr(hash);
System.out.println("Hash: "+hashStr.toLowerCase());
}
@Test
public void generateRandomDigit() {
Random rnd = new Random();
StringBuilder sb = new StringBuilder();
sb.append(1000000 + rnd.nextInt(9000000));
String random = sb.toString();
System.out.println("Random: " + random);
}
@Test
public void hashTestString() {
String sn = "SN3123141";
String snPN = "default-package-1";
String nonce = "1234567";
String text = sn + snPN + nonce;
// LogUtil.d(TAG,"Plain Text: "+text);
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
String hashStr = ByteUtil.bytes2HexStr(hash);
System.out.println("Hash: "+hashStr.toLowerCase());
}
}

View File

@ -8,8 +8,7 @@
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m -Dfile.encoding=UTF-8
# Force Gradle to use system Java instead of Android Studio's JBR
#org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
org.gradle.java.home=C:\\Program Files\\Microsoft\\jdk-17.0.16.8-hotspot
org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
# Enable parallel builds and configure cache
org.gradle.parallel=true

BIN
key.jks

Binary file not shown.

View File

@ -24,208 +24,9 @@ public class DecodePackage {
}
public static HashMap<String, MsgField> unAssembly(byte[] body, HostName hostName,boolean printLog) {
return unAssembly(body,hostName == HostName.BPC? FieldConfig.FieldTypeConfig128 : FieldConfig.FieldTypeConfigV1,hostName,printLog);
return unAssembly(body, FieldConfig.FieldTypeConfig128,hostName,printLog);
}
public synchronized static HashMap<String, MsgField> unAssembly(byte[] body, int[][] fieldConfig) {
HashMap<String, MsgField> resMap = new HashMap<>();
// Request header length 15
// Len[2] + tPDU[5] + Header[6] + Type[2]
int head = 7 + FieldConfig.MESSAGE_HEADER_LENGTH;
// Calculate the length of the message type
byte[] msgData = null;
int typeLength = FieldConfig.FieldTypeConfig128[0][2];
switch (FieldConfig.FieldTypeConfig128[0][3]) {
case FieldConfig.SDK_8583_DATA_BCD:
head += (typeLength + 1) / 2;
msgData = new byte[(typeLength + 1) / 2];
break;
case FieldConfig.SDK_8583_DATA_ASC:
case FieldConfig.SDK_8583_DATA_BIT:
head += typeLength;
msgData = new byte[typeLength];
break;
default:
break;
}
// Fetch header
byte[] headerData = new byte[FieldConfig.MESSAGE_HEADER_LENGTH];
System.arraycopy(body, 7, headerData, 0, FieldConfig.MESSAGE_HEADER_LENGTH);
MsgField headerFiled = new MsgField();
headerFiled.setFieldPos(-1);
headerFiled.setLengthType(fieldConfig[0][0]);
headerFiled.setLengthTypeEncode(fieldConfig[0][1]);
headerFiled.setDataType(fieldConfig[0][3]);
headerFiled.setAlignType(fieldConfig[0][4]);
headerFiled.setFillChar(fieldConfig[0][5]);
headerFiled.setDataLength(fieldConfig[0][2]);
headerFiled.setDataBytes(headerData);
headerFiled.setDataStr(Utils.byte2HexStr(headerData));
resMap.put("header", headerFiled);
String header = Utils.byte2HexStr(headerData);
LogUtil.d(TAG, "header" + header);
// Get message type
System.arraycopy(body, 7 + FieldConfig.MESSAGE_HEADER_LENGTH, msgData, 0, msgData.length);
String msgType = "";
switch (FieldConfig.FieldTypeConfig128[0][3]) {
case FieldConfig.SDK_8583_DATA_BCD:
case FieldConfig.SDK_8583_DATA_BIT:
msgType = Utils.byte2HexStr(msgData);
break;
case FieldConfig.SDK_8583_DATA_ASC:
try {
msgType = new String(msgData, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
break;
default:
break;
}
MsgField msgFiled = new MsgField();
msgFiled.setFieldPos(0);
msgFiled.setLengthType(fieldConfig[0][0]);
msgFiled.setLengthTypeEncode(fieldConfig[0][1]);
msgFiled.setDataType(fieldConfig[0][3]);
msgFiled.setAlignType(fieldConfig[0][4]);
msgFiled.setFillChar(fieldConfig[0][5]);
msgFiled.setDataLength(fieldConfig[0][2]);
msgFiled.setDataBytes(msgData);
msgFiled.setDataStr(msgType);
resMap.put("type", msgFiled);
LogUtil.d(TAG, "Message type" + msgType);
// Get bitmap
boolean[] boolBitmap;
byte[] bitmap = new byte[8];
System.arraycopy(body, head, bitmap, 0, 8);
boolBitmap = Utils.getBinaryFromByte(bitmap);
if (boolBitmap[1]) {
//If the first bit is 1, it is an expandable bitmap, set to 16 bytes in length.
byte[] b = new byte[16];
System.arraycopy(body, head, b, 0, 16);
boolBitmap = Utils.getBinaryFromByte(b);
head += 16;
} else {
head += 8;
}
int size = boolBitmap.length;
// Total length of request header and bitmap
int tmpLen = head;
// 0 1 Domain not used
for (int i = 2; i < size; i++) {
if (boolBitmap[i]) {
MsgField outField = new MsgField();
outField.setFieldPos(i);
outField.setLengthType(fieldConfig[i][0]);
outField.setLengthTypeEncode(fieldConfig[i][1]);
outField.setDataType(fieldConfig[i][3]);
outField.setAlignType(fieldConfig[i][4]);
outField.setFillChar(fieldConfig[i][5]);
// len is useless for variable length
outField.setDataLength(fieldConfig[i][2]);
byte[] nextData;
//53 templen - 54
// Get the value of the variable length part
if (outField.getLengthType() > 0) {
// Get the length of the byte array
int varLen = (outField.getLengthType() + 1) / 2;
byte[] varValue = new byte[varLen];
if(i==62){
tmpLen++;
}
System.arraycopy(body, tmpLen, varValue, 0, varValue.length);
// Length of data length
tmpLen += varLen; //tmp len 54
// Number of bytes of variable length data
int datLen;
int bcdLength = Utils.bcdToint(varValue); //31
// Determine the data type (binary type data is not processed)
if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
datLen = (bcdLength / 2) + (bcdLength % 2);
outField.setDataLength(bcdLength); // Fill the variable length
} else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BIT) {
datLen = bcdLength;
outField.setDataLength(2 * bcdLength); // Fill the variable length
} else {
//asc
datLen = bcdLength;
outField.setDataLength(bcdLength); // Fill the variable length
}
// Take the value of the variable length part
nextData = new byte[datLen];
//tmp len 55
System.arraycopy(body, tmpLen, nextData, 0, datLen);
//updated
/* if(body.length>tmpLen+datLen){
System.arraycopy(body, tmpLen, nextData, 0, datLen);
}else {
return null;
}*/
// Data length
tmpLen += datLen;
} else {
// Fixed-length data length
int datLen;
// Determine the data type (binary type data is not processed)
if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
datLen = (outField.getDataLength() / 2) + (outField.getDataLength() % 2);
} else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_ASC) {
datLen = outField.getDataLength();
} else {
datLen = outField.getDataLength();
}
nextData = new byte[datLen];
System.arraycopy(body, tmpLen, nextData, 0, nextData.length);
tmpLen += nextData.length;
}
// Data input
if (outField.getDataType() == FieldConfig.SDK_8583_DATA_ASC) {
String s = null;
try {
s = new String(nextData, "gbk");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (!TextUtils.isEmpty(s) && Utils.isMessyCode(s)) {
LogUtil.d(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.byte2HexStr(nextData));
} else {
LogUtil.d(TAG, "field pos:" + outField.getFieldPos() + " = " + s);
}
// Determine whether it is GBK encoding or garbled
outField.setDataStr(new String(nextData));
} else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BIT) {
LogUtil.d(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.byte2HexStr(nextData));
outField.setDataStr(Utils.byte2HexStr(nextData));
} else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
LogUtil.d(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.Bcd2String(nextData));
outField.setDataStr(Utils.Bcd2String(nextData));
}
outField.setDataBytes(nextData);
resMap.put("F" + String.format(Locale.getDefault(), "%03d", i), outField);
}
}
return resMap;
}
public synchronized static HashMap<String, MsgField> unAssembly(byte[] body, int[][] fieldConfig,HostName hostName,boolean printLog) {
HashMap<String, MsgField> resMap = new HashMap<>();
@ -351,17 +152,9 @@ public class DecodePackage {
// Get the value of the variable length part
if (outField.getLengthType() > 0) {
int varLen;
if( hostName == HostName.BPC) {
varLen = outField.getLengthType();
} else {
varLen = (outField.getLengthType() + 1) / 2;
}
// Get the length of the byte array
// int varLen = (outField.getLengthType() + 1) / 2;
// varLen = outField.getLengthType();
int varLen = outField.getLengthType();
byte[] varValue = new byte[varLen];
if(i==62){
tmpLen++;
@ -379,7 +172,6 @@ public class DecodePackage {
bcdLength = Integer.parseInt(new String(varValue)); //31
} else {
bcdLength = Utils.bcdToint(varValue); //31
// bcdLength = Integer.parseInt(new String(varValue)); //31
}
// Determine the data type (binary type data is not processed)
@ -405,13 +197,8 @@ public class DecodePackage {
//tmp len 55
try {
if(hostName == HostName.BPC) {
System.arraycopy(body, tmpLen, nextData, 0, datLen);
} else {
System.arraycopy(body, tmpLen, nextData, 0, body.length-tmpLen);
}
//
System.arraycopy(body, tmpLen, nextData, 0, datLen);
// System.arraycopy(body, tmpLen, nextData, 0, body.length-tmpLen);
} catch (IndexOutOfBoundsException e){
e.printStackTrace();
}

View File

@ -19,12 +19,10 @@ import java.util.Map;
import com.utsmyanmar.paylibs.utils.LogUtil;
/**
* Package with MPU certification ready.
* Package
*/
public class EncodePackage {
public static Map<String, MsgField> preAssemblyBase(String bitmapHexString,HostName hostName) {
int [][] fieldTypeViaHost = hostName == HostName.BPC ? FieldConfig.FieldTypeConfig128 : FieldConfig.FieldTypeConfigV1;
return preAssembly(bitmapHexString, fieldTypeViaHost );
@ -139,12 +137,7 @@ public class EncodePackage {
if (fieldDataType == FieldConfig.SDK_8583_DATA_BCD) {
if (msgField.getLengthType() > 0) {
// F035 enter into this step
// len += msgField.getLengthType() + ( msgField.getDataLength() / 2);
if(hostName == HostName.BPC) {
len += msgField.getLengthType() + ( msgField.getDataLength() / 2);
} else {
len += (msgField.getLengthType() + 1) / 2 + (msgField.getDataLength() / 2) + (msgField.getDataLength() % 2);
}
len += msgField.getLengthType() + ( msgField.getDataLength() / 2);
// len += (msgField.getLengthType() + 1) / 2 + (msgField.getDataLength() / 2) + (msgField.getDataLength() % 2);
} else {
len += (msgField.getDataLength() / 2) + (msgField.getDataLength() % 2);
@ -153,12 +146,7 @@ public class EncodePackage {
if (msgField.getLengthType() > 0) {
// commended at Oct4 , 2023 ( for BPC DE55)
// len += (msgField.getLengthType() + 1) / 2 + (msgField.getDataLength() / 2);
if(hostName == HostName.BPC) {
len += msgField.getLengthType() + (msgField.getDataLength() / 2);
} else {
len += (msgField.getLengthType() + 1) / 2 + (msgField.getDataLength() / 2);
}
len += msgField.getLengthType() + (msgField.getDataLength() / 2);
} else {
len += msgField.getDataLength();
@ -168,14 +156,8 @@ public class EncodePackage {
// 12:51pm jan 26 / 21 comment switch cuz of getting error at field 57
// fixing bcd ASCII length odd number eg.3
// need to fix this one later for field 62
if(hostName == HostName.BPC) {
len += msgField.getLengthType() + msgField.getDataLength();
} else {
// len += (msgField.getLengthType() + 1) / 2 + msgField.getDataLength(); // Nov19,2025
len += msgField.getDataLength();
}
// len += (msgField.getLengthType() + 1) / 2 + msgField.getDataLength();
// len += msgField.getLengthType() + msgField.getDataLength();
len += msgField.getLengthType() + msgField.getDataLength();
// msgField.getLengthType() => 2
// len+=msgField.getDataLength()-msgField.getLengthType();
@ -238,13 +220,7 @@ public class EncodePackage {
System.arraycopy(varValue, 0, body, index, varValue.length);
index += varValue.length;
} else if (dataType == FieldConfig.SDK_8583_DATA_BCD) {
byte[] varValue;
if(hostName == HostName.BPC) {
varValue = (String.format("%0" + msgField.getLengthType() + "d", msgField.getDataLength()/2)).getBytes();
} else {
varValue = Utils.StrToBCDBytes(String.format("%0"+msgField.getLengthType() + "d",msgField.getDataLength()));
}
// byte[] varValue = (String.format("%0" + msgField.getLengthType() + "d", msgField.getDataLength()/2)).getBytes();
byte[] varValue = (String.format("%0" + msgField.getLengthType() + "d", msgField.getDataLength()/2)).getBytes();
// byte[] varValue = Utils.StrToBCDBytes(String.format("%0" + msgField.getLengthType() + "d", msgField.getDataLength()));
System.arraycopy(varValue, 0, body, index, varValue.length);
index += varValue.length;
@ -270,40 +246,27 @@ public class EncodePackage {
if (msgField.getDataType() == FieldConfig.SDK_8583_DATA_ASC) {
if (msgField.getLengthType() == 2) {
/* Field 60 issue with TTIP*/
/* String fieldHead = msgField.getDataStr().substring(0,4);
int bcdLen = (fieldHead.length() / 2) + (fieldHead.length() % 2);
byte dat[] = new byte[bcdLen];
Utils.BCDEncode(fieldHead, dat, msgField.getAlignType(), msgField.getFillChar());
System.arraycopy(dat, 0, body, index, bcdLen);
index += bcdLen;
String fieldBody=msgField.getDataStr().substring(4,msgField.getDataLength());
*/
if(hostName == HostName.BPC) {
String fieldBody = msgField.getDataStr();
System.arraycopy(fieldBody.getBytes(StandardCharsets.ISO_8859_1), 0, body, index, fieldBody.length());
index += fieldBody.length();
} else {
String fieldHead = msgField.getDataStr().substring(0,4);
int bcdLen = (fieldHead.length() / 2) + (fieldHead.length() % 2);
byte dat[] = new byte[bcdLen];
Utils.BCDEncode(fieldHead, dat, msgField.getAlignType(), msgField.getFillChar());
System.arraycopy(dat, 0, body, index, bcdLen);
index += bcdLen;
String fieldBody=msgField.getDataStr().substring(4,msgField.getDataLength());
System.arraycopy(fieldBody.getBytes(StandardCharsets.ISO_8859_1), 0, body, index, fieldBody.length());
LogUtil.d(Constant.TAG,"fieldBody : "+fieldBody);
index += fieldBody.length();
}
String fieldBody = msgField.getDataStr();
System.arraycopy(fieldBody.getBytes(StandardCharsets.ISO_8859_1), 0, body, index, fieldBody.length());
index += fieldBody.length();
} else {
LogUtil.d(Constant.TAG, " msgField ------ " + entry.getKey());
if(hostName == HostName.BPC) {
try {
System.arraycopy(msgField.getDataStr().getBytes(StandardCharsets.ISO_8859_1), 0, body, index, msgField.getDataLength());
index += msgField.getDataLength();
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
} else {
try {
System.arraycopy(msgField.getDataStr().getBytes(StandardCharsets.ISO_8859_1), 0, body, index, msgField.getDataLength());
index += msgField.getDataLength();
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
// try {
// LogUtil.d(Constant.TAG, " msgField ------ " + entry.getKey());

View File

@ -122,43 +122,19 @@ public abstract class BaseISOMsgX {
return newBytes;
} else if(isoMode == ISOMode.ONLY_HEADER) {
byte[] outBytes = new byte[receiveBytes.length + 5];
byte[] fakeTPDU = ByteUtil.hexStr2Bytes("5555555555");
System.arraycopy(fakeTPDU, 0, outBytes, 2, 5);
System.arraycopy(receiveBytes, 2, outBytes, 7, receiveBytes.length-2 );
int hig = (outBytes.length - 2) / 256;
int low = (outBytes.length - 2) % 256;
outBytes[0] = (byte) hig;
outBytes[1] = (byte) low;
byte[] outBytes = new byte[receiveBytes.length + 6];
byte[] headBytes = ByteUtil.hexStr2Bytes("888888888888");
System.arraycopy(receiveBytes, 0, outBytes, 0, 7);
System.arraycopy(headBytes, 0, outBytes, 7, headBytes.length);
System.arraycopy(receiveBytes, 7, outBytes, 13, receiveBytes.length - 7);
log = "HexString:" + ByteUtil.bytes2HexStr(outBytes);
LogUtil.d(Constant.TAG, log);
return outBytes;
// byte[] newBytes = new byte[outBytes.length + 6];
//
//
// System.arraycopy(outBytes, 0, newBytes, 0, 7);
// System.arraycopy(headBytes, 0, newBytes, 7, headBytes.length);
// System.arraycopy(outBytes, 7, newBytes, 13, outBytes.length - 7);
//
// log = "HexString Packed:" + ByteUtil.bytes2HexStr(newBytes);
// LogUtil.d(Constant.TAG, log);
// return newBytes;
// byte[] outBytes = new byte[receiveBytes.length + 6];
//
// byte[] headBytes = ByteUtil.hexStr2Bytes("888888888888");
//
// System.arraycopy(receiveBytes, 0, outBytes, 0, 6);
// System.arraycopy(headBytes, 0, outBytes, 6, headBytes.length);
// System.arraycopy(receiveBytes, 6, outBytes, 12, receiveBytes.length - 6);
//
// log = "HexString:" + ByteUtil.bytes2HexStr(outBytes);
// LogUtil.d(Constant.TAG, log);
//
// return outBytes;
} else {

View File

@ -26,15 +26,11 @@ import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
@ -69,8 +65,6 @@ import com.utsmyanmar.paylibs.utils.LogUtil;
public class ISOSocket {
private static final int DEFAULT_TIMEOUT = 30 * 1000;
private static final String TAG = ISOSocket.class.getSimpleName();
private String serverIP;
private int serverPort;
private int connectTimeout = 20;
@ -154,15 +148,16 @@ public class ISOSocket {
private SSLSocketFactory getSSLSocketFactory()
throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = context.getResources().openRawResource(R.raw.uat_test); // this cert file stored in \app\src\main\res\raw folder path
InputStream caInput = context.getResources().openRawResource(R.raw.smile_uat); // this cert file stored in \app\src\main\res\raw folder path
Certificate ca = cf.generateCertificate(caInput);
caInput.close();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); // BKS
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
@ -179,118 +174,81 @@ public class ISOSocket {
private OkHttpClient getClient()
throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {
// CertificateFactory cf = CertificateFactory.getInstance("X.509");
// InputStream caInput = context.getResources().openRawResource(R.raw.uat_test); // this cert file stored in \app\src\main\res\raw folder path
//
//
// Certificate ca = cf.generateCertificate(caInput);
// caInput.close();
//
// KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
// keyStore.load(null, null);
// keyStore.setCertificateEntry("ca", ca);
//
//
// TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
// TrustManagerFactory.getDefaultAlgorithm());
// trustManagerFactory.init(keyStore);
// TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
// if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
// throw new IllegalStateException("Unexpected default trust managers:"
// + Arrays.toString(trustManagers));
// }
// X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
// SSLContext sslContext = SSLContext.getInstance("TLS");
// sslContext.init(null, new TrustManager[]{trustManager}, null);
// SSLSocketFactory sslSocketFactory = getSSLSocketFactory();
//
// Interceptor dummyInterceptor = new Interceptor() {
// @NotNull
// @Override
// public Response intercept(@NotNull Chain chain) throws IOException {
// Request request = chain.request();
// Response response = chain.proceed(request);
// System.out.println("Dummy interceptor fired!\n\nRequest: " + request.headers() + "\nResponse: " + response.headers());
// return response;
// }
// };
// Interceptor dummyNetworkInterceptor = new Interceptor() {
// @NotNull
// @Override
// public Response intercept(@NotNull Chain chain) throws IOException {
// Request request = chain.request();
// Response response = chain.proceed(request);
// System.out.println("Dummy interceptor fired!\n\nRequest: " + request.headers() + "\nResponse: " + response.headers());
// return response;
// }
// };
//
// Interceptor tlsIntercept = new Interceptor() {
// @NotNull
// @Override
// public Response intercept(@NotNull Chain chain) throws IOException {
// final Response response = chain.proceed(chain.request());
// Handshake handshake = response.handshake();
// if (handshake != null) {
// final CipherSuite cipherSuite = handshake.cipherSuite();
// final TlsVersion tlsVersion = handshake.tlsVersion();
// LogUtil.d(Constant.TAG, "TLS: " + tlsVersion + ", CipherSuite: " + cipherSuite);
// }
// return response;
// }
// };
//
//
// return new OkHttpClient.Builder()
// .sslSocketFactory(sslSocketFactory, trustManager)
// .hostnameVerifier(new HostnameVerifier() {
// @Override
// public boolean verify(String hostname, SSLSession session) {
// return true;
// }
// })
// .addInterceptor(tlsIntercept)
// .connectTimeout(30000, TimeUnit.MILLISECONDS)
// .readTimeout(30000, TimeUnit.MILLISECONDS)
// .writeTimeout(30000, TimeUnit.MILLISECONDS)
// .retryOnConnectionFailure(true)
// .build();
// 1. Read the DER file into a byte array/InputStream
// (Assuming the file is bundled in your app's resources)
InputStream caInput = context.getResources().openRawResource(R.raw.uat_test); // Replace R.raw.cacert
// 2. Load the certificate from the InputStream
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) cf.generateCertificate(caInput);
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
InputStream caInput = context.getResources().openRawResource(R.raw.smile_uat); // this cert file stored in \app\src\main\res\raw folder path
Certificate ca = cf.generateCertificate(caInput);
caInput.close();
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", caCert); // 'ca' is an alias
keyStore.setCertificateEntry("ca", ca);
// 3. Create a TrustManager that uses your custom KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
TrustManager[] trustAll = new TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
}};
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, trustAll, new SecureRandom());
SSLSocketFactory factory = ctx.getSocketFactory();
try (SSLSocket ssock = (SSLSocket) factory.createSocket()) {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{trustManager}, null);
SSLSocketFactory sslSocketFactory = getSSLSocketFactory();
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(ctx.getSocketFactory())
Interceptor dummyInterceptor = new Interceptor() {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
System.out.println("Dummy interceptor fired!\n\nRequest: " + request.headers() + "\nResponse: " + response.headers());
return response;
}
};
Interceptor dummyNetworkInterceptor = new Interceptor() {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
System.out.println("Dummy interceptor fired!\n\nRequest: " + request.headers() + "\nResponse: " + response.headers());
return response;
}
};
Interceptor tlsIntercept = new Interceptor() {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
final Response response = chain.proceed(chain.request());
Handshake handshake = response.handshake();
if (handshake != null) {
final CipherSuite cipherSuite = handshake.cipherSuite();
final TlsVersion tlsVersion = handshake.tlsVersion();
LogUtil.d(Constant.TAG, "TLS: " + tlsVersion + ", CipherSuite: " + cipherSuite);
}
return response;
}
};
return new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustManager)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.addInterceptor(tlsIntercept)
.connectTimeout(30000, TimeUnit.MILLISECONDS)
.readTimeout(30000, TimeUnit.MILLISECONDS)
.writeTimeout(30000, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(true)
.build();
return client;
}
public boolean isOnline() {
@ -375,8 +333,6 @@ public class ISOSocket {
serverPort = getSecondaryPort();
}
private String formatDate(Date d) { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(d); }
public void enqueue(byte[] sendBuff, int sendLen, boolean reversalTrans, ISOCallback listener) {
this.listener = listener;
@ -428,54 +384,8 @@ public class ISOSocket {
if (SystemParamsOperation.getInstance().isSslOn()) {
try {
TrustManager[] trustAll = new TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
}};
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, trustAll, new SecureRandom());
SSLSocketFactory factory = ctx.getSocketFactory();
// try (SSLSocket sslsock = (SSLSocket) factory.createSocket()) {
//
// sslsock.setEnabledProtocols(new String[]{"TLSv1.2"});
//// while (!isSSLOnline(timeout,subscriber)) {
//// Thread.sleep(150);
//// subscriber.onError(new Throwable("java.net.SocketTimeoutException: connect timed out"));
//// }
//
// sslsock.setSoTimeout(60000);
// sslsock.connect(new InetSocketAddress(serverIP, serverPort), connectTimeout);
//
// sslsock.startHandshake();
//
// SSLSession session = sslsock.getSession();
//
// LogUtil.d(TAG, "SSL handshake success to " + serverIP + ":" + serverPort + "\n");
// LogUtil.d(TAG, "TLS handshake success to " + serverIP + ":" + serverPort + "\n");
// LogUtil.d(TAG, "TLS version: " + session.getProtocol() + "\n");
// LogUtil.d(TAG,"Cipher suite: " + session.getCipherSuite() + "\n");
//
// try {
// java.security.cert.Certificate[] chain = session.getPeerCertificates();
// if (chain != null && chain.length > 0) {
// LogUtil.d(TAG,"Peer certificates:\n");
// for (int i = 0; i < chain.length; i++) {
// X509Certificate x = (X509Certificate) chain[i];
// LogUtil.d(TAG, " [" + i + "] Subject: " + x.getSubjectX500Principal().getName() + "\n");
// LogUtil.d(TAG," Issuer: " + x.getIssuerX500Principal().getName() + "\n");
// LogUtil.d(TAG," Valid: " + formatDate(x.getNotBefore()) + " - " + formatDate(x.getNotAfter()) + "\n");
// }
// }
// } catch (Exception ignored) { }
// }
// OkHttpClient client = getClient();
sslSocket = (SSLSocket) factory.createSocket();
sslSocket.setEnabledProtocols(new String[]{"TLSv1.2"});
// sslSocket.setEnabledProtocols(new String[]{"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"});
OkHttpClient client = getClient();
sslSocket = (SSLSocket) client.sslSocketFactory().createSocket();
// while (!isSSLOnline(timeout,subscriber)) {
// Thread.sleep(150);
// subscriber.onError(new Throwable("java.net.SocketTimeoutException: connect timed out"));
@ -484,28 +394,6 @@ public class ISOSocket {
sslSocket.setSoTimeout(60000);
sslSocket.connect(new InetSocketAddress(serverIP, serverPort), connectTimeout);
sslSocket.startHandshake();
SSLSession session = sslSocket.getSession();
LogUtil.d(TAG, "SSL handshake success to " + serverIP + ":" + serverPort + "\n");
LogUtil.d(TAG, "TLS handshake success to " + serverIP + ":" + serverPort + "\n");
LogUtil.d(TAG, "TLS version: " + session.getProtocol() + "\n");
LogUtil.d(TAG,"Cipher suite: " + session.getCipherSuite() + "\n");
try {
java.security.cert.Certificate[] chain = session.getPeerCertificates();
if (chain != null && chain.length > 0) {
LogUtil.d(TAG,"Peer certificates:\n");
for (int i = 0; i < chain.length; i++) {
X509Certificate x = (X509Certificate) chain[i];
LogUtil.d(TAG, " [" + i + "] Subject: " + x.getSubjectX500Principal().getName() + "\n");
LogUtil.d(TAG," Issuer: " + x.getIssuerX500Principal().getName() + "\n");
LogUtil.d(TAG," Valid: " + formatDate(x.getNotBefore()) + " - " + formatDate(x.getNotAfter()) + "\n");
}
}
} catch (Exception ignored) { }
inputStream = sslSocket.getInputStream();
outputStream = sslSocket.getOutputStream();
@ -533,7 +421,7 @@ public class ISOSocket {
subscriber.onComplete();
} catch ( IOException |
} catch (CertificateException | KeyStoreException | IOException |
NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
subscriber.onError(e);
@ -607,9 +495,7 @@ public class ISOSocket {
@Override
public void onNext(byte[] aByte) {
LogUtil.d(Constant.TAG, "onNext raw:"+ByteUtil.bytes2HexStr(aByte));
LogUtil.d(Constant.TAG, "onNext");
//rlen =47 MPU 5:44pm 21/9/2020
listener.onReceive(recBuff, rLen);
isReversal = false;

View File

@ -706,7 +706,7 @@ public abstract class BaseXPrint {
String cvmText = "NO SIGNATURE REQUIRED";
switch (payDetail.getTransCVM()) {
case SIGNATURE:
cvmText = "SIGN : --------------";
cvmText = "SIGN : -----------------------------";
break;
case ONLINE_PIN:
cvmText = "ONLINE PIN VERIFIED";

View File

@ -40,7 +40,7 @@ public class PrintXImpl extends BaseXPrint implements PrintX {
SimpleDateFormat dfm = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault());
currentTime = dfm.format(new Date());
BitmapFactory.Options opts = new BitmapFactory.Options();
bitmap = BitmapFactory.decodeResource(resources, R.drawable.print_logo_mpu, opts);
bitmap = BitmapFactory.decodeResource(resources, R.drawable.print_kbz_logo, opts);
}
@Override

View File

@ -49,7 +49,7 @@ public class ReversalAction {
}
private ReversalAction() {
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.ONLY_HEADER,HostName.FINEXUS)
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU,HostName.BPC)
.build();
}

View File

@ -47,7 +47,7 @@ public class EchoTestProcess {
private EchoTestProcess() {
tradeData = Params.newTrade(true);
payDetail = tradeData.getPayDetail();
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.ONLY_HEADER,HostName.FINEXUS)
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU,HostName.BPC)
.build();
}

View File

@ -51,7 +51,7 @@ public class SignOnProcess {
private SignOnProcess() {
tradeData = Params.newTrade(true);
// payDetail = tradeData.getPayDetail();
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.ONLY_HEADER,HostName.FINEXUS)
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU,HostName.BPC)
.build();
}
@ -84,7 +84,7 @@ public class SignOnProcess {
}
byte[] sendBytes = isoMsgX.buildISOPackets(tradeData, BitmapConfig.MPU_SIGN_ON, MessageType.NETWORK_MANAGEMENT);
byte[] sendBytes = isoMsgX.buildISOPackets(tradeData, BitmapConfig.BPC_SIGN_ON, MessageType.NETWORK_MANAGEMENT);
ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length,false, new ISOCallback() {
@Override
public void onReceive(byte[] bytes, int length) {
@ -107,9 +107,7 @@ public class SignOnProcess {
byte[] field62 = Objects.requireNonNull(responseMap.get("F062")).getDataBytes();
byte[] encryptedPIK = new byte[16];
System.arraycopy(field62, 0, encryptedPIK, 0, 8);
System.arraycopy(field62, 0, encryptedPIK, 8, 8);
// System.arraycopy(field62, 0, encryptedPIK, 0, 16);
System.arraycopy(field62, 2, encryptedPIK, 0, 16);
try {
byte[] kcv = ByteUtil.hexStr2Bytes(TriDes.getKcv(encryptedPIK));
@ -120,9 +118,6 @@ public class SignOnProcess {
tmkIndex = Integer.parseInt(SystemParamsOperation.getInstance().getTMKIndex());
}
LogUtil.d(TAG, "TMK Index:" + tmkIndex);
SystemParamsOperation.getInstance().saveKeyPIK(encryptedPIK, kcv);
int res = PayLibNex.getInstance().deviceEngine.getPinPad().writeWKey(9, WorkKeyTypeEnum.PINKEY,encryptedPIK,encryptedPIK.length);
// int res = PayLibsUtils.getInstance().securityOptV2.saveCiphertextKey(AidlConstantsV2.Security.KEY_TYPE_PIK, encryptedPIK, null, tmkIndex, AidlConstantsV2.Security.KEY_ALG_TYPE_3DES, 11);
// resultCode = res;

View File

@ -82,7 +82,7 @@ public class TransactionsOperation {
TradeData transTradeData;
PayDetail transPayDetail;
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1987, ISOMode.ONLY_HEADER, hostName)
isoMsgX = new ISOMsgX.ISOMsgXBuilder(ISOVersion.VERSION_1993, ISOMode.BOTH_HEADER_TPDU, hostName)
.build();
if (transactionsType == TransactionsType.SALE || transactionsType == TransactionsType.PRE_AUTH_SALE || transactionsType == TransactionsType.CASH_OUT) {
@ -102,6 +102,7 @@ public class TransactionsOperation {
return;
}
transPayDetail.setSendBag(sendBytes);
@ -348,13 +349,7 @@ public class TransactionsOperation {
if (transactionsType == TransactionsType.VOID || transactionsType == TransactionsType.REFUND) {
String field60;
if(hostName == HostName.BPC) {
field60 = String.format(Locale.getDefault(), "%010d00", oldPay.getAmount());
} else {
field60 = String.format(Locale.getDefault(), "%012d", oldPay.getAmount());
}
// String field60 = String.format(Locale.getDefault(), "%010d00", oldPay.getAmount());
String field60 = String.format(Locale.getDefault(), "%010d00", oldPay.getAmount());
newPay.setReferNo(oldPay.getReferNo());
newPay.setTransCVM(TransCVM.SIGNATURE);
newTrade.setField60(field60);

View File

@ -29,6 +29,7 @@ public class KernelDataProcessUtil {
private static final String TAG = KernelDataProcessUtil.class.getSimpleName();
private static CardScheme cardScheme;
public static com.sunmi.pay.hardware.aidl.bean.CardInfo getCardInfo(int cardType, byte[] data) {
Map<String, TLV> tlvMap = TLVUtil.buildTLVMap(data);
com.sunmi.pay.hardware.aidl.bean.CardInfo cardInfo = new com.sunmi.pay.hardware.aidl.bean.CardInfo();
@ -68,6 +69,7 @@ public class KernelDataProcessUtil {
}
LogUtil.d(Constant.TAG, "The card is valid for" + value);
}
}
// Card serial number
@ -102,6 +104,7 @@ public class KernelDataProcessUtil {
}
public static TradeData fillTradeDataInfo(com.sunmi.pay.hardware.aidl.bean.CardInfo cardInfo, TradeData tradeData) {
PayDetail payDetail = tradeData.getPayDetail();
if (cardInfo.expireDate != null && cardInfo.expireDate.length() > 4) {
cardInfo.expireDate = cardInfo.expireDate.substring(0, 4);
@ -589,6 +592,7 @@ public class KernelDataProcessUtil {
}
/*
* merchant category code
* */
@ -722,6 +726,7 @@ public class KernelDataProcessUtil {
return tradeData;
}
private static String getHexLen(int len) {
String str = Integer.toHexString(len);
if (str.length() == 1) {

View File

@ -41,8 +41,7 @@ public class SystemParamsSettings implements Serializable {
private boolean checkExpSwitch = false;
// private String tmsAddress = "https://tms.smile-mm.com";
// private String tmsAddress = "http://128.199.170.203";
private String tmsAddress = "http://sirius-nest.utsmyanmar.com";
private String tmsAddress = "http://128.199.170.203";
private String terminalCapability = "E0E8C8";

View File

@ -12,8 +12,6 @@ public enum TransMenu {
REVERSAL,
CASH_OUT,
CLEAR_BATCH,
CLEAR_REVERSAL,
SUMMARY_REPORT,

View File

@ -27,63 +27,63 @@ public class HostUtils {
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_SALE;
} else {
bitmap = BitmapConfig.MPU_NEW_SALE;
bitmap = BitmapConfig.FINEXUS_SALE;
}
break;
case CASH_OUT:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_SALE;
} else {
bitmap = BitmapConfig.MPU_NEW_CASH_ADVANCE;
bitmap = BitmapConfig.FINEXUS_SALE;
}
break;
case VOID:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_VOID;
} else {
bitmap = BitmapConfig.MPU_NEW_VOID;
bitmap = BitmapConfig.FINEXUS_VOID;
}
break;
case SETTLEMENT:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_SETTLEMENT;
} else {
bitmap = BitmapConfig.MPU_NEW_BATCH_UPLOAD;
bitmap = BitmapConfig.FINEXUS_BATCH_UPLOAD;
}
break;
case PRE_AUTH_SALE:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_PRE_AUTH_SALE;
} else {
bitmap = BitmapConfig.MPU_NEW_PRE_AUTH;
bitmap = BitmapConfig.FUND_TRANSFER_PRE_CHECK;
}
break;
case PRE_AUTH_VOID:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_PRE_AUTH_SALE_VOID_REVERSAL;
} else {
bitmap = BitmapConfig.MPU_NEW_PRE_AUTH_CANCEL;
bitmap = BitmapConfig.FINEXUS_SALE;
}
break;
case PRE_AUTH_COMPLETE:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_PRE_AUTH_SALE_COMPLETE;
} else {
bitmap = BitmapConfig.MPU_NEW_PRE_AUTH_COMPLETE_BITMAP;
bitmap = BitmapConfig.FINEXUS_SALE;
}
break;
case PRE_AUTH_COMPLETE_VOID:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_VOID;
} else {
bitmap = BitmapConfig.MPU_NEW_PRE_AUTH_COMPLETE_CANCEL;
bitmap = BitmapConfig.FINEXUS_PRE_AUTH_VOID;
}
break;
case REFUND:
if (hostName == HostName.BPC) {
bitmap = BitmapConfig.BPC_REFUND;
} else {
bitmap = BitmapConfig.MPU_NEW_REFUND;
bitmap = BitmapConfig.FINEXUS_SALE;
}
break;
case TIP_ADJUSTMENT:

View File

@ -200,7 +200,7 @@ public class FieldConfig {
public static int[][] FieldTypeConfigV1 =
{
/* FLD 00 */ {0, SDK_8583_LEN_BCD, 4, SDK_8583_DATA_BCD, SDK_8583_ALIGN_L, '0'},
/* FLD 01 */ {0, SDK_8583_LEN_BCD, 8, SDK_8583_DATA_BIT, SDK_8583_ALIGN_L, 0}, // 8
/* FLD 01 */ {0, SDK_8583_LEN_BCD, 8, SDK_8583_DATA_BIT, SDK_8583_ALIGN_L, 0},
/* FLD 02 */ {2, SDK_8583_LEN_BCD, 19, SDK_8583_DATA_BCD, SDK_8583_ALIGN_L, '0'},
@ -242,12 +242,12 @@ public class FieldConfig {
/* FLD 34 */ {0, SDK_8583_LEN_BCD, 40, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, ' '},
//MPU is fine with this config
/* FLD 35 */ {2, SDK_8583_LEN_BCD, 37, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
// /* FLD 35 */ {2, SDK_8583_LEN_BCD, 37, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
//For Finexus
// for TTIP MPU
// /* FLD 35 */ {2, SDK_8583_LEN_BCD, 37, SDK_8583_DATA_BCD, SDK_8583_ALIGN_L, '0'},
// /* FLD 35 */ {2, SDK_8583_LEN_BCD, 37, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
/* FLD 35 */ {2, SDK_8583_LEN_BCD, 37, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
/* FLD 36 */ {3, SDK_8583_LEN_BCD, 999, SDK_8583_DATA_BIT, SDK_8583_ALIGN_L, '0'},
/* FLD 37 */ {0, SDK_8583_LEN_BCD, 12, SDK_8583_DATA_ASC, SDK_8583_ALIGN_R, '0'},
@ -269,8 +269,8 @@ public class FieldConfig {
// /* FLD 48 */ {0, SDK_8583_LEN_BCD, 999, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, 0}, // Jun4 2023 BPC
/* FLD 48 */ {3, SDK_8583_LEN_BCD, 322, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, '0'},
/* FLD 49 */ {0, SDK_8583_LEN_BCD, 3, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
// /* FLD 49 */ {0, SDK_8583_LEN_BCD, 3, SDK_8583_DATA_ASC, SDK_8583_ALIGN_R, ' '},
// /* FLD 49 */ {0, SDK_8583_LEN_BCD, 3, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
/* FLD 49 */ {0, SDK_8583_LEN_BCD, 3, SDK_8583_DATA_ASC, SDK_8583_ALIGN_R, ' '},
/* FLD 50 */ {0, SDK_8583_LEN_BCD, 12, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
/* FLD 51 */ {0, SDK_8583_LEN_BCD, 12, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
/* FLD 52 */ {0, SDK_8583_LEN_BCD, 8, SDK_8583_DATA_BIT, SDK_8583_ALIGN_L, 0},
@ -289,11 +289,11 @@ public class FieldConfig {
/* FLD 59 */ {3, SDK_8583_LEN_BCD, 999, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, '0'},
// original /* FLD 60 */ {3, SDK_8583_LEN_BCD, 17, SDK_8583_DATA_BCD, SDK_8583_ALIGN_L, '0'},
/*FLD 60 */ {2, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, ' '}, // MPU //2
// /*FLD 60 */ {3, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, '0'},
// MPU /*FLD 60 */ {2, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, ' '},
/*FLD 60 */ {3, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, '0'},
/* FLD 61 */ {3, SDK_8583_LEN_BCD, 29, SDK_8583_DATA_BCD, SDK_8583_ALIGN_L, '0'},
/* FLD 62 */ {2, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, '0'}, // Jun 1 2023
// /* FLD 62 */ {2, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, ' '},
// /* FLD 62 */ {3, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, '0'}, // Jun 1 2023
/* FLD 62 */ {2, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, ' '},
// /* FLD 62 */ {2, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_BCD, SDK_8583_ALIGN_R, '0'},
// original /* FLD 63 */ {2, SDK_8583_LEN_BCD, 255, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, ' '},

View File

@ -257,23 +257,12 @@ public class FieldUtils {
switch (fieldPos) {
case 2: //PAN
if(payDetail.getHostName().equals(Constant.HOST_BPC)) {
if (payDetail.getCardType() == -1) { //manual entry
String cardNumber = payDetail.getCardNo();
field.setDataStr(cardNumber);
} else {
iterator.remove();
}
if (payDetail.getCardType() == -1) { //manual entry
String cardNumber = payDetail.getCardNo();
field.setDataStr(cardNumber);
} else {
if (!payDetail.getCardNo().isEmpty()) {
String cardNumber = payDetail.getCardNo();
field.setDataStr(cardNumber);
} else {
iterator.remove();
}
iterator.remove();
}
break;
case 3: // processing code
String code = payDetail.getProcessCode();
@ -371,8 +360,7 @@ public class FieldUtils {
break;
case 24: //Network International Identifier NII
String nii = "609";
// String nii = processField24(payDetail); // BPC
String nii = processField24(payDetail);
field.setDataStr(nii);
break;
@ -512,7 +500,6 @@ public class FieldUtils {
case 60: //Private(oldMPU) //original Amount Void(new MPU)
String field60 = tradeData.getField60();
String lengthValue = String.format(Locale.getDefault(),"%04d", field60.length())+field60;
// String lengthValue = String.format(Locale.getDefault(),"%04d", field60.length())+field60;
field.setDataStr(lengthValue);
break;
case 61:
@ -539,8 +526,8 @@ public class FieldUtils {
break;
case 63: //Private Use
String settleData = payDetail.getSettleData();
field.setDataStr(settleData);
// String settleData = payDetail.getSettleData();
// field.setDataStr(settleData);
break;
case 64: //Message Authentication Code (MAC) Required when the 39 field in the response message is "00"
field.setDataStr("0000000000000000");

View File

@ -9,13 +9,13 @@ public enum TransactionsType {
REFUND("REFUND",4,"200000"),
PRE_AUTH_SALE("PRE-AUTH",5,"300000"), //930000
PRE_AUTH_SALE("PRE-AUTH",5,"930000"),
PRE_AUTH_VOID("PREAUTH CANCELLATION",6,"020000"), //200000
PRE_AUTH_COMPLETE("PREAUTH COMPLETION",7,"000000"), //940000
PRE_AUTH_COMPLETE("PREAUTH COMPLETION",7,"940000"),
PRE_AUTH_COMPLETE_VOID("VOID PREAUTH COMPLETE",8,"000000"),//940000
PRE_AUTH_COMPLETE_VOID("VOID PREAUTH COMPLETE",8,"940000"),
CASH_OUT("CASH_OUT",9,"010000"),
REVERSAL("REVERSAL",10,"00"),
@ -24,7 +24,7 @@ public enum TransactionsType {
CASH_DEPOSIT("CASH_DEPOSIT",13,"210000"),
FUND_TRANSFER("FUND_TRANSFER",14,""),
SETTLEMENT_CUT_OVER("SETTLEMENT_CUT_OVER",15,""),
SIGN_ON("SIGN_ON",16,"920000"), // bpc 990000
SIGN_ON("SIGN_ON",16,"990000"),
SETTLEMENT_UPLOAD("SETTLEMENT_UPLOAD",17,"960000"),
TIP_ADJUSTMENT("TIP_ADJUSTMENT",18,"190000"),

View File

@ -82,8 +82,7 @@ public class Params {
payDetail.setIsCanceled(false);
payDetail.transNum = System.currentTimeMillis() / 1000;
// need to add host logic in another place
// payDetail.setHostName("BPC");
payDetail.setHostName("FINEXUS");
payDetail.setHostName("BPC");
payDetail.setOriginalTransDate(SystemDateTime.getMMDD()+SystemDateTime.getYYYY());

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

View File

@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDnzCCAoegAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJNTTEL
MAkGA1UECAwCTU0xDDAKBgNVBAoMA01QVTEMMAoGA1UECwwDTVBVMREwDwYDVQQD
DAh1YXRfdGVzdDEfMB0GCSqGSIb3DQEJARYQdWF0X3Rlc3RAbXB1LmNvbTAeFw0y
NDA4MjMwODU5NTNaFw0yNzA4MjMwODU5NTNaMGoxCzAJBgNVBAYTAk1NMQswCQYD
VQQIDAJNTTEMMAoGA1UECgwDTVBVMQwwCgYDVQQLDANNUFUxETAPBgNVBAMMCHVh
dF90ZXN0MR8wHQYJKoZIhvcNAQkBFhB1YXRfdGVzdEBtcHUuY29tMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnhwFBnMvyuRldNggsrrHMuFTTfTcJLIR
sz+n+WBVxcYhiJWK1QR8CvvOhcvAiiFte+3qy98APBGTRtKwgvGI7bNgV+fBbdgI
UmXzvrU/3XykjlbPV8IPWmgugQ1PBcJ/M8NN8VVephR8300VaGgvMmFuv7ybaGFV
iEHOhXgZOu5d4Hhn41n0GNCpmDZHzEFXcUcELTOZTelh+Hmr9agcY1NkPoitasNA
qvT+J0FfCRWQnbbmy2Fou93fKBxg/76+Lu9ZuuGfsmFenA/6vdgPjNxHivz5WycA
l6hPR4YmfLGpfCO/WHmXhcf4Fy77s52daLOpWYSvw2FID94h08czRQIDAQABo1Aw
TjAdBgNVHQ4EFgQUvgnkWvwGg5YxSQf3VyB1iup1AAUwHwYDVR0jBBgwFoAUvgnk
WvwGg5YxSQf3VyB1iup1AAUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
AQEAUtSEqdJ36X4SD+HsAWZ7Eu4jnjOq6sCk8uaQSOU1fr+ABYIx/AuJ77OvyMj1
biEO7YQ+t0dxF5upAeb4e4tiEddS3XgntGbg6jEfjyyxfsZfTV3OzlPw3dUD8pHA
8ej3iSSRdhiywrHRQP1fEAZhcYa9yElkGJlsH/AUTlbv236AkyUvqf992QJRsw1T
YBYUDjONt1jxiW1/4SKcWN/9MlCpXLCTqNxgUHXuINi1vVI4gsjkQgvoMDdL7BdZ
8kvMh/CjqYHngqwruAQ9SPRZAfp63dHwXsi4HvkqsVdw4TkjEYMi2FuBCUvr7Eww
mU11cvvzhOXUxzpnEegAXsDVxg==
-----END CERTIFICATE-----

View File

@ -1,79 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=MM, ST=MM, O=MPU, OU=MPU, CN=uat_test/emailAddress=uat_test@mpu.com
Validity
Not Before: Aug 23 08:59:53 2024 GMT
Not After : Aug 23 08:59:53 2027 GMT
Subject: C=MM, ST=MM, O=MPU, OU=MPU, CN=uat_test/emailAddress=uat_test@mpu.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:9e:1c:05:06:73:2f:ca:e4:65:74:d8:20:b2:ba:
c7:32:e1:53:4d:f4:dc:24:b2:11:b3:3f:a7:f9:60:
55:c5:c6:21:88:95:8a:d5:04:7c:0a:fb:ce:85:cb:
c0:8a:21:6d:7b:ed:ea:cb:df:00:3c:11:93:46:d2:
b0:82:f1:88:ed:b3:60:57:e7:c1:6d:d8:08:52:65:
f3:be:b5:3f:dd:7c:a4:8e:56:cf:57:c2:0f:5a:68:
2e:81:0d:4f:05:c2:7f:33:c3:4d:f1:55:5e:a6:14:
7c:df:4d:15:68:68:2f:32:61:6e:bf:bc:9b:68:61:
55:88:41:ce:85:78:19:3a:ee:5d:e0:78:67:e3:59:
f4:18:d0:a9:98:36:47:cc:41:57:71:47:04:2d:33:
99:4d:e9:61:f8:79:ab:f5:a8:1c:63:53:64:3e:88:
ad:6a:c3:40:aa:f4:fe:27:41:5f:09:15:90:9d:b6:
e6:cb:61:68:bb:dd:df:28:1c:60:ff:be:be:2e:ef:
59:ba:e1:9f:b2:61:5e:9c:0f:fa:bd:d8:0f:8c:dc:
47:8a:fc:f9:5b:27:00:97:a8:4f:47:86:26:7c:b1:
a9:7c:23:bf:58:79:97:85:c7:f8:17:2e:fb:b3:9d:
9d:68:b3:a9:59:84:af:c3:61:48:0f:de:21:d3:c7:
33:45
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
BE:09:E4:5A:FC:06:83:96:31:49:07:F7:57:20:75:8A:EA:75:00:05
X509v3 Authority Key Identifier:
keyid:BE:09:E4:5A:FC:06:83:96:31:49:07:F7:57:20:75:8A:EA:75:00:05
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha1WithRSAEncryption
52:d4:84:a9:d2:77:e9:7e:12:0f:e1:ec:01:66:7b:12:ee:23:
9e:33:aa:ea:c0:a4:f2:e6:90:48:e5:35:7e:bf:80:05:82:31:
fc:0b:89:ef:b3:af:c8:c8:f5:6e:21:0e:ed:84:3e:b7:47:71:
17:9b:a9:01:e6:f8:7b:8b:62:11:d7:52:dd:78:27:b4:66:e0:
ea:31:1f:8f:2c:b1:7e:c6:5f:4d:5d:ce:ce:53:f0:dd:d5:03:
f2:91:c0:f1:e8:f7:89:24:91:76:18:b2:c2:b1:d1:40:fd:5f:
10:06:61:71:86:bd:c8:49:64:18:99:6c:1f:f0:14:4e:56:ef:
db:7e:80:93:25:2f:a9:ff:7d:d9:02:51:b3:0d:53:60:16:14:
0e:33:8d:b7:58:f1:89:6d:7f:e1:22:9c:58:df:fd:32:50:a9:
5c:b0:93:a8:dc:60:50:75:ee:20:d8:b5:bd:52:38:82:c8:e4:
42:0b:e8:30:37:4b:ec:17:59:f2:4b:cc:87:f0:a3:a9:81:e7:
82:ac:2b:b8:04:3d:48:f4:59:01:fa:7a:dd:d1:f0:5e:c8:b8:
1e:f9:2a:b1:57:70:e1:39:23:11:83:22:d8:5b:81:09:4b:eb:
ec:4c:30:99:4d:75:72:fb:f3:84:e5:d4:c7:3a:67:11:e8:00:
5e:c0:d5:c6
-----BEGIN CERTIFICATE-----
MIIDnzCCAoegAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJNTTEL
MAkGA1UECAwCTU0xDDAKBgNVBAoMA01QVTEMMAoGA1UECwwDTVBVMREwDwYDVQQD
DAh1YXRfdGVzdDEfMB0GCSqGSIb3DQEJARYQdWF0X3Rlc3RAbXB1LmNvbTAeFw0y
NDA4MjMwODU5NTNaFw0yNzA4MjMwODU5NTNaMGoxCzAJBgNVBAYTAk1NMQswCQYD
VQQIDAJNTTEMMAoGA1UECgwDTVBVMQwwCgYDVQQLDANNUFUxETAPBgNVBAMMCHVh
dF90ZXN0MR8wHQYJKoZIhvcNAQkBFhB1YXRfdGVzdEBtcHUuY29tMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnhwFBnMvyuRldNggsrrHMuFTTfTcJLIR
sz+n+WBVxcYhiJWK1QR8CvvOhcvAiiFte+3qy98APBGTRtKwgvGI7bNgV+fBbdgI
UmXzvrU/3XykjlbPV8IPWmgugQ1PBcJ/M8NN8VVephR8300VaGgvMmFuv7ybaGFV
iEHOhXgZOu5d4Hhn41n0GNCpmDZHzEFXcUcELTOZTelh+Hmr9agcY1NkPoitasNA
qvT+J0FfCRWQnbbmy2Fou93fKBxg/76+Lu9ZuuGfsmFenA/6vdgPjNxHivz5WycA
l6hPR4YmfLGpfCO/WHmXhcf4Fy77s52daLOpWYSvw2FID94h08czRQIDAQABo1Aw
TjAdBgNVHQ4EFgQUvgnkWvwGg5YxSQf3VyB1iup1AAUwHwYDVR0jBBgwFoAUvgnk
WvwGg5YxSQf3VyB1iup1AAUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
AQEAUtSEqdJ36X4SD+HsAWZ7Eu4jnjOq6sCk8uaQSOU1fr+ABYIx/AuJ77OvyMj1
biEO7YQ+t0dxF5upAeb4e4tiEddS3XgntGbg6jEfjyyxfsZfTV3OzlPw3dUD8pHA
8ej3iSSRdhiywrHRQP1fEAZhcYa9yElkGJlsH/AUTlbv236AkyUvqf992QJRsw1T
YBYUDjONt1jxiW1/4SKcWN/9MlCpXLCTqNxgUHXuINi1vVI4gsjkQgvoMDdL7BdZ
8kvMh/CjqYHngqwruAQ9SPRZAfp63dHwXsi4HvkqsVdw4TkjEYMi2FuBCUvr7Eww
mU11cvvzhOXUxzpnEegAXsDVxg==
-----END CERTIFICATE-----

View File

@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDnzCCAoegAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJNTTEL
MAkGA1UECAwCTU0xDDAKBgNVBAoMA01QVTEMMAoGA1UECwwDTVBVMREwDwYDVQQD
DAh1YXRfdGVzdDEfMB0GCSqGSIb3DQEJARYQdWF0X3Rlc3RAbXB1LmNvbTAeFw0y
NDA4MjMwODU5NTNaFw0yNzA4MjMwODU5NTNaMGoxCzAJBgNVBAYTAk1NMQswCQYD
VQQIDAJNTTEMMAoGA1UECgwDTVBVMQwwCgYDVQQLDANNUFUxETAPBgNVBAMMCHVh
dF90ZXN0MR8wHQYJKoZIhvcNAQkBFhB1YXRfdGVzdEBtcHUuY29tMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnhwFBnMvyuRldNggsrrHMuFTTfTcJLIR
sz+n+WBVxcYhiJWK1QR8CvvOhcvAiiFte+3qy98APBGTRtKwgvGI7bNgV+fBbdgI
UmXzvrU/3XykjlbPV8IPWmgugQ1PBcJ/M8NN8VVephR8300VaGgvMmFuv7ybaGFV
iEHOhXgZOu5d4Hhn41n0GNCpmDZHzEFXcUcELTOZTelh+Hmr9agcY1NkPoitasNA
qvT+J0FfCRWQnbbmy2Fou93fKBxg/76+Lu9ZuuGfsmFenA/6vdgPjNxHivz5WycA
l6hPR4YmfLGpfCO/WHmXhcf4Fy77s52daLOpWYSvw2FID94h08czRQIDAQABo1Aw
TjAdBgNVHQ4EFgQUvgnkWvwGg5YxSQf3VyB1iup1AAUwHwYDVR0jBBgwFoAUvgnk
WvwGg5YxSQf3VyB1iup1AAUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
AQEAUtSEqdJ36X4SD+HsAWZ7Eu4jnjOq6sCk8uaQSOU1fr+ABYIx/AuJ77OvyMj1
biEO7YQ+t0dxF5upAeb4e4tiEddS3XgntGbg6jEfjyyxfsZfTV3OzlPw3dUD8pHA
8ej3iSSRdhiywrHRQP1fEAZhcYa9yElkGJlsH/AUTlbv236AkyUvqf992QJRsw1T
YBYUDjONt1jxiW1/4SKcWN/9MlCpXLCTqNxgUHXuINi1vVI4gsjkQgvoMDdL7BdZ
8kvMh/CjqYHngqwruAQ9SPRZAfp63dHwXsi4HvkqsVdw4TkjEYMi2FuBCUvr7Eww
mU11cvvzhOXUxzpnEegAXsDVxg==
-----END CERTIFICATE-----

View File

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDnzCCAoegAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJNTTEL
MAkGA1UECAwCTU0xDDAKBgNVBAoMA01QVTEMMAoGA1UECwwDTVBVMREwDwYDVQQD
DAh1YXRfdGVzdDEfMB0GCSqGSIb3DQEJARYQdWF0X3Rlc3RAbXB1LmNvbTAeFw0y
NDA4MjMwODU5NTNaFw0yNzA4MjMwODU5NTNaMGoxCzAJBgNVBAYTAk1NMQswCQYD
VQQIDAJNTTEMMAoGA1UECgwDTVBVMQwwCgYDVQQLDANNUFUxETAPBgNVBAMMCHVh
dF90ZXN0MR8wHQYJKoZIhvcNAQkBFhB1YXRfdGVzdEBtcHUuY29tMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnhwFBnMvyuRldNggsrrHMuFTTfTcJLIR
sz+n+WBVxcYhiJWK1QR8CvvOhcvAiiFte+3qy98APBGTRtKwgvGI7bNgV+fBbdgI
UmXzvrU/3XykjlbPV8IPWmgugQ1PBcJ/M8NN8VVephR8300VaGgvMmFuv7ybaGFV
iEHOhXgZOu5d4Hhn41n0GNCpmDZHzEFXcUcELTOZTelh+Hmr9agcY1NkPoitasNA
qvT+J0FfCRWQnbbmy2Fou93fKBxg/76+Lu9ZuuGfsmFenA/6vdgPjNxHivz5WycA
l6hPR4YmfLGpfCO/WHmXhcf4Fy77s52daLOpWYSvw2FID94h08czRQIDAQABo1Aw
TjAdBgNVHQ4EFgQUvgnkWvwGg5YxSQf3VyB1iup1AAUwHwYDVR0jBBgwFoAUvgnk
WvwGg5YxSQf3VyB1iup1AAUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
AQEAUtSEqdJ36X4SD+HsAWZ7Eu4jnjOq6sCk8uaQSOU1fr+ABYIx/AuJ77OvyMj1
biEO7YQ+t0dxF5upAeb4e4tiEddS3XgntGbg6jEfjyyxfsZfTV3OzlPw3dUD8pHA
8ej3iSSRdhiywrHRQP1fEAZhcYa9yElkGJlsH/AUTlbv236AkyUvqf992QJRsw1T
YBYUDjONt1jxiW1/4SKcWN/9MlCpXLCTqNxgUHXuINi1vVI4gsjkQgvoMDdL7BdZ
8kvMh/CjqYHngqwruAQ9SPRZAfp63dHwXsi4HvkqsVdw4TkjEYMi2FuBCUvr7Eww
mU11cvvzhOXUxzpnEegAXsDVxg==
-----END CERTIFICATE-----

View File

@ -1,7 +0,0 @@
package android.text;
public class TextUtils {
public static boolean isEmpty(CharSequence str) {
return str == null || str.length() == 0;
}
}

View File

@ -1,25 +0,0 @@
package android.util;
public class Log {
public static int d(String tag, String msg) {
System.out.println("DEBUG: " + tag + ": " + msg);
return 0;
}
public static int i(String tag, String msg) {
System.out.println("INFO: " + tag + ": " + msg);
return 0;
}
public static int w(String tag, String msg) {
System.out.println("WARN: " + tag + ": " + msg);
return 0;
}
public static int e(String tag, String msg) {
System.out.println("ERROR: " + tag + ": " + msg);
return 0;
}
// add other methods if required...
}