From e60985b2ec99f1696a82b3b1a3d51fbef56cf73c Mon Sep 17 00:00:00 2001 From: kizzy Date: Thu, 12 Mar 2026 15:23:45 +0700 Subject: [PATCH] fixed for pinpad retry --- .../kbz/ui/core_ui/CardWaitingFragment.java | 2 +- .../ui/core_ui/EmvTransactionFragment.java | 2 +- .../baselib/emv/EmvParamHelper.java | 1 + .../baselib/viewModel/EmvBaseViewModel.java | 344 +++++++----------- .../paylibs/utils/iso_utils/FieldUtils.java | 3 +- 5 files changed, 145 insertions(+), 207 deletions(-) diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_ui/CardWaitingFragment.java b/app/src/main/java/com/utsmm/kbz/ui/core_ui/CardWaitingFragment.java index d2eb012..c8a9668 100644 --- a/app/src/main/java/com/utsmm/kbz/ui/core_ui/CardWaitingFragment.java +++ b/app/src/main/java/com/utsmm/kbz/ui/core_ui/CardWaitingFragment.java @@ -290,7 +290,7 @@ public class CardWaitingFragment extends DataBindingFragment implements DataBind } else if (isFallback && cardType == CardTypeX.MAG) { /* do fallback transactions */ - sharedViewModel.isEmv.setValue(false); + sharedViewModel.isEmv.postValue(false); cardReadViewModel.setCardTransactionType(CardTransactionType.FALLBACK); } else if (cardType == CardTypeX.IC || cardType == CardTypeX.NFC) { diff --git a/app/src/main/java/com/utsmm/kbz/ui/core_ui/EmvTransactionFragment.java b/app/src/main/java/com/utsmm/kbz/ui/core_ui/EmvTransactionFragment.java index 693cc73..575d1ba 100644 --- a/app/src/main/java/com/utsmm/kbz/ui/core_ui/EmvTransactionFragment.java +++ b/app/src/main/java/com/utsmm/kbz/ui/core_ui/EmvTransactionFragment.java @@ -244,7 +244,7 @@ public class EmvTransactionFragment extends DataBindingFragment { isCardTaped("Please try again",new CardDetectCallback() { @Override public void onComplete() { - sharedViewModel.setIsSeePhone(true); + sharedViewModel.setIsSeePhone(false); navigateToCheckCard(); } }); diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamHelper.java b/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamHelper.java index 02ad555..a31d8af 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamHelper.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/emv/EmvParamHelper.java @@ -413,6 +413,7 @@ public class EmvParamHelper { aidV2.setTransType("FF"); aidV2.setOnlinePinCap(1); aidV2.setAsi(1); + aidV2.setThreshold(99); if (!(contactAid.getCvmLimit() < 0)) { aidV2.setContactlessCvmLimit(contactAid.getCvmLimit()); diff --git a/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java b/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java index 3055774..452797c 100644 --- a/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java +++ b/baselib/src/main/java/com/utsmyanmar/baselib/viewModel/EmvBaseViewModel.java @@ -6,6 +6,7 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.util.Log; +import android.view.View; import android.view.ViewTreeObserver; import androidx.annotation.NonNull; @@ -260,7 +261,8 @@ public abstract class EmvBaseViewModel extends BaseViewModel { unionPayTransDataEntity.setSupportCDCVM(true); //if support QPS, please enable below lines unionPayTransDataEntity.setSupportContactlessQps(true); - unionPayTransDataEntity.setContactlessQpsLimit("000090000000"); + unionPayTransDataEntity.setContactlessQpsLimit("000000030000"); + transData.setUnionPayTransDataEntity(unionPayTransDataEntity); @@ -425,213 +427,142 @@ public abstract class EmvBaseViewModel extends BaseViewModel { initKeyboard(isOnlinePin == 1); } - - private void initKeyboard(boolean isOnlinePin) { - - LogUtil.d(TAG,"init keyboard!"); + LogUtil.d(TAG, "init keyboard!"); pinPadVisibility.setValue(0); - LogUtil.d(TAG,"pin pad is visible now!"); - customPinPadKeyboard.getViewTreeObserver().addOnGlobalLayoutListener( - new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - customPinPadKeyboard.getViewTreeObserver().removeOnGlobalLayoutListener(this); + LogUtil.d(TAG, "pin pad is visible now!"); - LogUtil.d(TAG,"inside the global layout!"); - PinpadLayoutEntity pinpadLayout = new PinpadLayoutEntity(); - int[] location = new int[2]; - Rect r; - customPinPadKeyboard.getKey_1().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_1().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_1().getHeight() + r.top; - pinpadLayout.setKey1(r); - - customPinPadKeyboard.getKey_2().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_2().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_2().getHeight() + r.top; - pinpadLayout.setKey2(r); - - customPinPadKeyboard.getKey_3().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_3().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_3().getHeight() + r.top; - pinpadLayout.setKey3(r); - - customPinPadKeyboard.getKey_4().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_4().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_4().getHeight() + r.top; - pinpadLayout.setKey4(r); - - customPinPadKeyboard.getKey_5().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_5().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_5().getHeight() + r.top; - pinpadLayout.setKey5(r); - - customPinPadKeyboard.getKey_6().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_6().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_6().getHeight() + r.top; - pinpadLayout.setKey6(r); - - customPinPadKeyboard.getKey_7().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_7().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_7().getHeight() + r.top; - pinpadLayout.setKey7(r); - - customPinPadKeyboard.getKey_8().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_8().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_8().getHeight() + r.top; - pinpadLayout.setKey8(r); - - customPinPadKeyboard.getKey_9().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_9().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_9().getHeight() + r.top; - pinpadLayout.setKey9(r); - - customPinPadKeyboard.getKey_0().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_0().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_0().getHeight() + r.top; - pinpadLayout.setKey10(r); - - customPinPadKeyboard.getKey_cancel().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_cancel().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_cancel().getHeight() + r.top; - pinpadLayout.setKeyCancel(r); - - customPinPadKeyboard.getKey_clear().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_clear().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_clear().getHeight() + r.top; - pinpadLayout.setKeyClear(r); - - customPinPadKeyboard.getKey_ok().getLocationOnScreen(location); - r = new Rect(); - r.left = location[0]; - r.top = location[1]; - r.right = customPinPadKeyboard.getKey_ok().getWidth() + r.left; - r.bottom = customPinPadKeyboard.getKey_ok().getHeight() + r.top; - pinpadLayout.setKeyConfirm(r); - - - byte[] number = pinPad.setPinpadLayout(pinpadLayout); - - - OnPinPadInputListener pinPadInputListener = new OnPinPadInputListener() { - @Override - public void onInputResult(final int retCode, final byte[] data) { - if (retCode == SdkResult.Success) { - LogUtil.d(TAG, "Success"); - if(isOnlinePin) { - mPayDetail.setPINCipher(ByteUtil.bytes2HexStr(data)); - } - mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget(); - } else if (retCode == SdkResult.Fail) { - LogUtil.d(TAG, "Failure"); - } else if (retCode == SdkResult.PinPad_Input_Cancel) { - LogUtil.d(TAG, "Cancel"); - mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget(); - } else if (retCode == SdkResult.PinPad_Input_Timeout) { - mHandler.obtainMessage(PIN_TIME_OUT,-7009).sendToTarget(); - } else if (retCode == SdkResult.PinPad_No_Pin_Input) { - mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget(); - } else { - mHandler.obtainMessage(PIN_ERROR).sendToTarget(); - } - - LogUtil.d(TAG, "RetCode:" + retCode); - LogUtil.d(TAG, "data bytes:" + ByteUtil.bytes2HexStr(data)); - } - - @Override - public void onSendKey(byte keyCode) { - increaseCount(); - if (keyCode == PinPadKeyCode.KEYCODE_CLEAR) { - LogUtil.d(TAG, "on clear"); - mHandler.obtainMessage(PIN_CLICK_CLEAR).sendToTarget(); - } else if (keyCode == PinPadKeyCode.KEYCODE_CANCEL) { - LogUtil.d(TAG, "on click cancel"); - mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget(); - } else if (keyCode == PinPadKeyCode.KEYCODE_CONFIRM) { - LogUtil.d(TAG, "on click confirm"); - mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget(); - } else { - LogUtil.d(TAG, "on click number"); - mHandler.obtainMessage(PIN_CLICK_NUMBER, pinEnterCount, 0).sendToTarget(); - } - LogUtil.d(TAG, "SendKey: " + ByteUtil.byte2HexStr(keyCode)); - } - }; - - if (number != null) { - customPinPadKeyboard.setKeyBoard(number); -// customPinPadKeyboard.setKeyBoard(ByteUtil.bytes2HexStr(number)); - - LogUtil.d(TAG, "PinPad: " + ByteUtil.bytes2HexStr(number)); - int[] supperLen = new int[]{0x00, 0x04, 0x06, 0x0c}; - - - pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT); - pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED); -// pinPad.setAlgorithmMode(AlgorithmModeEnum.DES); - - - if(cardNo == null){ - cardNo = emvHandler.getEmvCardDataInfo().getCardNo(); - } - int length = cardNo.length(); - byte[] panBytes = cardNo.substring( length- 13).getBytes(StandardCharsets.US_ASCII); - LogUtil.d(TAG,"card num :"+cardNo); - LogUtil.d(TAG,"Is Online Pin:"+isOnlinePin); -// pinPad.inputOnlinePin(supperLen, 60, pan, 0, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener); - if (isOnlinePin) { - - pinPad.inputOnlinePin(supperLen, 60, panBytes, pinIndex, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener); - - } else { - mPayDetail.transCVM = TransCVM.OFFLINE_PIN; - pinPad.inputOfflinePin(supperLen, 60, pinPadInputListener); + // Check if the view is already laid out + if (customPinPadKeyboard.getWidth() > 0 && customPinPadKeyboard.getHeight() > 0) { + // View already laid out — call setup directly + setupPinPadLayout(isOnlinePin); + } else { + // View not yet laid out — wait for layout + customPinPadKeyboard.getViewTreeObserver().addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (customPinPadKeyboard.getWidth() > 0 && customPinPadKeyboard.getHeight() > 0) { + customPinPadKeyboard.getViewTreeObserver().removeOnGlobalLayoutListener(this); + setupPinPadLayout(isOnlinePin); } } } + ); + } + } + private void setupPinPadLayout(boolean isOnlinePin) { + LogUtil.d(TAG, "inside the global layout!"); + PinpadLayoutEntity pinpadLayout = new PinpadLayoutEntity(); + + // Helper to avoid repetition + pinpadLayout.setKey1(getRectForView(customPinPadKeyboard.getKey_1())); + pinpadLayout.setKey2(getRectForView(customPinPadKeyboard.getKey_2())); + pinpadLayout.setKey3(getRectForView(customPinPadKeyboard.getKey_3())); + pinpadLayout.setKey4(getRectForView(customPinPadKeyboard.getKey_4())); + pinpadLayout.setKey5(getRectForView(customPinPadKeyboard.getKey_5())); + pinpadLayout.setKey6(getRectForView(customPinPadKeyboard.getKey_6())); + pinpadLayout.setKey7(getRectForView(customPinPadKeyboard.getKey_7())); + pinpadLayout.setKey8(getRectForView(customPinPadKeyboard.getKey_8())); + pinpadLayout.setKey9(getRectForView(customPinPadKeyboard.getKey_9())); + pinpadLayout.setKey10(getRectForView(customPinPadKeyboard.getKey_0())); + pinpadLayout.setKeyCancel(getRectForView(customPinPadKeyboard.getKey_cancel())); + pinpadLayout.setKeyClear(getRectForView(customPinPadKeyboard.getKey_clear())); + pinpadLayout.setKeyConfirm(getRectForView(customPinPadKeyboard.getKey_ok())); + + + byte[] number = pinPad.setPinpadLayout(pinpadLayout); + + + OnPinPadInputListener pinPadInputListener = new OnPinPadInputListener() { + @Override + public void onInputResult(final int retCode, final byte[] data) { + if (retCode == SdkResult.Success) { + LogUtil.d(TAG, "Success"); + if(isOnlinePin) { + mPayDetail.setPINCipher(ByteUtil.bytes2HexStr(data)); + } + mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget(); + } else if (retCode == SdkResult.Fail) { + LogUtil.d(TAG, "Failure"); + } else if (retCode == SdkResult.PinPad_Input_Cancel) { + LogUtil.d(TAG, "Cancel"); + mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget(); + } else if (retCode == SdkResult.PinPad_Input_Timeout) { + mHandler.obtainMessage(PIN_TIME_OUT,-7009).sendToTarget(); + } else if (retCode == SdkResult.PinPad_No_Pin_Input) { + mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget(); + } else { + mHandler.obtainMessage(PIN_ERROR).sendToTarget(); } - ); + + LogUtil.d(TAG, "RetCode:" + retCode); + LogUtil.d(TAG, "data bytes:" + ByteUtil.bytes2HexStr(data)); + } + + @Override + public void onSendKey(byte keyCode) { + increaseCount(); + if (keyCode == PinPadKeyCode.KEYCODE_CLEAR) { + LogUtil.d(TAG, "on clear"); + mHandler.obtainMessage(PIN_CLICK_CLEAR).sendToTarget(); + } else if (keyCode == PinPadKeyCode.KEYCODE_CANCEL) { + LogUtil.d(TAG, "on click cancel"); + mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget(); + } else if (keyCode == PinPadKeyCode.KEYCODE_CONFIRM) { + LogUtil.d(TAG, "on click confirm"); + mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget(); + } else { + LogUtil.d(TAG, "on click number"); + mHandler.obtainMessage(PIN_CLICK_NUMBER, pinEnterCount, 0).sendToTarget(); + } + LogUtil.d(TAG, "SendKey: " + ByteUtil.byte2HexStr(keyCode)); + } + }; + + if (number != null) { + customPinPadKeyboard.setKeyBoard(number); +// customPinPadKeyboard.setKeyBoard(ByteUtil.bytes2HexStr(number)); + + LogUtil.d(TAG, "PinPad: " + ByteUtil.bytes2HexStr(number)); + int[] supperLen = new int[]{0x00, 0x04, 0x06, 0x0c}; + pinPad.setPinKeyboardViewMode(PinKeyboardViewModeEnum.DEFAULT); + pinPad.setPinKeyboardMode(PinKeyboardModeEnum.FIXED); +// pinPad.setAlgorithmMode(AlgorithmModeEnum.DES); + + + if(cardNo == null){ + cardNo = emvHandler.getEmvCardDataInfo().getCardNo(); + } + int length = cardNo.length(); + byte[] panBytes = cardNo.substring( length- 13).getBytes(StandardCharsets.US_ASCII); + LogUtil.d(TAG,"card num :"+cardNo); + LogUtil.d(TAG,"Is Online Pin:"+isOnlinePin); +// pinPad.inputOnlinePin(supperLen, 60, pan, 0, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener); + if (isOnlinePin) { + + pinPad.inputOnlinePin(supperLen, 60, panBytes, pinIndex, PinAlgorithmModeEnum.ISO9564FMT0, pinPadInputListener); + + } else { + mPayDetail.transCVM = TransCVM.OFFLINE_PIN; + pinPad.inputOfflinePin(supperLen, 60, pinPadInputListener); + } + } + } + + // Reusable rect helper + private Rect getRectForView(View view) { + int[] location = new int[2]; + view.getLocationOnScreen(location); + Rect r = new Rect(); + r.left = location[0]; + r.top = location[1]; + r.right = view.getWidth() + r.left; + r.bottom = view.getHeight() + r.top; + return r; } private void increaseCount() { @@ -676,11 +607,11 @@ 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}, ByteUtil.hexStr2Bytes(terminalCapability)); - emvHandler.setTlv(new byte[]{(byte) 0xE0, (byte) 0x1D}, ByteUtils.hexString2ByteArray("6C00800000000000"));//terminal risk - - } +// if (ByteUtils.byteArray2HexString(aid).toUpperCase().contains("A000000004")) { +// emvHandler.setTlv(new byte[]{(byte) 0x9F, (byte) 0x33}, ByteUtil.hexStr2Bytes(terminalCapability)); +// emvHandler.setTlv(new byte[]{(byte) 0xE0, (byte) 0x1D}, ByteUtils.hexString2ByteArray("6C00800000000000"));//terminal risk +// +// } } emvHandler.onSetTransInitBeforeGPOResponse(true); @@ -743,7 +674,12 @@ public abstract class EmvBaseViewModel extends BaseViewModel { @Override public void onPrompt(PromptEnum promptEnum) { LogUtil.d(TAG, "onPrompt->" + promptEnum); - emvHandler.onSetPromptResponse(true); + if( promptEnum == PromptEnum.OFFLINE_PIN_INCORRECT_TRY_AGAIN) { + emvHandler.onSetPromptResponse(false); + } else { + emvHandler.onSetPromptResponse(true); + } + } @Override diff --git a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/FieldUtils.java b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/FieldUtils.java index 41f7bb0..770c007 100644 --- a/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/FieldUtils.java +++ b/paylibs/src/main/java/com/utsmyanmar/paylibs/utils/iso_utils/FieldUtils.java @@ -341,7 +341,8 @@ public class FieldUtils { } else if (BaseCardType.IC.getValue() == cardType) { // IC value = "05"; } else if (FALLBACK == cardType){ // Fallback - value = "08"; + value = "72"; +// value = "08"; } else { // Hand-in card number value = "01"; }