Compare commits

..

10 Commits

Author SHA1 Message Date
moon
a83e98e3c8 Merge branch 'ecr' into new_history 2026-03-06 23:43:09 +06:30
moon
5ee9745762 server address 2026-03-06 23:42:24 +06:30
moon
83bc15a7ab pinpad fix 2026-03-06 23:06:11 +06:30
80a1229d0f fixed for magstripe not allowed and 12 digit pin 2026-03-06 16:43:56 +07:00
e0906ab434 Merge remote-tracking branch 'origin/ecr' into ecr
# Conflicts:
#	baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java
2026-03-06 16:41:08 +07:00
620620e138 fixed for magstripe not allowed 2026-03-06 16:40:43 +07:00
moon
d8d1a5c1d5 amount fix 2026-03-06 15:25:14 +06:30
89252a6732 fixed com2 2026-03-06 11:21:54 +07:00
900ca456dd fixed for key issues 2026-03-05 16:40:25 +07:00
9e2dd24f3d fixed for DE 52 2026-03-05 14:16:54 +07:00
14 changed files with 129 additions and 120 deletions

View File

@ -157,10 +157,10 @@ public class MainActivity extends AppCompatActivity implements
}
private void initKey(){
SystemParamsOperation.getInstance().setTmsAddress("https://api-tms-uat.kbzbank.com:8443/sirius");
// SystemParamsOperation.getInstance().setTmsAddress("https://sirius-nest.utsmyanmar.com");
SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms-uat.kbzbank.com:8443/receipt");
// SystemParamsOperation.getInstance().setEReceiptAddress("http://receipt-nest.utsmyanmar.com");
// SystemParamsOperation.getInstance().setTmsAddress("https://api-tms-uat.kbzbank.com:8443/sirius");
SystemParamsOperation.getInstance().setTmsAddress("https://sirius-nest.utsmyanmar.com");
// SystemParamsOperation.getInstance().setEReceiptAddress("https://api-tms-uat.kbzbank.com:8443/receipt");
SystemParamsOperation.getInstance().setEReceiptAddress("https://receipt-nest.utsmyanmar.com");
PinPad pinPad = MyApplication.getInstance().deviceEngine.getPinPad();
byte[] encryptedPIK = SystemParamsOperation.getInstance().getPIK();

View File

@ -448,7 +448,7 @@ public class AutoSettleService extends Service {
stopSelf();
}
}
@Override
public void onCreate() {
super.onCreate();

View File

@ -151,6 +151,9 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind
}else if(sharedViewModel.getIsSeePhone().getValue() != null && sharedViewModel.getIsSeePhone().getValue()) {
cardReadViewModel.setCheckCardAlertMsg("Please Tap!",false);
setupCardReadProcess(true);
} else if(sharedViewModel.getIsCardAppBlock().getValue() != null && sharedViewModel.getIsCardAppBlock().getValue()) {
cardReadViewModel.setCheckCardAlertMsg("Magstripe not allowed!",false);
setupCardReadProcess(true);
} else {
setupCardReadProcess(false);
}

View File

@ -249,7 +249,25 @@ public class EmvTransactionFragment extends DataBindingFragment {
}
});
}
break;
case CARD_APP_BLOCKED:
if(cardReadViewModel.cardTypeData.getValue()!= null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.IC.value) {
isCardInserted(new CardDetectCallback() {
@Override
public void onComplete() {
sharedViewModel.setIsCardAppBlock(true);
navigateToCheckCard();
}
});
} else if(cardReadViewModel.cardTypeData.getValue() != null && cardReadViewModel.cardTypeData.getValue() == CardTypeX.NFC.value) {
isCardTaped("Please try again",new CardDetectCallback() {
@Override
public void onComplete() {
sharedViewModel.setIsCardAppBlock(true);
navigateToCheckCard();
}
});
}
// sharedViewModel.set_errorFragmentMsg("Interface not found!");
// navigateToError();
break;

View File

@ -164,6 +164,9 @@ public class EmvTransactionProcessViewModel extends EmvBaseViewModel implements
case EMV_TRY_AGAIN:
emvResultStatus.postValue(EmvResultStatus.READ_CARD_RETRY);
break;
case EMV_CARD_APP_BLOCK:
emvResultStatus.postValue(EmvResultStatus.CARD_APP_BLOCKED);
break;
case EMV_CONFIRM_CODE_VERIFY:
emvResultStatus.postValue(EmvResultStatus.CONFIRM_CODE_VERIFY);
break;

View File

@ -13,112 +13,109 @@ import java.util.Objects;
public class InputAmountViewModel extends ViewModel {
private static final String TAG = InputAmountViewModel.class.getSimpleName();
public MutableLiveData<String> inputAmountView = new MutableLiveData<>();
public SingleLiveEvent<String> invalidAmountMsg = new SingleLiveEvent<>();
public SingleLiveEvent<String> availableAmount = new SingleLiveEvent<>();
private static final int MAX_INT_DIGITS = 10;
private static final int MAX_DECIMAL_DIGITS = 2;
public InputAmountViewModel() {
inputAmountView.setValue("0");
}
private int countDecimalDigits(double number) {
String numberStr = Double.toString(number);
int decimalIndex = numberStr.indexOf('.');
return decimalIndex >= 0 ? numberStr.length() - decimalIndex - 1 : 0;
private String formatInteger(String value) {
if (TextUtils.isEmpty(value)) return "0";
double amt = Double.parseDouble(value);
DecimalFormat formatter = new DecimalFormat("#,###");
return formatter.format(amt);
}
public NumberKeyboard.KeyClickCallback onKeyClick() {
return new NumberKeyboard.KeyClickCallback() {
@Override
public void onNumClick(int keyNum) {
if (inputAmountView.getValue().length() == 15) {
return;
}
String current = inputAmountView.getValue();
if (current == null) return;
if (TextUtils.equals(inputAmountView.getValue(), "0")) {
inputAmountView.setValue(keyNum + "");
} else if (inputAmountView.getValue().contains(".")) {
StringBuilder inputAmount = new StringBuilder();
inputAmount.append(inputAmountView.getValue());
String raw = current.replace(",", "");
int dotIndex = inputAmount.indexOf(".");
if (raw.contains(".")) {
if(inputAmount.substring(dotIndex).length() > 0 && inputAmount.substring(dotIndex+1).length() == 2) {
String[] parts = raw.split("\\.");
String intPart = parts[0];
String decimalPart = parts.length > 1 ? parts[1] : "";
if (decimalPart.length() >= MAX_DECIMAL_DIGITS) {
return;
}
if (inputAmountView.getValue().contains(",")) {
inputAmountView.setValue(inputAmountView.getValue().replace(",", ""));
}
double amt = Double.parseDouble(inputAmountView.getValue());
if (countDecimalDigits(amt) < 2) {
inputAmountView.setValue(inputAmountView.getValue() + keyNum);
}
raw = raw + keyNum;
} else {
if (inputAmountView.getValue().contains(",")) {
inputAmountView.setValue(inputAmountView.getValue().replace(",", ""));
if (raw.length() >= MAX_INT_DIGITS) {
return;
}
inputAmountView.setValue(inputAmountView.getValue() + keyNum);
double amt = Double.parseDouble(inputAmountView.getValue());
DecimalFormat formatter = new DecimalFormat("#,###");
inputAmountView.setValue(formatter.format(amt));
if (TextUtils.equals(raw, "0")) {
raw = String.valueOf(keyNum);
} else {
raw = raw + keyNum;
}
}
if (raw.contains(".")) {
String[] parts = raw.split("\\.");
String formattedInt = formatInteger(parts[0]);
String decimal = parts.length > 1 ? parts[1] : "";
inputAmountView.setValue(formattedInt + "." + decimal);
} else {
inputAmountView.setValue(formatInteger(raw));
}
}
@Override
public void onDelClick() {
if (Objects.requireNonNull(inputAmountView.getValue()).contains(".")) {
return;
}
if (inputAmountView.getValue().length() == 15) {
return;
}
if (TextUtils.equals(inputAmountView.getValue(), "0")) {
String current = inputAmountView.getValue();
if (current == null) return;
if (current.contains(".")) return;
if (TextUtils.equals(current, "0")) {
inputAmountView.setValue("0.");
} else {
inputAmountView.setValue(inputAmountView.getValue() + ".");
inputAmountView.setValue(current + ".");
}
}
@Override
public void onCleanClick() {
if (inputAmountView.getValue() != null) {
if (inputAmountView.getValue().contains(".")) {
StringBuilder inputAmount = new StringBuilder();
inputAmount.append(inputAmountView.getValue());
inputAmount.deleteCharAt(inputAmount.length() - 1);
inputAmountView.setValue(inputAmount.toString());
} else if (!inputAmountView.getValue().equals("0")) {
String currentValue = inputAmountView.getValue();
String rawNumber = currentValue.replace(",", "");
String current = inputAmountView.getValue();
if (current == null) return;
if (rawNumber.length() > 1) {
rawNumber = rawNumber.substring(0, rawNumber.length() - 1);
String raw = current.replace(",", "");
double amt = Double.parseDouble(rawNumber);
DecimalFormat formatter = new DecimalFormat("#,###");
inputAmountView.setValue(formatter.format(amt));
} else {
inputAmountView.setValue("0");
}
}
if (raw.length() <= 1) {
inputAmountView.setValue("0");
return;
}
raw = raw.substring(0, raw.length() - 1);
if (raw.contains(".")) {
String[] parts = raw.split("\\.");
String formattedInt = formatInteger(parts[0]);
String decimal = parts.length > 1 ? parts[1] : "";
inputAmountView.setValue(formattedInt + "." + decimal);
} else {
inputAmountView.setValue(formatInteger(raw));
}
}
};
}
}
}

View File

@ -164,6 +164,7 @@ public class SharedViewModel extends ViewModel {
private SingleLiveEvent<Boolean> isFallback = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isSeePhone = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> isCardAppBlock = new SingleLiveEvent<>();
private SingleLiveEvent<Boolean> _isCardDataExist = new SingleLiveEvent<>();
@ -233,6 +234,10 @@ public class SharedViewModel extends ViewModel {
public SingleLiveEvent<Boolean> getIsFallback() { return isFallback;}
public void setIsCardAppBlock(boolean status) { isCardAppBlock.setValue(status);}
public SingleLiveEvent<Boolean> getIsCardAppBlock() {return isCardAppBlock;}
public void setIsSeePhone(boolean status) { isSeePhone.setValue(status);}
public SingleLiveEvent<Boolean> getIsSeePhone() { return isSeePhone;}

View File

@ -22,11 +22,13 @@ 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()); // KBZ UAT
// private static final byte[] main_key_data = ByteUtil.hexStr2Bytes("e121249099a677e8b7d4f6a9d49fe8d1".toUpperCase()); // MPU
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");

View File

@ -287,8 +287,8 @@ public class NetworkModule {
tmsAddress = getTMSUrlFromNative();
}
// String baseUrl = tmsAddress.trim() + "/api/v1/"; //for on prim
String baseUrl = tmsAddress.trim() + "/"; //for uat and prod
String baseUrl = tmsAddress.trim() + "/api/v1/"; //for on prim
// String baseUrl = tmsAddress.trim() + "/"; //for uat and prod
final Gson gson =
new GsonBuilder().create();

View File

@ -30,5 +30,6 @@ public enum EmvResultStatus {
CONFIRM_CODE_VERIFY,
MPU_CARD,
SEE_PHONE,
OTHER_INTERFACE
OTHER_INTERFACE,
CARD_APP_BLOCKED
}

View File

@ -153,6 +153,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
protected static final int EMV_ONLINE_PROCESS = 11;
protected static final int EMV_ERROR = 12;
protected static final int EMV_TRY_AGAIN = 13;
protected static final int EMV_CARD_APP_BLOCK = 23;
protected static final int EMV_CTLS_TRY_AGAIN = 13;
protected static final int EMV_CONFIRM_CODE_VERIFY = 14;
@ -599,7 +601,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
// customPinPadKeyboard.setKeyBoard(ByteUtil.bytes2HexStr(number));
LogUtil.d(TAG, "PinPad: " + ByteUtil.bytes2HexStr(number));
int[] supperLen = new int[]{0x00, 0x04, 0x06};
int[] supperLen = new int[]{0x00, 0x04, 0x06, 0x0c};
pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT);
@ -652,7 +654,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
byte[] aid = emvHandler.getTlv(new byte[]{0x4F}, EmvDataSourceEnum.FROM_KERNEL);
LogUtil.d(TAG, "onTransInitBeforeGPO :");
String terminalCapability = SystemParamsOperation.getInstance().getTerminalCapability();
LogUtil.d(TAG,"Terminal capability : " + terminalCapability );
LogUtil.d(TAG,"Terminal capability :"+terminalCapability);
// emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, new byte[]{(byte) 0xE0, (byte) 0x28, (byte) 0xC8});
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, ByteUtil.hexStr2Bytes(terminalCapability));
if (mPayDetail.getCardType() == CardTypeX.NFC.value) {
@ -675,8 +677,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
} else {
//contact terminal capability ; if different card brand(depend on aid) have different terminal capability
if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000004")) {
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, new byte[]{(byte) 0xE0, (byte) 0xF0, (byte) 0xC8});
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x1D}, ByteUtils.hexString2ByteArray("6C00800000000000"));//terminal risk
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, ByteUtil.hexStr2Bytes(terminalCapability));
emvHandler.setTlv(new byte[]{(byte) 0xE0, (byte) 0x1D}, ByteUtils.hexString2ByteArray("6C00800000000000"));//terminal risk
}
}
@ -826,6 +828,11 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
//union pay online contactless--application should go online
break;
case SdkResult.Emv_App_Block:
case SdkResult.Emv_Card_Block:
mHandler.sendEmptyMessage(EMV_CARD_APP_BLOCK);
break;
case SdkResult.Emv_Candidatelist_Empty:// Application have no aid list
case SdkResult.Emv_FallBack:// FallBack ,chip card reset failed
//fallback process
@ -1232,8 +1239,7 @@ public abstract class EmvBaseViewModel extends BaseViewModel {
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x1d}, ByteUtils.hexString2ByteArray("4C00800000000000"));
} else {
//set 9F1D terminal risk management - MasterCard. it should be same with the MTIP configuration for 9F1D
// emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x1d}, ByteUtils.hexString2ByteArray("6C00800000000000"));
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x1d}, ByteUtils.hexString2ByteArray("6C7A800000000000"));
emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x1d}, ByteUtils.hexString2ByteArray("6C00800000000000"));
}

View File

@ -10,8 +10,8 @@
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000040",
"tacDefault": "F45084800C",
"tacOnline": "F45084800C",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 75000,
@ -35,8 +35,8 @@
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000040",
"tacDefault": "F45084800C",
"tacOnline": "F45084800C",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 75000,
@ -49,7 +49,6 @@
"cateCode": "2701",
"currencyCode": "0104"
},
{
"aidEnable": true,
"aid": "A0000000041010C123456789",
@ -61,8 +60,8 @@
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000040",
"tacDefault": "F45084800C",
"tacOnline": "F45084800C",
"tacDefault": "D84000A800",
"tacOnline": "DC4004F800",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 75000,
@ -74,30 +73,5 @@
"ttq": "36804000",
"cateCode": "2701",
"currencyCode": "0104"
},
{
"aidEnable": true,
"aid": "A00000000430",
"cardLabel": "MASTERCARD",
"applicationVersion": "0002",
"emvDDOL": "9F3704",
"emvTDOL": "9F3704",
"partialAidSelection": false,
"targetPercent": "99",
"maxTargetPercent": "99",
"threshold": "00000040",
"tacDefault": "F45084800C",
"tacOnline": "F45084800C",
"tacDenial": "0000000000",
"floorLimit": "000000000000",
"cvmLimit": 75000,
"transLimit": "999999999999",
"transLimitCDV": "999999999999",
"terminalCapability": "E0F8C8",
"riskManageData": "6C7A800000000000",
"kernelType": "02",
"ttq": "36804000",
"cateCode": "2701",
"currencyCode": "0104"
}
]

View File

@ -42,10 +42,10 @@ public class SystemParamsSettings implements Serializable {
// private String tmsAddress = "https://tms.smile-mm.com";
// private String tmsAddress = "http://128.199.170.203";
// private String tmsAddress = "https://sirius-nest.utsmyanmar.com";
private String tmsAddress = "https://api-tms-uat.kbzbank.com:8443/sirius"; //for uat
// private String ereceiptAddress = "https://receipt-nest.utsmyanmar.com"; //for on prime
private String ereceiptAddress = "https://api-tms-uat.kbzbank.com:8443/receipt"; //for uat
private String tmsAddress = "https://sirius-nest.utsmyanmar.com";
// private String tmsAddress = "https://api-tms-uat.kbzbank.com:8443/sirius"; //for uat
private String ereceiptAddress = "https://receipt-nest.utsmyanmar.com"; //for on prime
// private String ereceiptAddress = "https://api-tms-uat.kbzbank.com:8443/receipt"; //for uat
private String binValues = "";

View File

@ -103,8 +103,8 @@ public class FieldConfig {
/* 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},
// /* FLD 52 */ {0, SDK_8583_LEN_BCD, 8, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, ' '},
/* FLD 52 */ {2, SDK_8583_LEN_ASC, 8, SDK_8583_DATA_BIT, SDK_8583_ALIGN_L, '0'},
// /* FLD 52 */ {0, SDK_8583_LEN_BCD, 8, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, 0},
/* FLD 53 */ {2, SDK_8583_LEN_ASC, 32, SDK_8583_DATA_BCD, SDK_8583_ALIGN_L, '0'},
/* FLD 54 */ {3, SDK_8583_LEN_BCD, 40, SDK_8583_DATA_ASC, SDK_8583_ALIGN_L, ' '},