Safepoint Check EMV
This commit is contained in:
		
							parent
							
								
									2ea0792d28
								
							
						
					
					
						commit
						f48e3e64a4
					
				@ -98,47 +98,66 @@ public class CreditCardActivity extends AppCompatActivity {
 | 
			
		||||
                case EMV_FINAL_APP_SELECT:
 | 
			
		||||
                    importFinalAppSelectStatus(0);
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case EMV_APP_SELECT:
 | 
			
		||||
                    String[] candiNames = (String[]) msg.obj;
 | 
			
		||||
                    showAppSelectDialog(candiNames);
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case EMV_CONFIRM_CARD_NO:
 | 
			
		||||
                    // ✅ Tampilkan UI konfirmasi, JANGAN langsung import
 | 
			
		||||
                    showCardNumberConfirmation();
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case EMV_CERT_VERIFY:
 | 
			
		||||
                    // ✅ Tampilkan UI sertifikat, JANGAN langsung import
 | 
			
		||||
                    showCertificateVerification();
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case EMV_SHOW_PIN_PAD:
 | 
			
		||||
                    dismissLoadingDialog();
 | 
			
		||||
                    android.util.Log.d(TAG, "Initializing PIN pad...");
 | 
			
		||||
                    initPinPad();
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case EMV_ONLINE_PROCESS:
 | 
			
		||||
                    mockOnlineProcess();
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case EMV_SIGNATURE:
 | 
			
		||||
                    importSignatureStatus(0);
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case PIN_CLICK_PIN:
 | 
			
		||||
                    android.util.Log.d(TAG, "PIN input confirmed");
 | 
			
		||||
                    importPinInputStatus(0);
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case PIN_CLICK_CONFIRM:
 | 
			
		||||
                    android.util.Log.d(TAG, "PIN confirm without input (bypass)");
 | 
			
		||||
                    importPinInputStatus(2);
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case PIN_CLICK_CANCEL:
 | 
			
		||||
                    showToast("User cancelled PIN input");
 | 
			
		||||
                    showToast("PIN input cancelled by user");
 | 
			
		||||
                    importPinInputStatus(1);
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case PIN_ERROR:
 | 
			
		||||
                    showToast("PIN Error: " + msg.obj + " -- " + msg.arg1);
 | 
			
		||||
                    android.util.Log.e(TAG, "PIN Error: " + msg.obj + " -- " + msg.arg1);
 | 
			
		||||
                    showToast("PIN Error: " + msg.obj);
 | 
			
		||||
                    importPinInputStatus(3);
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case EMV_TRANS_FAIL:
 | 
			
		||||
                    resetUI();
 | 
			
		||||
                    showToast("Transaction failed: " + msg.obj + " -- " + msg.arg1);
 | 
			
		||||
                    break;
 | 
			
		||||
                    
 | 
			
		||||
                case EMV_TRANS_SUCCESS:
 | 
			
		||||
                    resetUI();
 | 
			
		||||
                    getTlvData(); // Get complete card data
 | 
			
		||||
                    showToast("Transaction successful: " + msg.obj + " -- " + msg.arg1);
 | 
			
		||||
                    showToast("Transaction successful!");
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -382,8 +401,12 @@ public class CreditCardActivity extends AppCompatActivity {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void switchCheckCard() {
 | 
			
		||||
        android.util.Log.d(TAG, "switchCheckCard called, checkingCard: " + checkingCard);
 | 
			
		||||
        android.util.Log.d(TAG, "switchCheckCard called, mProcessStep: " + mProcessStep);
 | 
			
		||||
        
 | 
			
		||||
        try {
 | 
			
		||||
            // Handle berbagai process steps
 | 
			
		||||
            if (mProcessStep == 0) {
 | 
			
		||||
                // Initial state - start/stop card scanning
 | 
			
		||||
                if (checkingCard) {
 | 
			
		||||
                    android.util.Log.d(TAG, "Stopping card check");
 | 
			
		||||
                    stopCardCheck();
 | 
			
		||||
@ -391,13 +414,50 @@ public class CreditCardActivity extends AppCompatActivity {
 | 
			
		||||
                    android.util.Log.d(TAG, "Starting card check");
 | 
			
		||||
                    startCardCheck();
 | 
			
		||||
                }
 | 
			
		||||
            } else if (mProcessStep == EMV_CONFIRM_CARD_NO) {
 | 
			
		||||
                // ✅ Handle card number confirmation
 | 
			
		||||
                android.util.Log.d(TAG, "User confirmed card number");
 | 
			
		||||
                showLoadingDialog("Processing card confirmation...");
 | 
			
		||||
                btnCheckCard.setText("Processing...");
 | 
			
		||||
                
 | 
			
		||||
                // ✅ Import card number status dan reset process step
 | 
			
		||||
                importCardNoStatus(0);
 | 
			
		||||
                
 | 
			
		||||
            } else if (mProcessStep == EMV_CERT_VERIFY) {
 | 
			
		||||
                // ✅ Handle certificate verification  
 | 
			
		||||
                android.util.Log.d(TAG, "User confirmed certificate");
 | 
			
		||||
                showLoadingDialog("Processing certificate...");
 | 
			
		||||
                btnCheckCard.setText("Processing...");
 | 
			
		||||
                
 | 
			
		||||
                // ✅ Import certificate status
 | 
			
		||||
                importCertStatus(0);
 | 
			
		||||
                
 | 
			
		||||
            } else {
 | 
			
		||||
                android.util.Log.w(TAG, "Unknown process step: " + mProcessStep);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            android.util.Log.e(TAG, "Error in switchCheckCard: " + e.getMessage());
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
            updateUI("Error: " + e.getMessage(), false);
 | 
			
		||||
            resetUI();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void showLoadingDialog(String message) {
 | 
			
		||||
        runOnUiThread(() -> {
 | 
			
		||||
            if (tvResult != null) {
 | 
			
		||||
                tvResult.setText(message + "...");
 | 
			
		||||
            }
 | 
			
		||||
            android.util.Log.d(TAG, "Loading: " + message);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void dismissLoadingDialog() {
 | 
			
		||||
        // Method ini bisa kosong atau implement actual dialog dismissal
 | 
			
		||||
        android.util.Log.d(TAG, "Loading dismissed");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void startCardCheck() {
 | 
			
		||||
        try {
 | 
			
		||||
            if (isEMVMode) {
 | 
			
		||||
@ -860,22 +920,38 @@ public class CreditCardActivity extends AppCompatActivity {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void showCardNumberConfirmation() {
 | 
			
		||||
        tvResult.setText("Card Number: " + maskCardNumber(mCardNo) + "\n\nPlease confirm card number");
 | 
			
		||||
        btnCheckCard.setText("Confirm");
 | 
			
		||||
        btnCheckCard.setOnClickListener(v -> {
 | 
			
		||||
            importCardNoStatus(0);
 | 
			
		||||
            btnCheckCard.setText("Processing...");
 | 
			
		||||
            btnCheckCard.setOnClickListener(null);
 | 
			
		||||
        runOnUiThread(() -> {
 | 
			
		||||
            dismissLoadingDialog(); // Pastikan loading dialog ditutup
 | 
			
		||||
            
 | 
			
		||||
            String displayText = "Card Number: " + maskCardNumber(mCardNo) + 
 | 
			
		||||
                            "\n\nPlease confirm this card number to continue";
 | 
			
		||||
            tvResult.setText(displayText);
 | 
			
		||||
            
 | 
			
		||||
            // ✅ HANYA ubah text button, JANGAN ubah listener
 | 
			
		||||
            btnCheckCard.setText("Confirm Card Number");
 | 
			
		||||
            
 | 
			
		||||
            // ✅ Set process step untuk onClick handler
 | 
			
		||||
            mProcessStep = EMV_CONFIRM_CARD_NO;
 | 
			
		||||
            
 | 
			
		||||
            android.util.Log.d(TAG, "Card number confirmation UI updated, waiting for user input");
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void showCertificateVerification() {
 | 
			
		||||
        tvResult.setText("Certificate Info: " + mCertInfo + "\n\nPlease confirm certificate");
 | 
			
		||||
        btnCheckCard.setText("Confirm");
 | 
			
		||||
        btnCheckCard.setOnClickListener(v -> {
 | 
			
		||||
            importCertStatus(0);
 | 
			
		||||
            btnCheckCard.setText("Processing...");
 | 
			
		||||
            btnCheckCard.setOnClickListener(null);
 | 
			
		||||
        runOnUiThread(() -> {
 | 
			
		||||
            dismissLoadingDialog();
 | 
			
		||||
            
 | 
			
		||||
            String displayText = "Certificate Information:\n" + mCertInfo + 
 | 
			
		||||
                            "\n\nPlease confirm certificate to continue";
 | 
			
		||||
            tvResult.setText(displayText);
 | 
			
		||||
            
 | 
			
		||||
            // ✅ HANYA ubah text button
 | 
			
		||||
            btnCheckCard.setText("Confirm Certificate");
 | 
			
		||||
            
 | 
			
		||||
            // ✅ Set process step
 | 
			
		||||
            mProcessStep = EMV_CERT_VERIFY;
 | 
			
		||||
            
 | 
			
		||||
            android.util.Log.d(TAG, "Certificate verification UI updated, waiting for user input");
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1437,61 +1513,115 @@ public class CreditCardActivity extends AppCompatActivity {
 | 
			
		||||
 | 
			
		||||
    // ====== PIN PAD METHODS ======
 | 
			
		||||
    private void initPinPad() {
 | 
			
		||||
        android.util.Log.e(TAG, "========== PIN PAD INITIALIZATION ==========");
 | 
			
		||||
        try {
 | 
			
		||||
            // Validate components
 | 
			
		||||
            if (mPinPadOptV2 == null) {
 | 
			
		||||
                throw new IllegalStateException("PIN Pad service not available");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Validate card number
 | 
			
		||||
            if (mCardNo == null || mCardNo.length() < 13) {
 | 
			
		||||
                throw new IllegalArgumentException("Invalid card number for PIN");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            PinPadConfigV2 pinPadConfig = new PinPadConfigV2();
 | 
			
		||||
            pinPadConfig.setPinPadType(0);
 | 
			
		||||
            pinPadConfig.setPinType(mPinType);
 | 
			
		||||
            pinPadConfig.setOrderNumKey(false);
 | 
			
		||||
            byte[] panBytes = mCardNo.substring(mCardNo.length() - 13, mCardNo.length() - 1).getBytes("US-ASCII");
 | 
			
		||||
            pinPadConfig.setPan(panBytes);
 | 
			
		||||
            pinPadConfig.setTimeout(60 * 1000);
 | 
			
		||||
            pinPadConfig.setPinKeyIndex(12);
 | 
			
		||||
            pinPadConfig.setMaxInput(12);
 | 
			
		||||
            pinPadConfig.setMinInput(0);
 | 
			
		||||
            pinPadConfig.setKeySystem(0);
 | 
			
		||||
            pinPadConfig.setAlgorithmType(0);
 | 
			
		||||
            
 | 
			
		||||
            // Use the correct PAN format (last 12 digits excluding check digit)
 | 
			
		||||
            String panForPin = mCardNo.substring(mCardNo.length() - 13, mCardNo.length() - 1);
 | 
			
		||||
            byte[] panBytes = panForPin.getBytes("US-ASCII");
 | 
			
		||||
            pinPadConfig.setPan(panBytes);
 | 
			
		||||
            
 | 
			
		||||
            pinPadConfig.setTimeout(60 * 1000);
 | 
			
		||||
            pinPadConfig.setPinKeyIndex(12); // Make sure this matches your key index
 | 
			
		||||
            pinPadConfig.setMaxInput(12);
 | 
			
		||||
            pinPadConfig.setMinInput(0); // Allow bypass
 | 
			
		||||
            pinPadConfig.setKeySystem(0); // 0 = international, 1 = domestic
 | 
			
		||||
            pinPadConfig.setAlgorithmType(0); // 0 = 3DES, 1 = SM4
 | 
			
		||||
            
 | 
			
		||||
            // Update UI
 | 
			
		||||
            runOnUiThread(() -> {
 | 
			
		||||
                updateUI("PIN Input Required\n\nPIN pad is ready\nPlease enter your PIN on the device", false);
 | 
			
		||||
                btnCheckCard.setText("PIN Pad Active");
 | 
			
		||||
                btnCheckCard.setEnabled(false);
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
            // Initialize PIN pad
 | 
			
		||||
            mPinPadOptV2.initPinPad(pinPadConfig, mPinPadListener);
 | 
			
		||||
            
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
            mHandler.obtainMessage(PIN_ERROR, Integer.MIN_VALUE, Integer.MIN_VALUE, "initPinPad() failure").sendToTarget();
 | 
			
		||||
            android.util.Log.e(TAG, "PIN pad initialization failed: " + e.getMessage());
 | 
			
		||||
            mHandler.obtainMessage(PIN_ERROR, -1, -1, 
 | 
			
		||||
                "PIN Error: " + e.getMessage()).sendToTarget();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final PinPadListenerV2 mPinPadListener = new PinPadListenerV2.Stub() {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onPinLength(int len) {
 | 
			
		||||
            android.util.Log.d(TAG, "onPinLength:" + len);
 | 
			
		||||
            mHandler.obtainMessage(PIN_CLICK_NUMBER, len).sendToTarget();
 | 
			
		||||
        public void onPinLength(int len) throws RemoteException {
 | 
			
		||||
            android.util.Log.d(TAG, "PIN input length: " + len);
 | 
			
		||||
            runOnUiThread(() -> {
 | 
			
		||||
                String dots = "";
 | 
			
		||||
                for (int i = 0; i < len; i++) {
 | 
			
		||||
                    dots += "• ";
 | 
			
		||||
                }
 | 
			
		||||
                tvResult.setText("PIN Input: " + dots + "\n\nEntering PIN... (" + len + " digits)");
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onConfirm(int i, byte[] pinBlock) {
 | 
			
		||||
        public void onConfirm(int i, byte[] pinBlock) throws RemoteException {
 | 
			
		||||
            android.util.Log.d(TAG, "PIN input confirmed");
 | 
			
		||||
            
 | 
			
		||||
            runOnUiThread(() -> {
 | 
			
		||||
                btnCheckCard.setEnabled(true);
 | 
			
		||||
                btnCheckCard.setText("Processing...");
 | 
			
		||||
                tvResult.setText("PIN confirmed, processing...");
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
            if (pinBlock != null) {
 | 
			
		||||
                String hexStr = ByteUtil.bytes2HexStr(pinBlock);
 | 
			
		||||
                android.util.Log.d(TAG, "onConfirm pin block:" + hexStr);
 | 
			
		||||
                android.util.Log.d(TAG, "PIN block received: " + hexStr);
 | 
			
		||||
                mHandler.obtainMessage(PIN_CLICK_PIN, pinBlock).sendToTarget();
 | 
			
		||||
            } else {
 | 
			
		||||
                android.util.Log.d(TAG, "PIN bypass confirmed");
 | 
			
		||||
                mHandler.obtainMessage(PIN_CLICK_CONFIRM).sendToTarget();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onCancel() {
 | 
			
		||||
            android.util.Log.d(TAG, "onCancel");
 | 
			
		||||
        public void onCancel() throws RemoteException {
 | 
			
		||||
            android.util.Log.d(TAG, "PIN input cancelled by user");
 | 
			
		||||
            
 | 
			
		||||
            runOnUiThread(() -> {
 | 
			
		||||
                btnCheckCard.setEnabled(true);
 | 
			
		||||
                btnCheckCard.setText("Start Scanning");
 | 
			
		||||
                tvResult.setText("PIN input cancelled");
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
            mHandler.obtainMessage(PIN_CLICK_CANCEL).sendToTarget();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onError(int code) {
 | 
			
		||||
            android.util.Log.e(TAG, "onError:" + code);
 | 
			
		||||
        public void onError(int code) throws RemoteException {
 | 
			
		||||
            android.util.Log.e(TAG, "PIN pad error: " + code);
 | 
			
		||||
            String msg = AidlErrorCodeV2.valueOf(code).getMsg();
 | 
			
		||||
            
 | 
			
		||||
            runOnUiThread(() -> {
 | 
			
		||||
                btnCheckCard.setEnabled(true);
 | 
			
		||||
                btnCheckCard.setText("Start Scanning");
 | 
			
		||||
                tvResult.setText("PIN error: " + msg);
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
            mHandler.obtainMessage(PIN_ERROR, code, code, msg).sendToTarget();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onHover(int event, byte[] data) throws RemoteException {
 | 
			
		||||
            android.util.Log.d(TAG, "onHover(), event:" + event + ", data:" + ByteUtil.bytes2HexStr(data));
 | 
			
		||||
            android.util.Log.d(TAG, "PIN pad hover event: " + event);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -1543,9 +1673,12 @@ public class CreditCardActivity extends AppCompatActivity {
 | 
			
		||||
 | 
			
		||||
    private void resetUI() {
 | 
			
		||||
        runOnUiThread(() -> {
 | 
			
		||||
            mProcessStep = 0;
 | 
			
		||||
            mProcessStep = 0;  // ✅ Reset process step ke initial state
 | 
			
		||||
            btnCheckCard.setText("Start Scanning");
 | 
			
		||||
            
 | 
			
		||||
            // ✅ Reset click listener ke original method
 | 
			
		||||
            btnCheckCard.setOnClickListener(v -> switchCheckCard());
 | 
			
		||||
            
 | 
			
		||||
            dismissAppSelectDialog();
 | 
			
		||||
            updateModeDisplay();
 | 
			
		||||
            
 | 
			
		||||
@ -1556,6 +1689,8 @@ public class CreditCardActivity extends AppCompatActivity {
 | 
			
		||||
            if (btnClearData != null) {
 | 
			
		||||
                btnClearData.setVisibility(android.view.View.GONE);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            android.util.Log.d(TAG, "UI reset to initial state");
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user