Result Transaction dan QRIS
This commit is contained in:
		
							parent
							
								
									b66ef4bb00
								
							
						
					
					
						commit
						53964211c2
					
				@ -23,6 +23,8 @@ import java.net.HttpURLConnection;
 | 
				
			|||||||
import java.io.OutputStream;
 | 
					import java.io.OutputStream;
 | 
				
			||||||
import java.net.URL;
 | 
					import java.net.URL;
 | 
				
			||||||
import java.net.URI;
 | 
					import java.net.URI;
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.example.bdkipoc.cetakulang.ReprintActivity;
 | 
					import com.example.bdkipoc.cetakulang.ReprintActivity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -52,6 +54,28 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
    private LinearLayout emailButton;
 | 
					    private LinearLayout emailButton;
 | 
				
			||||||
    private Button finishButton;
 | 
					    private Button finishButton;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ✅ ENHANCED: Mapping dari technical issuer ke display name
 | 
				
			||||||
 | 
					    private static final Map<String, String> ISSUER_DISPLAY_MAP = new HashMap<String, String>() {{
 | 
				
			||||||
 | 
					        put("airpay shopee", "ShopeePay");
 | 
				
			||||||
 | 
					        put("shopeepay", "ShopeePay");
 | 
				
			||||||
 | 
					        put("shopee", "ShopeePay");
 | 
				
			||||||
 | 
					        put("linkaja", "LinkAja");
 | 
				
			||||||
 | 
					        put("link aja", "LinkAja");
 | 
				
			||||||
 | 
					        put("dana", "DANA");
 | 
				
			||||||
 | 
					        put("ovo", "OVO");
 | 
				
			||||||
 | 
					        put("gopay", "GoPay");
 | 
				
			||||||
 | 
					        put("jenius", "Jenius");
 | 
				
			||||||
 | 
					        put("sakuku", "Sakuku");
 | 
				
			||||||
 | 
					        put("bni", "BNI");
 | 
				
			||||||
 | 
					        put("bca", "BCA");
 | 
				
			||||||
 | 
					        put("mandiri", "Mandiri");
 | 
				
			||||||
 | 
					        put("bri", "BRI");
 | 
				
			||||||
 | 
					        put("cimb", "CIMB Niaga");
 | 
				
			||||||
 | 
					        put("permata", "Permata");
 | 
				
			||||||
 | 
					        put("maybank", "Maybank");
 | 
				
			||||||
 | 
					        put("qris", "QRIS");
 | 
				
			||||||
 | 
					    }};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    protected void onCreate(Bundle savedInstanceState) {
 | 
					    protected void onCreate(Bundle savedInstanceState) {
 | 
				
			||||||
        super.onCreate(savedInstanceState);
 | 
					        super.onCreate(savedInstanceState);
 | 
				
			||||||
@ -118,10 +142,27 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
        finishButton.setOnClickListener(v -> handleFinish());
 | 
					        finishButton.setOnClickListener(v -> handleFinish());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * ✅ ENHANCED: Load transaction data with support for both EMV/Card and QRIS
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void loadTransactionData() {
 | 
					    private void loadTransactionData() {
 | 
				
			||||||
        Intent intent = getIntent();
 | 
					        Intent intent = getIntent();
 | 
				
			||||||
        if (intent != null) {
 | 
					        if (intent != null) {
 | 
				
			||||||
            Log.d("ReceiptActivity", "=== LOADING TRANSACTION DATA ===");
 | 
					            Log.d("ReceiptActivity", "=== LOADING ENHANCED TRANSACTION DATA ===");
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // ✅ DETECT TRANSACTION TYPE
 | 
				
			||||||
 | 
					            String callingActivity = intent.getStringExtra("calling_activity");
 | 
				
			||||||
 | 
					            String channelCategory = intent.getStringExtra("channel_category");
 | 
				
			||||||
 | 
					            String channelCode = intent.getStringExtra("channel_code");
 | 
				
			||||||
 | 
					            boolean isEmvTransaction = "EMV_CARD".equals(channelCategory) || "ResultTransactionActivity".equals(callingActivity);
 | 
				
			||||||
 | 
					            boolean isQrisTransaction = "QRIS".equalsIgnoreCase(channelCode) || "QrisResultActivity".equals(callingActivity);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "🔍 TRANSACTION TYPE DETECTION:");
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Calling Activity: " + callingActivity);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Channel Category: " + channelCategory);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Channel Code: " + channelCode);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Is EMV Transaction: " + isEmvTransaction);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Is QRIS Transaction: " + isQrisTransaction);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // Get all available data from intent
 | 
					            // Get all available data from intent
 | 
				
			||||||
            String amount = intent.getStringExtra("transaction_amount");
 | 
					            String amount = intent.getStringExtra("transaction_amount");
 | 
				
			||||||
@ -135,89 +176,144 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
            String createdAt = intent.getStringExtra("created_at");
 | 
					            String createdAt = intent.getStringExtra("created_at");
 | 
				
			||||||
            String paymentMethodStr = intent.getStringExtra("payment_method");
 | 
					            String paymentMethodStr = intent.getStringExtra("payment_method");
 | 
				
			||||||
            String cardTypeStr = intent.getStringExtra("card_type");
 | 
					            String cardTypeStr = intent.getStringExtra("card_type");
 | 
				
			||||||
            String channelCode = intent.getStringExtra("channel_code");
 | 
					 | 
				
			||||||
            String channelCategory = intent.getStringExtra("channel_category");
 | 
					 | 
				
			||||||
            String acquirer = intent.getStringExtra("acquirer");
 | 
					            String acquirer = intent.getStringExtra("acquirer");
 | 
				
			||||||
            String mid = intent.getStringExtra("mid");
 | 
					            String mid = intent.getStringExtra("mid");
 | 
				
			||||||
            String tid = intent.getStringExtra("tid");
 | 
					            String tid = intent.getStringExtra("tid");
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
 | 
					            // ✅ EMV SPECIFIC DATA
 | 
				
			||||||
 | 
					            String emvCardholderName = intent.getStringExtra("emv_cardholder_name");
 | 
				
			||||||
 | 
					            String emvAid = intent.getStringExtra("emv_aid");
 | 
				
			||||||
 | 
					            String emvExpiry = intent.getStringExtra("emv_expiry");
 | 
				
			||||||
 | 
					            String cardNumber = intent.getStringExtra("card_number");
 | 
				
			||||||
 | 
					            String midtransResponse = intent.getStringExtra("midtrans_response");
 | 
				
			||||||
 | 
					            boolean emvMode = intent.getBooleanExtra("emv_mode", false);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // ✅ QRIS SPECIFIC DATA
 | 
				
			||||||
 | 
					            String qrString = intent.getStringExtra("qr_string");
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            // Log received data for debugging
 | 
					            // Log received data for debugging
 | 
				
			||||||
            Log.d("ReceiptActivity", "🔍 RECEIVED DATA:");
 | 
					            Log.d("ReceiptActivity", "🔍 RECEIVED DATA:");
 | 
				
			||||||
            Log.d("ReceiptActivity", "   amount: " + amount);
 | 
					            Log.d("ReceiptActivity", "   amount: " + amount);
 | 
				
			||||||
            Log.d("ReceiptActivity", "   referenceId: " + referenceId);
 | 
					            Log.d("ReceiptActivity", "   referenceId: " + referenceId);
 | 
				
			||||||
            Log.d("ReceiptActivity", "   orderId: " + orderId);
 | 
					            Log.d("ReceiptActivity", "   orderId: " + orderId);
 | 
				
			||||||
            Log.d("ReceiptActivity", "   channelCode: " + channelCode);
 | 
					 | 
				
			||||||
            Log.d("ReceiptActivity", "   acquirer (from intent): " + acquirer);
 | 
					            Log.d("ReceiptActivity", "   acquirer (from intent): " + acquirer);
 | 
				
			||||||
            Log.d("ReceiptActivity", "   createdAt: " + createdAt);
 | 
					            Log.d("ReceiptActivity", "   createdAt: " + createdAt);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   EMV Mode: " + emvMode);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   EMV Cardholder: " + emvCardholderName);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Card Number: " + (cardNumber != null ? cardNumber : "N/A"));
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   QR String Available: " + (qrString != null && !qrString.isEmpty()));
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // 1. Set merchant data with defaults
 | 
					            // 1. Set merchant data with defaults
 | 
				
			||||||
            merchantName.setText(merchantNameStr != null ? merchantNameStr : "Marcel Panjaitan");
 | 
					            merchantName.setText(merchantNameStr != null ? merchantNameStr : "TOKO KLONTONG PAK EKO");
 | 
				
			||||||
            merchantLocation.setText(merchantLocationStr != null ? merchantLocationStr : "Jakarta, Indonesia");
 | 
					            merchantLocation.setText(merchantLocationStr != null ? merchantLocationStr : "Ciputat Baru, Tangsel");
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // 2. Set MID and TID
 | 
					            // 2. Set MID and TID
 | 
				
			||||||
            midText.setText(mid != null ? mid : "71000026521");
 | 
					            midText.setText("MID: " + (mid != null ? mid : "123456789901"));
 | 
				
			||||||
            tidText.setText(tid != null ? tid : "73001500");
 | 
					            tidText.setText("TID: " + (tid != null ? tid : "123456789901"));
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // 3. Set transaction number
 | 
					            // 3. Set transaction number
 | 
				
			||||||
            String displayTransactionNumber = null;
 | 
					            String displayTransactionNumber = getDisplayTransactionNumber(referenceId, transactionId, orderId);
 | 
				
			||||||
            if (referenceId != null && !referenceId.isEmpty()) {
 | 
					            transactionNumber.setText(displayTransactionNumber);
 | 
				
			||||||
                displayTransactionNumber = referenceId;
 | 
					 | 
				
			||||||
            } else if (transactionId != null && !transactionId.isEmpty()) {
 | 
					 | 
				
			||||||
                displayTransactionNumber = transactionId;
 | 
					 | 
				
			||||||
            } else if (orderId != null && !orderId.isEmpty()) {
 | 
					 | 
				
			||||||
                displayTransactionNumber = orderId;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            transactionNumber.setText(displayTransactionNumber != null ? displayTransactionNumber : "N/A");
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // 4. Set transaction date
 | 
					            // 4. Set transaction date
 | 
				
			||||||
            String displayDate = null;
 | 
					            String displayDate = getDisplayTransactionDate(createdAt, transactionDateStr, isEmvTransaction);
 | 
				
			||||||
            if (createdAt != null && !createdAt.isEmpty()) {
 | 
					 | 
				
			||||||
                displayDate = formatDateFromCreatedAt(createdAt);
 | 
					 | 
				
			||||||
            } else if (transactionDateStr != null && !transactionDateStr.isEmpty()) {
 | 
					 | 
				
			||||||
                displayDate = transactionDateStr;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                displayDate = getCurrentDateTime();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            transactionDate.setText(displayDate);
 | 
					            transactionDate.setText(displayDate);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // 5. Set payment method
 | 
					            // 5. ✅ ENHANCED: Set payment method based on transaction type
 | 
				
			||||||
            String displayPaymentMethod = getPaymentMethodFromChannelCode(channelCode, paymentMethodStr);
 | 
					            String displayPaymentMethod = getDisplayPaymentMethod(channelCode, paymentMethodStr, isEmvTransaction, emvMode);
 | 
				
			||||||
            paymentMethod.setText(displayPaymentMethod);
 | 
					            paymentMethod.setText(displayPaymentMethod);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // 6. ✅ IMPROVED: Enhanced card type detection for QRIS
 | 
					            // 6. ✅ ENHANCED: Set card type with EMV and QRIS priority
 | 
				
			||||||
            String displayCardType = null;
 | 
					            String displayCardType = getDisplayCardType(cardTypeStr, acquirer, channelCode, isEmvTransaction, 
 | 
				
			||||||
            
 | 
					                                                      isQrisTransaction, midtransResponse, referenceId);
 | 
				
			||||||
            if (channelCode != null && channelCode.equalsIgnoreCase("QRIS")) {
 | 
					 | 
				
			||||||
                Log.d("ReceiptActivity", "🔍 QRIS transaction detected - searching for real acquirer");
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                // For QRIS, try to get real acquirer from webhook data
 | 
					 | 
				
			||||||
                if (referenceId != null && !referenceId.isEmpty()) {
 | 
					 | 
				
			||||||
                    String realAcquirer = fetchRealAcquirerSync(referenceId);
 | 
					 | 
				
			||||||
                    if (realAcquirer != null && !realAcquirer.isEmpty() && !realAcquirer.equalsIgnoreCase("qris")) {
 | 
					 | 
				
			||||||
                        displayCardType = getCardTypeFromAcquirer(realAcquirer, null, null);
 | 
					 | 
				
			||||||
                        Log.d("ReceiptActivity", "✅ QRIS real acquirer found: " + realAcquirer + " -> " + displayCardType);
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        Log.w("ReceiptActivity", "⚠️ QRIS real acquirer not found, using generic QRIS");
 | 
					 | 
				
			||||||
                        displayCardType = "QRIS";
 | 
					 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        // Start async search for better results
 | 
					 | 
				
			||||||
                        fetchRealAcquirerFromWebhook(referenceId);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    displayCardType = "QRIS";
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                // Non-QRIS transaction
 | 
					 | 
				
			||||||
                displayCardType = getCardTypeFromAcquirer(acquirer, channelCode, cardTypeStr);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            cardType.setText(displayCardType);
 | 
					            cardType.setText(displayCardType);
 | 
				
			||||||
            Log.d("ReceiptActivity", "💳 FINAL CARD TYPE: " + displayCardType);
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // 7. Format and set amounts
 | 
					            // 7. ✅ Format and set amounts with proper calculation
 | 
				
			||||||
            setAmountData(amount, grossAmount);
 | 
					            setAmountDataEnhanced(amount, grossAmount, isEmvTransaction, isQrisTransaction);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            Log.d("ReceiptActivity", "=== TRANSACTION DATA LOADED ===");
 | 
					            Log.d("ReceiptActivity", "💳 FINAL DISPLAY VALUES:");
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Payment Method: " + displayPaymentMethod);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Card Type: " + displayCardType);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "   Transaction Number: " + displayTransactionNumber);
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "=== ENHANCED TRANSACTION DATA LOADED ===");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get display transaction number with priority
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String getDisplayTransactionNumber(String referenceId, String transactionId, String orderId) {
 | 
				
			||||||
 | 
					        if (referenceId != null && !referenceId.isEmpty()) {
 | 
				
			||||||
 | 
					            return referenceId;
 | 
				
			||||||
 | 
					        } else if (transactionId != null && !transactionId.isEmpty()) {
 | 
				
			||||||
 | 
					            // For long transaction IDs, show last 10 characters
 | 
				
			||||||
 | 
					            return transactionId.length() > 10 ? 
 | 
				
			||||||
 | 
					                transactionId.substring(transactionId.length() - 10) : transactionId;
 | 
				
			||||||
 | 
					        } else if (orderId != null && !orderId.isEmpty()) {
 | 
				
			||||||
 | 
					            return orderId.length() > 10 ? 
 | 
				
			||||||
 | 
					                orderId.substring(orderId.length() - 10) : orderId;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return String.valueOf(System.currentTimeMillis() % 10000000000L);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get display transaction date with proper formatting
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String getDisplayTransactionDate(String createdAt, String transactionDateStr, boolean isEmvTransaction) {
 | 
				
			||||||
 | 
					        String dateToFormat = null;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (createdAt != null && !createdAt.isEmpty()) {
 | 
				
			||||||
 | 
					            dateToFormat = createdAt;
 | 
				
			||||||
 | 
					        } else if (transactionDateStr != null && !transactionDateStr.isEmpty()) {
 | 
				
			||||||
 | 
					            dateToFormat = transactionDateStr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (dateToFormat != null) {
 | 
				
			||||||
 | 
					            if (isEmvTransaction) {
 | 
				
			||||||
 | 
					                return formatDateForEmvTransaction(dateToFormat);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return formatDateFromCreatedAt(dateToFormat);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return getCurrentDateTime();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Format date specifically for EMV transactions
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String formatDateForEmvTransaction(String dateString) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            // EMV transactions might use different date formats
 | 
				
			||||||
 | 
					            String[] inputFormats = {
 | 
				
			||||||
 | 
					                "dd MMMM yyyy HH:mm",
 | 
				
			||||||
 | 
					                "yyyy-MM-dd HH:mm:ss",
 | 
				
			||||||
 | 
					                "yyyy-MM-dd'T'HH:mm:ss'Z'",
 | 
				
			||||||
 | 
					                "dd/MM/yyyy HH:mm"
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMMM yyyy HH:mm", new Locale("id", "ID"));
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            for (String format : inputFormats) {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    SimpleDateFormat inputFormat = new SimpleDateFormat(format, 
 | 
				
			||||||
 | 
					                        format.contains("MMMM") ? new Locale("id", "ID") : Locale.getDefault());
 | 
				
			||||||
 | 
					                    Date date = inputFormat.parse(dateString);
 | 
				
			||||||
 | 
					                    String formatted = outputFormat.format(date);
 | 
				
			||||||
 | 
					                    Log.d("ReceiptActivity", "EMV Date formatting: '" + dateString + "' -> '" + formatted + "'");
 | 
				
			||||||
 | 
					                    return formatted;
 | 
				
			||||||
 | 
					                } catch (Exception ignored) {
 | 
				
			||||||
 | 
					                    // Try next format
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // If all formats fail, return as-is
 | 
				
			||||||
 | 
					            Log.w("ReceiptActivity", "Could not format EMV date: " + dateString);
 | 
				
			||||||
 | 
					            return dateString;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            Log.e("ReceiptActivity", "Error formatting EMV date: " + dateString, e);
 | 
				
			||||||
 | 
					            return dateString;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -227,7 +323,7 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
 | 
					            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // Output format for receipt: "dd/MM/yyyy HH:mm"
 | 
					            // Output format for receipt: "dd/MM/yyyy HH:mm"
 | 
				
			||||||
            SimpleDateFormat outputFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm", new Locale("id", "ID"));
 | 
					            SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMMM yyyy HH:mm", new Locale("id", "ID"));
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            Date date = inputFormat.parse(createdAt);
 | 
					            Date date = inputFormat.parse(createdAt);
 | 
				
			||||||
            String formatted = outputFormat.format(date);
 | 
					            String formatted = outputFormat.format(date);
 | 
				
			||||||
@ -242,6 +338,39 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get display payment method with EMV support
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String getDisplayPaymentMethod(String channelCode, String fallbackPaymentMethod, 
 | 
				
			||||||
 | 
					                                         boolean isEmvTransaction, boolean emvMode) {
 | 
				
			||||||
 | 
					        if (isEmvTransaction) {
 | 
				
			||||||
 | 
					            // For EMV transactions, be more specific
 | 
				
			||||||
 | 
					            if (emvMode) {
 | 
				
			||||||
 | 
					                if (channelCode != null) {
 | 
				
			||||||
 | 
					                    switch (channelCode.toUpperCase()) {
 | 
				
			||||||
 | 
					                        case "CREDIT": return "Kartu Kredit (EMV)";
 | 
				
			||||||
 | 
					                        case "DEBIT": return "Kartu Debit (EMV)";
 | 
				
			||||||
 | 
					                        default: return "Kartu Kredit (EMV)";
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return "Kartu Kredit (EMV)";
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // Magnetic stripe
 | 
				
			||||||
 | 
					                if (channelCode != null) {
 | 
				
			||||||
 | 
					                    switch (channelCode.toUpperCase()) {
 | 
				
			||||||
 | 
					                        case "CREDIT": return "Kartu Kredit";
 | 
				
			||||||
 | 
					                        case "DEBIT": return "Kartu Debit";
 | 
				
			||||||
 | 
					                        default: return "Kartu Kredit";
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return "Kartu Kredit";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // For QRIS and other transactions, use existing logic
 | 
				
			||||||
 | 
					            return getPaymentMethodFromChannelCode(channelCode, fallbackPaymentMethod);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get payment method name from channel_code with comprehensive mapping
 | 
					     * Get payment method name from channel_code with comprehensive mapping
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -291,6 +420,78 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
        return fallbackPaymentMethod != null ? fallbackPaymentMethod : "QRIS";
 | 
					        return fallbackPaymentMethod != null ? fallbackPaymentMethod : "QRIS";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * ✅ ENHANCED: Card type detection with EMV and QRIS priority
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String getDisplayCardType(String cardTypeStr, String acquirer, String channelCode, 
 | 
				
			||||||
 | 
					                                    boolean isEmvTransaction, boolean isQrisTransaction, 
 | 
				
			||||||
 | 
					                                    String midtransResponse, String referenceId) {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        Log.d("ReceiptActivity", "🔍 ENHANCED CARD TYPE DETECTION:");
 | 
				
			||||||
 | 
					        Log.d("ReceiptActivity", "   Input Card Type: " + cardTypeStr);
 | 
				
			||||||
 | 
					        Log.d("ReceiptActivity", "   Input Acquirer: " + acquirer);
 | 
				
			||||||
 | 
					        Log.d("ReceiptActivity", "   Is EMV Transaction: " + isEmvTransaction);
 | 
				
			||||||
 | 
					        Log.d("ReceiptActivity", "   Is QRIS Transaction: " + isQrisTransaction);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (isEmvTransaction) {
 | 
				
			||||||
 | 
					            // ✅ FOR EMV TRANSACTIONS: Priority to cardTypeStr from ResultTransactionActivity
 | 
				
			||||||
 | 
					            if (cardTypeStr != null && !cardTypeStr.isEmpty() && !cardTypeStr.equalsIgnoreCase("unknown")) {
 | 
				
			||||||
 | 
					                Log.d("ReceiptActivity", "✅ EMV: Using provided card type: " + cardTypeStr);
 | 
				
			||||||
 | 
					                return cardTypeStr;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // ✅ FALLBACK: Try to extract from Midtrans response
 | 
				
			||||||
 | 
					            if (midtransResponse != null && !midtransResponse.isEmpty()) {
 | 
				
			||||||
 | 
					                String bankFromMidtrans = extractBankFromMidtransResponse(midtransResponse);
 | 
				
			||||||
 | 
					                if (bankFromMidtrans != null && !bankFromMidtrans.isEmpty()) {
 | 
				
			||||||
 | 
					                    Log.d("ReceiptActivity", "✅ EMV: Using bank from Midtrans response: " + bankFromMidtrans);
 | 
				
			||||||
 | 
					                    return bankFromMidtrans;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // ✅ FALLBACK: Use acquirer
 | 
				
			||||||
 | 
					            if (acquirer != null && !acquirer.isEmpty() && !acquirer.equalsIgnoreCase("qris")) {
 | 
				
			||||||
 | 
					                String mappedAcquirer = getCardTypeFromAcquirer(acquirer, channelCode, null);
 | 
				
			||||||
 | 
					                Log.d("ReceiptActivity", "✅ EMV: Using mapped acquirer: " + mappedAcquirer);
 | 
				
			||||||
 | 
					                return mappedAcquirer;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "⚠️ EMV: Using default fallback: BCA");
 | 
				
			||||||
 | 
					            return "BCA"; // Default for EMV
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        } else if (isQrisTransaction) {
 | 
				
			||||||
 | 
					            // ✅ FOR QRIS TRANSACTIONS: Enhanced detection
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "🔍 QRIS transaction detected - searching for real acquirer");
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Priority 1: Use provided cardTypeStr if it's not generic
 | 
				
			||||||
 | 
					            if (cardTypeStr != null && !cardTypeStr.isEmpty() && 
 | 
				
			||||||
 | 
					                !cardTypeStr.equalsIgnoreCase("qris") && !cardTypeStr.equalsIgnoreCase("unknown")) {
 | 
				
			||||||
 | 
					                Log.d("ReceiptActivity", "✅ QRIS: Using provided specific card type: " + cardTypeStr);
 | 
				
			||||||
 | 
					                return cardTypeStr;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Priority 2: Search webhook logs for real acquirer
 | 
				
			||||||
 | 
					            if (referenceId != null && !referenceId.isEmpty()) {
 | 
				
			||||||
 | 
					                String realAcquirer = fetchRealAcquirerSync(referenceId);
 | 
				
			||||||
 | 
					                if (realAcquirer != null && !realAcquirer.isEmpty() && !realAcquirer.equalsIgnoreCase("qris")) {
 | 
				
			||||||
 | 
					                    String mappedQrisAcquirer = getCardTypeFromAcquirer(realAcquirer, null, null);
 | 
				
			||||||
 | 
					                    Log.d("ReceiptActivity", "✅ QRIS real acquirer found: " + realAcquirer + " -> " + mappedQrisAcquirer);
 | 
				
			||||||
 | 
					                    return mappedQrisAcquirer;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    Log.w("ReceiptActivity", "⚠️ QRIS real acquirer not found, using generic QRIS");
 | 
				
			||||||
 | 
					                    // Start async search for better results
 | 
				
			||||||
 | 
					                    fetchRealAcquirerFromWebhook(referenceId);
 | 
				
			||||||
 | 
					                    return "QRIS";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return "QRIS";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // ✅ FOR OTHER TRANSACTIONS: Use standard logic
 | 
				
			||||||
 | 
					            return getCardTypeFromAcquirer(acquirer, channelCode, cardTypeStr);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String getCardTypeFromAcquirer(String acquirer, String channelCode, String fallbackCardType) {
 | 
					    private String getCardTypeFromAcquirer(String acquirer, String channelCode, String fallbackCardType) {
 | 
				
			||||||
        // STEP 1: If we have a valid acquirer that's not generic "qris", use it
 | 
					        // STEP 1: If we have a valid acquirer that's not generic "qris", use it
 | 
				
			||||||
        if (acquirer != null && !acquirer.isEmpty() && !acquirer.equalsIgnoreCase("qris")) {
 | 
					        if (acquirer != null && !acquirer.isEmpty() && !acquirer.equalsIgnoreCase("qris")) {
 | 
				
			||||||
@ -299,88 +500,14 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
            Log.d("ReceiptActivity", "🔍 Mapping acquirer: '" + acquirer + "' -> '" + acq + "'");
 | 
					            Log.d("ReceiptActivity", "🔍 Mapping acquirer: '" + acquirer + "' -> '" + acq + "'");
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // ✅ COMPREHENSIVE acquirer mapping (case-insensitive)
 | 
					            // ✅ COMPREHENSIVE acquirer mapping (case-insensitive)
 | 
				
			||||||
 | 
					            String mappedName = ISSUER_DISPLAY_MAP.get(acq);
 | 
				
			||||||
 | 
					            if (mappedName != null) {
 | 
				
			||||||
 | 
					                Log.d("ReceiptActivity", "✅ Mapped acquirer: " + acquirer + " -> " + mappedName);
 | 
				
			||||||
 | 
					                return mappedName;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Additional mapping for variations not in the map
 | 
				
			||||||
            switch (acq) {
 | 
					            switch (acq) {
 | 
				
			||||||
                // E-Wallet acquirers (most common for QRIS)
 | 
					 | 
				
			||||||
                case "gopay": 
 | 
					 | 
				
			||||||
                case "go-pay": 
 | 
					 | 
				
			||||||
                case "gojek": return "GoPay";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "shopeepay": 
 | 
					 | 
				
			||||||
                case "shopee_pay": 
 | 
					 | 
				
			||||||
                case "shopee": return "ShopeePay";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "ovo": return "OVO";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "dana": return "DANA";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "linkaja": 
 | 
					 | 
				
			||||||
                case "link_aja": 
 | 
					 | 
				
			||||||
                case "tcash": return "LinkAja";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "jenius": 
 | 
					 | 
				
			||||||
                case "btpn": return "Jenius";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "kaspro": 
 | 
					 | 
				
			||||||
                case "kas_pro": return "KasPro";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "sakuku": 
 | 
					 | 
				
			||||||
                case "saku_ku": return "SakuKu";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "doku": 
 | 
					 | 
				
			||||||
                case "doku_wallet": return "DOKU";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "paymi": 
 | 
					 | 
				
			||||||
                case "pay_mi": return "PayMi";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "isaku": 
 | 
					 | 
				
			||||||
                case "i_saku": return "i.Saku";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                // Bank acquirers
 | 
					 | 
				
			||||||
                case "bca": 
 | 
					 | 
				
			||||||
                case "bank_bca": return "BCA";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "mandiri":
 | 
					 | 
				
			||||||
                case "bank_mandiri":
 | 
					 | 
				
			||||||
                case "mandiri_bill": return "Mandiri";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "bni":
 | 
					 | 
				
			||||||
                case "bank_bni":
 | 
					 | 
				
			||||||
                case "bni_va": return "BNI";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "bri":
 | 
					 | 
				
			||||||
                case "bank_bri":
 | 
					 | 
				
			||||||
                case "bri_va": return "BRI";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "permata":
 | 
					 | 
				
			||||||
                case "bank_permata":
 | 
					 | 
				
			||||||
                case "permata_va": return "Permata";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "cimb":
 | 
					 | 
				
			||||||
                case "cimb_niaga":
 | 
					 | 
				
			||||||
                case "bank_cimb":
 | 
					 | 
				
			||||||
                case "cimb_va": return "CIMB Niaga";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "danamon":
 | 
					 | 
				
			||||||
                case "bank_danamon":
 | 
					 | 
				
			||||||
                case "danamon_va": return "Danamon";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "bsi":
 | 
					 | 
				
			||||||
                case "bank_bsi":
 | 
					 | 
				
			||||||
                case "bsi_va": 
 | 
					 | 
				
			||||||
                case "syariah_indonesia": return "BSI";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "maybank":
 | 
					 | 
				
			||||||
                case "bank_maybank": return "Maybank";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "bca_digital":
 | 
					 | 
				
			||||||
                case "blu": return "BCA Digital";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "jago":
 | 
					 | 
				
			||||||
                case "bank_jago": return "Bank Jago";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                case "seabank":
 | 
					 | 
				
			||||||
                case "sea_bank": return "SeaBank";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                // Credit card acquirers
 | 
					                // Credit card acquirers
 | 
				
			||||||
                case "visa": return "Visa";
 | 
					                case "visa": return "Visa";
 | 
				
			||||||
                case "mastercard": 
 | 
					                case "mastercard": 
 | 
				
			||||||
@ -740,6 +867,78 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
        return null; // No acquirer found for specified criteria
 | 
					        return null; // No acquirer found for specified criteria
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Extract bank from Midtrans response JSON string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String extractBankFromMidtransResponse(String midtransResponse) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            org.json.JSONObject response = new org.json.JSONObject(midtransResponse);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Try different possible bank fields
 | 
				
			||||||
 | 
					            String[] bankFields = {"bank", "issuer", "acquiring_bank", "issuer_bank"};
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            for (String field : bankFields) {
 | 
				
			||||||
 | 
					                if (response.has(field)) {
 | 
				
			||||||
 | 
					                    String bankValue = response.getString(field);
 | 
				
			||||||
 | 
					                    if (bankValue != null && !bankValue.trim().isEmpty() && !bankValue.equalsIgnoreCase("qris")) {
 | 
				
			||||||
 | 
					                        Log.d("ReceiptActivity", "Found bank in Midtrans response (" + field + "): " + bankValue);
 | 
				
			||||||
 | 
					                        return formatBankNameForReceipt(bankValue);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            Log.w("ReceiptActivity", "No valid bank found in Midtrans response");
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            Log.e("ReceiptActivity", "Error extracting bank from Midtrans response: " + e.getMessage());
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Format bank name specifically for receipt display
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String formatBankNameForReceipt(String bankName) {
 | 
				
			||||||
 | 
					        if (bankName == null || bankName.trim().isEmpty()) {
 | 
				
			||||||
 | 
					            return "BCA"; // Default
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        String formatted = bankName.trim();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Common bank name mappings for receipt display
 | 
				
			||||||
 | 
					        switch (formatted.toUpperCase()) {
 | 
				
			||||||
 | 
					            case "BCA":
 | 
				
			||||||
 | 
					            case "BANK BCA":
 | 
				
			||||||
 | 
					            case "BANK CENTRAL ASIA": return "BCA";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            case "MANDIRI":
 | 
				
			||||||
 | 
					            case "BANK MANDIRI": return "Mandiri";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            case "BNI":
 | 
				
			||||||
 | 
					            case "BANK BNI":
 | 
				
			||||||
 | 
					            case "BANK NEGARA INDONESIA": return "BNI";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            case "BRI":
 | 
				
			||||||
 | 
					            case "BANK BRI":
 | 
				
			||||||
 | 
					            case "BANK RAKYAT INDONESIA": return "BRI";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            case "CIMB":
 | 
				
			||||||
 | 
					            case "CIMB NIAGA":
 | 
				
			||||||
 | 
					            case "BANK CIMB NIAGA": return "CIMB Niaga";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            case "DANAMON":
 | 
				
			||||||
 | 
					            case "BANK DANAMON": return "Danamon";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            case "PERMATA":
 | 
				
			||||||
 | 
					            case "BANK PERMATA": return "Permata";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                // Return capitalized version
 | 
				
			||||||
 | 
					                return capitalizeFirstLetter(formatted);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String capitalizeFirstLetter(String input) {
 | 
					    private String capitalizeFirstLetter(String input) {
 | 
				
			||||||
        if (input == null || input.isEmpty()) {
 | 
					        if (input == null || input.isEmpty()) {
 | 
				
			||||||
            return input;
 | 
					            return input;
 | 
				
			||||||
@ -758,51 +957,79 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
        return cleaned.substring(0, 1).toUpperCase() + cleaned.substring(1).toLowerCase();
 | 
					        return cleaned.substring(0, 1).toUpperCase() + cleaned.substring(1).toLowerCase();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void setAmountData(String amount, String grossAmount) {
 | 
					    /**
 | 
				
			||||||
        // Prioritize 'amount' over 'grossAmount' for transaction data
 | 
					     * ✅ ENHANCED: Set amount data with EMV and QRIS support
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void setAmountDataEnhanced(String amount, String grossAmount, boolean isEmvTransaction, boolean isQrisTransaction) {
 | 
				
			||||||
        String amountToUse = amount != null ? amount : grossAmount;
 | 
					        String amountToUse = amount != null ? amount : grossAmount;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        Log.d("ReceiptActivity", "Setting amount data - amount: " + amount + 
 | 
					        Log.d("ReceiptActivity", "Setting enhanced amount data - amount: " + amount + 
 | 
				
			||||||
            ", grossAmount: " + grossAmount + ", using: " + amountToUse);
 | 
					            ", grossAmount: " + grossAmount + ", using: " + amountToUse + 
 | 
				
			||||||
 | 
					            ", isEMV: " + isEmvTransaction + ", isQRIS: " + isQrisTransaction);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (amountToUse != null) {
 | 
					        if (amountToUse != null) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                // Clean and parse the amount
 | 
					 | 
				
			||||||
                String cleanAmount = cleanAmountString(amountToUse);
 | 
					                String cleanAmount = cleanAmountString(amountToUse);
 | 
				
			||||||
                Log.d("ReceiptActivity", "Cleaned amount: " + cleanAmount);
 | 
					                Log.d("ReceiptActivity", "Cleaned amount: " + cleanAmount);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Parse as long integer (Indonesian Rupiah doesn't use decimal cents)
 | 
					 | 
				
			||||||
                long amountLong = Long.parseLong(cleanAmount);
 | 
					                long amountLong = Long.parseLong(cleanAmount);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Set transaction total
 | 
					                // Set transaction total
 | 
				
			||||||
                transactionTotal.setText("Rp " + formatCurrency(amountLong));
 | 
					                transactionTotal.setText(formatCurrency(amountLong));
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Calculate tax and service fee (for QRIS, typically no additional fees)
 | 
					                // ✅ CALCULATE FEES BASED ON TRANSACTION TYPE
 | 
				
			||||||
                long tax = 0; // QRIS usually doesn't have tax
 | 
					                long tax = 0;
 | 
				
			||||||
                long serviceFeeValue = 0; // QRIS usually doesn't have service fee
 | 
					                long serviceFeeValue = 0;
 | 
				
			||||||
                long total = amountLong + tax + serviceFeeValue;
 | 
					                long total = amountLong;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if (isEmvTransaction) {
 | 
				
			||||||
 | 
					                    // For EMV transactions, check if gross amount includes additional fees
 | 
				
			||||||
 | 
					                    if (grossAmount != null && !grossAmount.equals(amount)) {
 | 
				
			||||||
 | 
					                        try {
 | 
				
			||||||
 | 
					                            long grossAmountLong = Long.parseLong(cleanAmountString(grossAmount));
 | 
				
			||||||
 | 
					                            long difference = grossAmountLong - amountLong;
 | 
				
			||||||
 | 
					                            
 | 
				
			||||||
 | 
					                            if (difference > 0) {
 | 
				
			||||||
 | 
					                                // Assume 11% tax and 500 service fee (adjust based on your business logic)
 | 
				
			||||||
 | 
					                                tax = Math.round(amountLong * 0.11);
 | 
				
			||||||
 | 
					                                serviceFeeValue = 500;
 | 
				
			||||||
 | 
					                                total = grossAmountLong;
 | 
				
			||||||
 | 
					                                
 | 
				
			||||||
 | 
					                                Log.d("ReceiptActivity", "EMV: Calculated tax=" + tax + ", service=" + serviceFeeValue + ", total=" + total);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        } catch (Exception e) {
 | 
				
			||||||
 | 
					                            Log.w("ReceiptActivity", "Could not parse gross amount for EMV: " + grossAmount);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else if (isQrisTransaction) {
 | 
				
			||||||
 | 
					                    // For QRIS, typically no additional fees (tax=0, service=0)
 | 
				
			||||||
 | 
					                    tax = 0;
 | 
				
			||||||
 | 
					                    serviceFeeValue = 0;
 | 
				
			||||||
 | 
					                    total = amountLong;
 | 
				
			||||||
 | 
					                    Log.d("ReceiptActivity", "QRIS: No additional fees - total=" + total);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Set calculated values
 | 
					                // Set calculated values
 | 
				
			||||||
                taxPercentage.setText("Rp 0");
 | 
					                taxPercentage.setText(tax > 0 ? "11%" : "0%");
 | 
				
			||||||
                serviceFee.setText("Rp 0");
 | 
					                serviceFee.setText(formatCurrency(serviceFeeValue));
 | 
				
			||||||
                finalTotal.setText("Rp " + formatCurrency(total));
 | 
					                finalTotal.setText(formatCurrency(total));
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                Log.d("ReceiptActivity", "Amount formatting successful: " + amountLong + " -> Rp " + formatCurrency(total));
 | 
					                Log.d("ReceiptActivity", "Enhanced amount formatting successful: " + amountLong + " -> " + formatCurrency(total));
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            } catch (NumberFormatException e) {
 | 
					            } catch (NumberFormatException e) {
 | 
				
			||||||
                Log.e("ReceiptActivity", "Error parsing amount: " + amountToUse, e);
 | 
					                Log.e("ReceiptActivity", "Error parsing enhanced amount: " + amountToUse, e);
 | 
				
			||||||
                // Fallback if parsing fails
 | 
					                // Fallback if parsing fails
 | 
				
			||||||
                transactionTotal.setText("Rp " + amountToUse);
 | 
					                transactionTotal.setText(amountToUse);
 | 
				
			||||||
                taxPercentage.setText("Rp 0");
 | 
					                taxPercentage.setText("0%");
 | 
				
			||||||
                serviceFee.setText("Rp 0");
 | 
					                serviceFee.setText("0");
 | 
				
			||||||
                finalTotal.setText("Rp " + amountToUse);
 | 
					                finalTotal.setText(amountToUse);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // Default values if no amount provided
 | 
					            // Default values if no amount provided
 | 
				
			||||||
            transactionTotal.setText("Rp 0");
 | 
					            transactionTotal.setText("0");
 | 
				
			||||||
            taxPercentage.setText("Rp 0");
 | 
					            taxPercentage.setText("0%");
 | 
				
			||||||
            serviceFee.setText("Rp 0");
 | 
					            serviceFee.setText("0");
 | 
				
			||||||
            finalTotal.setText("Rp 0");
 | 
					            finalTotal.setText("0");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -876,7 +1103,7 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String getCurrentDateTime() {
 | 
					    private String getCurrentDateTime() {
 | 
				
			||||||
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", new Locale("id", "ID"));
 | 
					        SimpleDateFormat sdf = new SimpleDateFormat("dd MMMM yyyy HH:mm", new Locale("id", "ID"));
 | 
				
			||||||
        return sdf.format(new Date());
 | 
					        return sdf.format(new Date());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -916,6 +1143,11 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
                    navigateToHomePage();
 | 
					                    navigateToHomePage();
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
 | 
					                case "ResultTransactionActivity":
 | 
				
			||||||
 | 
					                    // ✅ NEW: Handle back from ResultTransactionActivity
 | 
				
			||||||
 | 
					                    navigateToHomePage();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
                case "PaymentActivity":
 | 
					                case "PaymentActivity":
 | 
				
			||||||
                case "QrisActivity":
 | 
					                case "QrisActivity":
 | 
				
			||||||
                    // Go back to payment/qris activity
 | 
					                    // Go back to payment/qris activity
 | 
				
			||||||
 | 
				
			|||||||
@ -78,15 +78,15 @@ public class QrisResultActivity extends AppCompatActivity {
 | 
				
			|||||||
    private String currentQrImageUrl;
 | 
					    private String currentQrImageUrl;
 | 
				
			||||||
    private int originalAmount;
 | 
					    private int originalAmount;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ✅ ADD: QR String untuk validasi QRIS
 | 
					    // ✅ QR String untuk validasi QRIS
 | 
				
			||||||
    private String currentQrString = "";
 | 
					    private String currentQrString = "";
 | 
				
			||||||
    private String qrStringFromMidtrans = "";
 | 
					    private String qrStringFromMidtrans = "";
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ✅ FIXED: Store actual issuer/acquirer from Midtrans response
 | 
					    // ✅ Store actual issuer/acquirer from Midtrans response
 | 
				
			||||||
    private String actualIssuerFromMidtrans = "";
 | 
					    private String actualIssuerFromMidtrans = "";
 | 
				
			||||||
    private String actualAcquirerFromMidtrans = "";
 | 
					    private String actualAcquirerFromMidtrans = "";
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ✅ ADD: Track QR refresh transaction for payment monitoring
 | 
					    // ✅ Track QR refresh transaction for payment monitoring
 | 
				
			||||||
    private String currentQrTransactionId = "";
 | 
					    private String currentQrTransactionId = "";
 | 
				
			||||||
    private boolean isMonitoringQrRefreshTransaction = false;
 | 
					    private boolean isMonitoringQrRefreshTransaction = false;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -97,7 +97,7 @@ public class QrisResultActivity extends AppCompatActivity {
 | 
				
			|||||||
    private static final String MIDTRANS_AUTH = "Basic U0ItTWlkLXNlcnZlci1PM2t1bXkwVDl4M1VvYnVvVTc3NW5QbXc=";
 | 
					    private static final String MIDTRANS_AUTH = "Basic U0ItTWlkLXNlcnZlci1PM2t1bXkwVDl4M1VvYnVvVTc3NW5QbXc=";
 | 
				
			||||||
    private static final String MIDTRANS_CHARGE_URL = "https://api.sandbox.midtrans.com/v2/charge";
 | 
					    private static final String MIDTRANS_CHARGE_URL = "https://api.sandbox.midtrans.com/v2/charge";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // ✅ ADD: Mapping dari technical issuer ke display name
 | 
					    // ✅ Mapping dari technical issuer ke display name
 | 
				
			||||||
    private static final Map<String, String> ISSUER_DISPLAY_MAP = new HashMap<String, String>() {{
 | 
					    private static final Map<String, String> ISSUER_DISPLAY_MAP = new HashMap<String, String>() {{
 | 
				
			||||||
        put("airpay shopee", "ShopeePay");
 | 
					        put("airpay shopee", "ShopeePay");
 | 
				
			||||||
        put("shopeepay", "ShopeePay");
 | 
					        put("shopeepay", "ShopeePay");
 | 
				
			||||||
@ -125,6 +125,8 @@ public class QrisResultActivity extends AppCompatActivity {
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    protected void onCreate(@Nullable Bundle savedInstanceState) {
 | 
					    protected void onCreate(@Nullable Bundle savedInstanceState) {
 | 
				
			||||||
        super.onCreate(savedInstanceState);
 | 
					        super.onCreate(savedInstanceState);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // ✅ TETAP MENGGUNAKAN LAYOUT ASLI UNTUK QR DISPLAY
 | 
				
			||||||
        setContentView(R.layout.activity_qris_result);
 | 
					        setContentView(R.layout.activity_qris_result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Initialize views
 | 
					        // Initialize views
 | 
				
			||||||
@ -409,7 +411,7 @@ public class QrisResultActivity extends AppCompatActivity {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // ✅ FIXED: Return both QR URL and QR String
 | 
					    // ✅ ENHANCED: Return both QR URL and QR String
 | 
				
			||||||
    private QrRefreshResult generateNewQrCode() {
 | 
					    private QrRefreshResult generateNewQrCode() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            Log.d("QrisResultFlow", "🔧 Refreshing QR code for existing transaction");
 | 
					            Log.d("QrisResultFlow", "🔧 Refreshing QR code for existing transaction");
 | 
				
			||||||
@ -807,7 +809,7 @@ public class QrisResultActivity extends AppCompatActivity {
 | 
				
			|||||||
        return fallbackName;
 | 
					        return fallbackName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // ✅ COMPLETELY FIXED: Use actual issuer from Midtrans response
 | 
					    // ✅ ENHANCED: Use actual issuer from Midtrans response
 | 
				
			||||||
    private void syncTransactionStatusToBackend(String finalStatus) {
 | 
					    private void syncTransactionStatusToBackend(String finalStatus) {
 | 
				
			||||||
        Log.d("QrisResultFlow", "🔄 Syncing status '" + finalStatus + "' to backend for reference: " + referenceId);
 | 
					        Log.d("QrisResultFlow", "🔄 Syncing status '" + finalStatus + "' to backend for reference: " + referenceId);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,8 @@ import android.os.Handler;
 | 
				
			|||||||
import android.os.Looper;
 | 
					import android.os.Looper;
 | 
				
			||||||
import android.util.Log;
 | 
					import android.util.Log;
 | 
				
			||||||
import android.view.View;
 | 
					import android.view.View;
 | 
				
			||||||
 | 
					import android.widget.Button;
 | 
				
			||||||
 | 
					import android.widget.ImageView;
 | 
				
			||||||
import android.widget.LinearLayout;
 | 
					import android.widget.LinearLayout;
 | 
				
			||||||
import android.widget.TextView;
 | 
					import android.widget.TextView;
 | 
				
			||||||
import android.widget.Toast;
 | 
					import android.widget.Toast;
 | 
				
			||||||
@ -14,7 +16,6 @@ import androidx.appcompat.app.AlertDialog;
 | 
				
			|||||||
import androidx.appcompat.app.AppCompatActivity;
 | 
					import androidx.appcompat.app.AppCompatActivity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.example.bdkipoc.R;
 | 
					import com.example.bdkipoc.R;
 | 
				
			||||||
import com.google.android.material.button.MaterialButton;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.json.JSONException;
 | 
					import org.json.JSONException;
 | 
				
			||||||
import org.json.JSONObject;
 | 
					import org.json.JSONObject;
 | 
				
			||||||
@ -25,30 +26,39 @@ import java.util.Date;
 | 
				
			|||||||
import java.util.Locale;
 | 
					import java.util.Locale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * ResultTransactionActivity - Enhanced Receipt-style Display with Better Bank Detection
 | 
					 * ResultTransactionActivity - Enhanced Receipt-style Display using activity_receipt.xml
 | 
				
			||||||
 * Shows transaction results in a professional receipt format with improved debugging
 | 
					 * Shows EMV/Card transaction results using the same layout as QRIS receipts
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class ResultTransactionActivity extends AppCompatActivity {
 | 
					public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			||||||
    private static final String TAG = "ResultTransaction";
 | 
					    private static final String TAG = "ResultTransaction";
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // UI Components - New Receipt Layout
 | 
					    // ✅ UI Components using activity_receipt.xml IDs
 | 
				
			||||||
    private TextView tvMerchantName, tvMerchantLocation;
 | 
					 | 
				
			||||||
    private TextView tvTid, tvTransactionNumber, tvTransactionDate;
 | 
					 | 
				
			||||||
    private TextView tvPaymentMethodDetail, tvCardType;
 | 
					 | 
				
			||||||
    private TextView tvSubtotal, tvTax, tvServiceFee, tvFinalTotal;
 | 
					 | 
				
			||||||
    private LinearLayout btnPrint, btnEmail;
 | 
					 | 
				
			||||||
    private MaterialButton btnFinish;
 | 
					 | 
				
			||||||
    private LinearLayout backNavigation;
 | 
					    private LinearLayout backNavigation;
 | 
				
			||||||
 | 
					    private ImageView backArrow;
 | 
				
			||||||
 | 
					    private TextView toolbarTitle;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Hidden compatibility components
 | 
					    // Receipt details
 | 
				
			||||||
    private TextView tvAmount, tvStatus, tvReference, tvCardInfo;
 | 
					    private TextView merchantName;
 | 
				
			||||||
    private TextView tvPaymentMethod, tvTransactionId, tvOrderId, tvTimestamp;
 | 
					    private TextView merchantLocation;
 | 
				
			||||||
    private TextView tvResponseData, tvErrorDetails;
 | 
					    private TextView midText;
 | 
				
			||||||
    private LinearLayout layoutErrorDetails;
 | 
					    private TextView tidText;
 | 
				
			||||||
 | 
					    private TextView transactionNumber;
 | 
				
			||||||
 | 
					    private TextView transactionDate;
 | 
				
			||||||
 | 
					    private TextView paymentMethod;
 | 
				
			||||||
 | 
					    private TextView cardType;
 | 
				
			||||||
 | 
					    private TextView transactionTotal;
 | 
				
			||||||
 | 
					    private TextView taxPercentage;
 | 
				
			||||||
 | 
					    private TextView serviceFee;
 | 
				
			||||||
 | 
					    private TextView finalTotal;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Action buttons
 | 
				
			||||||
 | 
					    private LinearLayout printButton;
 | 
				
			||||||
 | 
					    private LinearLayout emailButton;
 | 
				
			||||||
 | 
					    private Button finishButton;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Data from intent
 | 
					    // Data from intent
 | 
				
			||||||
    private String transactionAmount;
 | 
					    private String transactionAmount;
 | 
				
			||||||
    private String cardType;
 | 
					    private String cardTypeFromIntent;
 | 
				
			||||||
    private boolean emvMode;
 | 
					    private boolean emvMode;
 | 
				
			||||||
    private String referenceId;
 | 
					    private String referenceId;
 | 
				
			||||||
    private String cardNo;
 | 
					    private String cardNo;
 | 
				
			||||||
@ -66,18 +76,21 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
    private long subtotalAmount = 0;
 | 
					    private long subtotalAmount = 0;
 | 
				
			||||||
    private long taxAmount = 0;
 | 
					    private long taxAmount = 0;
 | 
				
			||||||
    private long serviceFeeAmount = 500; // Default service fee
 | 
					    private long serviceFeeAmount = 500; // Default service fee
 | 
				
			||||||
    private double taxPercentage = 0.11; // 11% tax
 | 
					    private double taxPercentageValue = 0.11; // 11% tax
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    protected void onCreate(Bundle savedInstanceState) {
 | 
					    protected void onCreate(Bundle savedInstanceState) {
 | 
				
			||||||
        super.onCreate(savedInstanceState);
 | 
					        super.onCreate(savedInstanceState);
 | 
				
			||||||
        setContentView(R.layout.activity_result_transaction);
 | 
					        
 | 
				
			||||||
 | 
					        // ✅ CRITICAL: Use the same layout as ReceiptActivity
 | 
				
			||||||
 | 
					        setContentView(R.layout.activity_receipt);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        Log.d(TAG, "=== RESULT TRANSACTION ACTIVITY STARTED ===");
 | 
					        Log.d(TAG, "=== RESULT TRANSACTION ACTIVITY STARTED ===");
 | 
				
			||||||
 | 
					        Log.d(TAG, "✅ Using activity_receipt.xml layout");
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        initViews();
 | 
					        initViews();
 | 
				
			||||||
        extractIntentData();
 | 
					        extractIntentData();
 | 
				
			||||||
        debugAllDataSources(); // ✅ ENHANCED: Debug all available data
 | 
					        debugAllDataSources();
 | 
				
			||||||
        setupListeners();
 | 
					        setupListeners();
 | 
				
			||||||
        calculateAmounts();
 | 
					        calculateAmounts();
 | 
				
			||||||
        displayReceiptData();
 | 
					        displayReceiptData();
 | 
				
			||||||
@ -86,47 +99,40 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private void initViews() {
 | 
					    private void initViews() {
 | 
				
			||||||
 | 
					        // ✅ Initialize views using activity_receipt.xml IDs
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        // Navigation
 | 
					        // Navigation
 | 
				
			||||||
        backNavigation = findViewById(R.id.back_navigation);
 | 
					        backNavigation = findViewById(R.id.back_navigation);
 | 
				
			||||||
 | 
					        backArrow = findViewById(R.id.backArrow);
 | 
				
			||||||
 | 
					        toolbarTitle = findViewById(R.id.toolbarTitle);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // New Receipt Layout Components
 | 
					        // Receipt details
 | 
				
			||||||
        tvMerchantName = findViewById(R.id.tv_merchant_name);
 | 
					        merchantName = findViewById(R.id.merchant_name);
 | 
				
			||||||
        tvMerchantLocation = findViewById(R.id.tv_merchant_location);
 | 
					        merchantLocation = findViewById(R.id.merchant_location);
 | 
				
			||||||
        tvTid = findViewById(R.id.tv_tid);
 | 
					        midText = findViewById(R.id.mid_text);
 | 
				
			||||||
        tvTransactionNumber = findViewById(R.id.tv_transaction_number);
 | 
					        tidText = findViewById(R.id.tid_text);
 | 
				
			||||||
        tvTransactionDate = findViewById(R.id.tv_transaction_date);
 | 
					        transactionNumber = findViewById(R.id.transaction_number);
 | 
				
			||||||
        tvPaymentMethodDetail = findViewById(R.id.tv_payment_method_detail);
 | 
					        transactionDate = findViewById(R.id.transaction_date);
 | 
				
			||||||
        tvCardType = findViewById(R.id.tv_card_type);
 | 
					        paymentMethod = findViewById(R.id.payment_method);
 | 
				
			||||||
        tvSubtotal = findViewById(R.id.tv_subtotal);
 | 
					        cardType = findViewById(R.id.card_type);
 | 
				
			||||||
        tvTax = findViewById(R.id.tv_tax);
 | 
					        transactionTotal = findViewById(R.id.transaction_total);
 | 
				
			||||||
        tvServiceFee = findViewById(R.id.tv_service_fee);
 | 
					        taxPercentage = findViewById(R.id.tax_percentage);
 | 
				
			||||||
        tvFinalTotal = findViewById(R.id.tv_final_total);
 | 
					        serviceFee = findViewById(R.id.service_fee);
 | 
				
			||||||
 | 
					        finalTotal = findViewById(R.id.final_total);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Action buttons
 | 
					        // Action buttons
 | 
				
			||||||
        btnPrint = findViewById(R.id.btn_print);
 | 
					        printButton = findViewById(R.id.print_button);
 | 
				
			||||||
        btnEmail = findViewById(R.id.btn_email);
 | 
					        emailButton = findViewById(R.id.email_button);
 | 
				
			||||||
        btnFinish = findViewById(R.id.btn_finish);
 | 
					        finishButton = findViewById(R.id.finish_button);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Hidden compatibility components
 | 
					        Log.d(TAG, "✅ All views initialized using activity_receipt.xml");
 | 
				
			||||||
        tvAmount = findViewById(R.id.tv_amount);
 | 
					 | 
				
			||||||
        tvStatus = findViewById(R.id.tv_status);
 | 
					 | 
				
			||||||
        tvReference = findViewById(R.id.tv_reference);
 | 
					 | 
				
			||||||
        tvCardInfo = findViewById(R.id.tv_card_info);
 | 
					 | 
				
			||||||
        tvPaymentMethod = findViewById(R.id.tv_payment_method);
 | 
					 | 
				
			||||||
        tvTransactionId = findViewById(R.id.tv_transaction_id);
 | 
					 | 
				
			||||||
        tvOrderId = findViewById(R.id.tv_order_id);
 | 
					 | 
				
			||||||
        tvTimestamp = findViewById(R.id.tv_timestamp);
 | 
					 | 
				
			||||||
        tvResponseData = findViewById(R.id.tv_response_data);
 | 
					 | 
				
			||||||
        tvErrorDetails = findViewById(R.id.tv_error_details);
 | 
					 | 
				
			||||||
        layoutErrorDetails = findViewById(R.id.layout_error_details);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ✅ ENHANCED: Better intent data extraction with comprehensive debugging
 | 
					 | 
				
			||||||
    private void extractIntentData() {
 | 
					    private void extractIntentData() {
 | 
				
			||||||
        Intent intent = getIntent();
 | 
					        Intent intent = getIntent();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        transactionAmount = intent.getStringExtra("TRANSACTION_AMOUNT");
 | 
					        transactionAmount = intent.getStringExtra("TRANSACTION_AMOUNT");
 | 
				
			||||||
        cardType = intent.getStringExtra("CARD_TYPE");
 | 
					        cardTypeFromIntent = intent.getStringExtra("CARD_TYPE");
 | 
				
			||||||
        emvMode = intent.getBooleanExtra("EMV_MODE", false);
 | 
					        emvMode = intent.getBooleanExtra("EMV_MODE", false);
 | 
				
			||||||
        referenceId = intent.getStringExtra("REFERENCE_ID");
 | 
					        referenceId = intent.getStringExtra("REFERENCE_ID");
 | 
				
			||||||
        cardNo = intent.getStringExtra("CARD_NO");
 | 
					        cardNo = intent.getStringExtra("CARD_NO");
 | 
				
			||||||
@ -136,41 +142,29 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
        emvAid = intent.getStringExtra("EMV_AID");
 | 
					        emvAid = intent.getStringExtra("EMV_AID");
 | 
				
			||||||
        emvExpiry = intent.getStringExtra("EMV_EXPIRY");
 | 
					        emvExpiry = intent.getStringExtra("EMV_EXPIRY");
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // ✅ ENHANCED: Better debugging for Midtrans response
 | 
					 | 
				
			||||||
        Log.d(TAG, "=== EXTRACTING INTENT DATA ===");
 | 
					        Log.d(TAG, "=== EXTRACTING INTENT DATA ===");
 | 
				
			||||||
        Log.d(TAG, "Card Type: " + cardType);
 | 
					        Log.d(TAG, "Card Type: " + cardTypeFromIntent);
 | 
				
			||||||
        Log.d(TAG, "EMV Mode: " + emvMode);
 | 
					        Log.d(TAG, "EMV Mode: " + emvMode);
 | 
				
			||||||
        Log.d(TAG, "Midtrans Response Raw: " + midtransResponse);
 | 
					        Log.d(TAG, "Transaction Amount: " + transactionAmount);
 | 
				
			||||||
 | 
					        Log.d(TAG, "Reference ID: " + referenceId);
 | 
				
			||||||
        Log.d(TAG, "Midtrans Response Length: " + (midtransResponse != null ? midtransResponse.length() : 0));
 | 
					        Log.d(TAG, "Midtrans Response Length: " + (midtransResponse != null ? midtransResponse.length() : 0));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Parse Midtrans response if available
 | 
					        // Parse Midtrans response if available
 | 
				
			||||||
        if (midtransResponse != null && !midtransResponse.isEmpty()) {
 | 
					        if (midtransResponse != null && !midtransResponse.isEmpty()) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                responseJsonData = new JSONObject(midtransResponse);
 | 
					                responseJsonData = new JSONObject(midtransResponse);
 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                // ✅ ENHANCED: Debug all fields in response
 | 
					 | 
				
			||||||
                Log.d(TAG, "✅ Midtrans Response parsed successfully!");
 | 
					                Log.d(TAG, "✅ Midtrans Response parsed successfully!");
 | 
				
			||||||
                Log.d(TAG, "Response keys: " + responseJsonData.keys().toString());
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Check for bank field specifically
 | 
					                // Check for bank field specifically
 | 
				
			||||||
                if (responseJsonData.has("bank")) {
 | 
					                if (responseJsonData.has("bank")) {
 | 
				
			||||||
                    String bankValue = responseJsonData.getString("bank");
 | 
					                    String bankValue = responseJsonData.getString("bank");
 | 
				
			||||||
                    Log.d(TAG, "✅ Bank field found: '" + bankValue + "' (length: " + bankValue.length() + ")");
 | 
					                    Log.d(TAG, "✅ Bank field found: '" + bankValue + "'");
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Log.w(TAG, "⚠️ No 'bank' field in Midtrans response");
 | 
					                    Log.w(TAG, "⚠️ No 'bank' field in Midtrans response");
 | 
				
			||||||
                    
 | 
					 | 
				
			||||||
                    // Check for alternative bank-related fields
 | 
					 | 
				
			||||||
                    String[] possibleBankFields = {"issuer", "card_type", "payment_method", "acquiring_bank"};
 | 
					 | 
				
			||||||
                    for (String field : possibleBankFields) {
 | 
					 | 
				
			||||||
                        if (responseJsonData.has(field)) {
 | 
					 | 
				
			||||||
                            Log.d(TAG, "Alternative field '" + field + "': " + responseJsonData.optString(field));
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            } catch (JSONException e) {
 | 
					            } catch (JSONException e) {
 | 
				
			||||||
                Log.e(TAG, "❌ Error parsing Midtrans response: " + e.getMessage());
 | 
					                Log.e(TAG, "❌ Error parsing Midtrans response: " + e.getMessage());
 | 
				
			||||||
                Log.e(TAG, "Raw response causing error: " + midtransResponse);
 | 
					 | 
				
			||||||
                responseJsonData = null;
 | 
					                responseJsonData = null;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@ -181,17 +175,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
        Log.d(TAG, "===============================");
 | 
					        Log.d(TAG, "===============================");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private void logTransactionDetails() {
 | 
					 | 
				
			||||||
        Log.d(TAG, "=== RECEIPT DETAILS ===");
 | 
					 | 
				
			||||||
        Log.d(TAG, "Reference ID: " + referenceId);
 | 
					 | 
				
			||||||
        Log.d(TAG, "Card Number: " + (cardNo != null ? maskCardNumber(cardNo) : "N/A"));
 | 
					 | 
				
			||||||
        Log.d(TAG, "Subtotal: " + subtotalAmount);
 | 
					 | 
				
			||||||
        Log.d(TAG, "Tax: " + taxAmount);
 | 
					 | 
				
			||||||
        Log.d(TAG, "Service Fee: " + serviceFeeAmount);
 | 
					 | 
				
			||||||
        Log.d(TAG, "Final Total: " + (subtotalAmount + taxAmount + serviceFeeAmount));
 | 
					 | 
				
			||||||
        Log.d(TAG, "======================");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    private void setupListeners() {
 | 
					    private void setupListeners() {
 | 
				
			||||||
        // Back navigation
 | 
					        // Back navigation
 | 
				
			||||||
        backNavigation.setOnClickListener(v -> {
 | 
					        backNavigation.setOnClickListener(v -> {
 | 
				
			||||||
@ -199,25 +182,35 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
            navigateBack();
 | 
					            navigateBack();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        backArrow.setOnClickListener(v -> {
 | 
				
			||||||
 | 
					            if (isNavigating) return;
 | 
				
			||||||
 | 
					            navigateBack();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        toolbarTitle.setOnClickListener(v -> {
 | 
				
			||||||
 | 
					            if (isNavigating) return;
 | 
				
			||||||
 | 
					            navigateBack();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        // Print button
 | 
					        // Print button
 | 
				
			||||||
        btnPrint.setOnClickListener(v -> {
 | 
					        printButton.setOnClickListener(v -> {
 | 
				
			||||||
            showToast("Mencetak struk...");
 | 
					            showToast("Mencetak struk...");
 | 
				
			||||||
            // TODO: Implement print functionality
 | 
					 | 
				
			||||||
            printReceipt();
 | 
					            printReceipt();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Email button
 | 
					        // Email button
 | 
				
			||||||
        btnEmail.setOnClickListener(v -> {
 | 
					        emailButton.setOnClickListener(v -> {
 | 
				
			||||||
            showToast("Mengirim email...");
 | 
					            showToast("Mengirim email...");
 | 
				
			||||||
            // TODO: Implement email functionality
 | 
					 | 
				
			||||||
            emailReceipt();
 | 
					            emailReceipt();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Finish button
 | 
					        // ✅ Finish button - Navigate to new transaction
 | 
				
			||||||
        btnFinish.setOnClickListener(v -> {
 | 
					        finishButton.setOnClickListener(v -> {
 | 
				
			||||||
            if (isNavigating) return;
 | 
					            if (isNavigating) return;
 | 
				
			||||||
            navigateToNewTransaction();
 | 
					            navigateToNewTransaction();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        Log.d(TAG, "✅ All click listeners setup");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private void calculateAmounts() {
 | 
					    private void calculateAmounts() {
 | 
				
			||||||
@ -229,7 +222,7 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // Calculate tax (11%)
 | 
					            // Calculate tax (11%)
 | 
				
			||||||
            taxAmount = Math.round(subtotalAmount * taxPercentage);
 | 
					            taxAmount = Math.round(subtotalAmount * taxPercentageValue);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // Service fee is fixed
 | 
					            // Service fee is fixed
 | 
				
			||||||
            serviceFeeAmount = 500;
 | 
					            serviceFeeAmount = 500;
 | 
				
			||||||
@ -247,48 +240,50 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private void displayReceiptData() {
 | 
					    private void displayReceiptData() {
 | 
				
			||||||
        // ✅ ENHANCED: Add debugging at start
 | 
					 | 
				
			||||||
        Log.d(TAG, "=== DISPLAYING RECEIPT DATA ===");
 | 
					        Log.d(TAG, "=== DISPLAYING RECEIPT DATA ===");
 | 
				
			||||||
        debugAllDataSources();
 | 
					        debugAllDataSources();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Merchant Information
 | 
					        // ✅ 1. Set merchant data
 | 
				
			||||||
        tvMerchantName.setText("TOKO KLONTONG PAK EKO");
 | 
					        merchantName.setText("TOKO KLONTONG PAK EKO");
 | 
				
			||||||
        tvMerchantLocation.setText("Ciputat Baru, Tangsel");
 | 
					        merchantLocation.setText("Ciputat Baru, Tangsel");
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Generate or extract transaction details
 | 
					        // ✅ 2. Set MID and TID
 | 
				
			||||||
        String tid = extractTidFromResponse();
 | 
					        String tid = extractTidFromResponse();
 | 
				
			||||||
        String transactionNumber = extractTransactionNumberFromResponse();
 | 
					        midText.setText("MID: " + tid);
 | 
				
			||||||
        String transactionDate = formatTransactionDate();
 | 
					        tidText.setText("TID: " + tid);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        tvTid.setText("TID: " + tid);
 | 
					        // ✅ 3. Set transaction number
 | 
				
			||||||
        tvTransactionNumber.setText(transactionNumber);
 | 
					        String displayTransactionNumber = extractTransactionNumberFromResponse();
 | 
				
			||||||
        tvTransactionDate.setText(transactionDate);
 | 
					        transactionNumber.setText(displayTransactionNumber);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Payment method details
 | 
					        // ✅ 4. Set transaction date
 | 
				
			||||||
        String paymentMethod = getPaymentMethodDisplay();
 | 
					        String displayDate = formatTransactionDate();
 | 
				
			||||||
        String cardTypeDisplay = getCardTypeDisplay();
 | 
					        transactionDate.setText(displayDate);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // ✅ ENHANCED: Add debugging for final values
 | 
					        // ✅ 5. Set payment method
 | 
				
			||||||
        Log.d(TAG, "Payment Method: " + paymentMethod);
 | 
					        String displayPaymentMethod = getPaymentMethodDisplay();
 | 
				
			||||||
        Log.d(TAG, "Final Card Type Display: " + cardTypeDisplay);
 | 
					        paymentMethod.setText(displayPaymentMethod);
 | 
				
			||||||
        Log.d(TAG, "================================");
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        tvPaymentMethodDetail.setText(paymentMethod);
 | 
					        // ✅ 6. ENHANCED: Set card type with comprehensive detection
 | 
				
			||||||
        tvCardType.setText(cardTypeDisplay);
 | 
					        String displayCardType = getCardTypeDisplay();
 | 
				
			||||||
 | 
					        cardType.setText(displayCardType);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Amount details
 | 
					        // ✅ 7. Set amount details
 | 
				
			||||||
        NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
 | 
					        NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        tvSubtotal.setText(formatter.format(subtotalAmount));
 | 
					        transactionTotal.setText(formatter.format(subtotalAmount));
 | 
				
			||||||
        tvTax.setText(Math.round(taxPercentage * 100) + "%");
 | 
					        taxPercentage.setText(Math.round(taxPercentageValue * 100) + "%");
 | 
				
			||||||
        tvServiceFee.setText(formatter.format(serviceFeeAmount));
 | 
					        serviceFee.setText(formatter.format(serviceFeeAmount));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Final total
 | 
					        // Final total
 | 
				
			||||||
        long finalTotal = subtotalAmount + taxAmount + serviceFeeAmount;
 | 
					        long finalTotalAmount = subtotalAmount + taxAmount + serviceFeeAmount;
 | 
				
			||||||
        tvFinalTotal.setText(formatter.format(finalTotal));
 | 
					        finalTotal.setText(formatter.format(finalTotalAmount));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Update hidden compatibility components for backward compatibility
 | 
					        Log.d(TAG, "✅ Receipt data displayed successfully");
 | 
				
			||||||
        updateCompatibilityComponents();
 | 
					        Log.d(TAG, "   Payment Method: " + displayPaymentMethod);
 | 
				
			||||||
 | 
					        Log.d(TAG, "   Card Type: " + displayCardType);
 | 
				
			||||||
 | 
					        Log.d(TAG, "   Final Total: " + formatter.format(finalTotalAmount));
 | 
				
			||||||
 | 
					        Log.d(TAG, "================================");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private String extractTidFromResponse() {
 | 
					    private String extractTidFromResponse() {
 | 
				
			||||||
@ -331,7 +326,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
            try {
 | 
					            try {
 | 
				
			||||||
                if (responseJsonData.has("transaction_time")) {
 | 
					                if (responseJsonData.has("transaction_time")) {
 | 
				
			||||||
                    String transactionTime = responseJsonData.getString("transaction_time");
 | 
					                    String transactionTime = responseJsonData.getString("transaction_time");
 | 
				
			||||||
                    // Parse and reformat if needed
 | 
					 | 
				
			||||||
                    return formatDateForDisplay(transactionTime);
 | 
					                    return formatDateForDisplay(transactionTime);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } catch (JSONException e) {
 | 
					            } catch (JSONException e) {
 | 
				
			||||||
@ -345,7 +339,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    private String formatDateForDisplay(String dateString) {
 | 
					    private String formatDateForDisplay(String dateString) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            // Try to parse the input date string and reformat
 | 
					 | 
				
			||||||
            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
 | 
					            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
 | 
				
			||||||
            SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMMM yyyy HH:mm", new Locale("id", "ID"));
 | 
					            SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMMM yyyy HH:mm", new Locale("id", "ID"));
 | 
				
			||||||
            Date date = inputFormat.parse(dateString);
 | 
					            Date date = inputFormat.parse(dateString);
 | 
				
			||||||
@ -362,32 +355,31 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private String getPaymentMethodDisplay() {
 | 
					    private String getPaymentMethodDisplay() {
 | 
				
			||||||
        if (cardType == null) return "Kartu Kredit";
 | 
					        if (cardTypeFromIntent == null) return "Kartu Kredit";
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        switch (cardType.toUpperCase()) {
 | 
					        switch (cardTypeFromIntent.toUpperCase()) {
 | 
				
			||||||
            case "EMV_MIDTRANS":
 | 
					            case "EMV_MIDTRANS":
 | 
				
			||||||
            case "IC":
 | 
					            case "IC":
 | 
				
			||||||
            case "NFC":
 | 
					            case "NFC":
 | 
				
			||||||
                return "Kartu Kredit";
 | 
					                return emvMode ? "Kartu Kredit (EMV)" : "Kartu Kredit";
 | 
				
			||||||
            case "DEBIT":
 | 
					            case "DEBIT":
 | 
				
			||||||
                return "Kartu Debit";
 | 
					                return emvMode ? "Kartu Debit (EMV)" : "Kartu Debit";
 | 
				
			||||||
            case "MAGNETIC":
 | 
					            case "MAGNETIC":
 | 
				
			||||||
                return "Kartu Magnetic";
 | 
					                return "Kartu Kredit";
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                return "Kartu Kredit";
 | 
					                return "Kartu Kredit";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ✅ ENHANCED: Comprehensive bank detection with multiple fallbacks
 | 
					    // ✅ ENHANCED: Comprehensive bank detection for EMV transactions
 | 
				
			||||||
    private String getCardTypeDisplay() {
 | 
					    private String getCardTypeDisplay() {
 | 
				
			||||||
        Log.d(TAG, "=== DETERMINING CARD TYPE DISPLAY ===");
 | 
					        Log.d(TAG, "=== DETERMINING CARD TYPE DISPLAY (EMV) ===");
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Priority 1: Get bank from Midtrans response (most accurate)
 | 
					        // Priority 1: Get bank from Midtrans response (most accurate)
 | 
				
			||||||
        if (responseJsonData != null) {
 | 
					        if (responseJsonData != null) {
 | 
				
			||||||
            Log.d(TAG, "✅ Midtrans response available, checking for bank...");
 | 
					            Log.d(TAG, "✅ Midtrans response available, checking for bank...");
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                // ✅ ENHANCED: Check multiple possible bank fields
 | 
					 | 
				
			||||||
                String bankFromResponse = null;
 | 
					                String bankFromResponse = null;
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                if (responseJsonData.has("bank")) {
 | 
					                if (responseJsonData.has("bank")) {
 | 
				
			||||||
@ -405,15 +397,11 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
                    String formattedBank = formatBankName(bankFromResponse);
 | 
					                    String formattedBank = formatBankName(bankFromResponse);
 | 
				
			||||||
                    Log.d(TAG, "✅ Bank from Midtrans response: '" + bankFromResponse + "' -> '" + formattedBank + "'");
 | 
					                    Log.d(TAG, "✅ Bank from Midtrans response: '" + bankFromResponse + "' -> '" + formattedBank + "'");
 | 
				
			||||||
                    return formattedBank;
 | 
					                    return formattedBank;
 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    Log.w(TAG, "⚠️ Bank field exists but is empty/null");
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            } catch (JSONException e) {
 | 
					            } catch (JSONException e) {
 | 
				
			||||||
                Log.e(TAG, "❌ Error extracting bank from response: " + e.getMessage());
 | 
					                Log.e(TAG, "❌ Error extracting bank from response: " + e.getMessage());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Log.w(TAG, "⚠️ No Midtrans response data available");
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Priority 2: EMV AID detection
 | 
					        // Priority 2: EMV AID detection
 | 
				
			||||||
@ -424,9 +412,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
                Log.d(TAG, "✅ Bank from EMV AID: " + bankFromAid);
 | 
					                Log.d(TAG, "✅ Bank from EMV AID: " + bankFromAid);
 | 
				
			||||||
                return bankFromAid;
 | 
					                return bankFromAid;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Log.d(TAG, "EMV AID resulted in default bank");
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Log.d(TAG, "No EMV AID available");
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Priority 3: Card BIN detection
 | 
					        // Priority 3: Card BIN detection
 | 
				
			||||||
@ -436,9 +421,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
            String bankFromBin = getBankFromComprehensiveBin(cardBin);
 | 
					            String bankFromBin = getBankFromComprehensiveBin(cardBin);
 | 
				
			||||||
            Log.d(TAG, "✅ Bank from BIN (" + cardBin + "): " + bankFromBin);
 | 
					            Log.d(TAG, "✅ Bank from BIN (" + cardBin + "): " + bankFromBin);
 | 
				
			||||||
            return bankFromBin;
 | 
					            return bankFromBin;
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Log.d(TAG, "Card number too short for BIN detection: " + 
 | 
					 | 
				
			||||||
                  (cardNo != null ? cardNo.length() : 0) + " digits");
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        Log.d(TAG, "⚠️ Using default bank: BCA");
 | 
					        Log.d(TAG, "⚠️ Using default bank: BCA");
 | 
				
			||||||
@ -446,216 +428,111 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
        return "BCA"; // Default fallback
 | 
					        return "BCA"; // Default fallback
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ✅ ENHANCED: Better bank name formatting with more variations
 | 
					    // ✅ ENHANCED: Better bank name formatting
 | 
				
			||||||
    private String formatBankName(String bankName) {
 | 
					    private String formatBankName(String bankName) {
 | 
				
			||||||
        if (bankName == null || bankName.trim().isEmpty()) {
 | 
					        if (bankName == null || bankName.trim().isEmpty()) {
 | 
				
			||||||
            Log.d(TAG, "Bank name is null/empty, using default BCA");
 | 
					 | 
				
			||||||
            return "BCA"; // Default
 | 
					            return "BCA"; // Default
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Clean and normalize input
 | 
					 | 
				
			||||||
        String formatted = bankName.trim().toUpperCase();
 | 
					        String formatted = bankName.trim().toUpperCase();
 | 
				
			||||||
        Log.d(TAG, "Formatting bank name: '" + bankName + "' -> '" + formatted + "'");
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Handle common bank name variations
 | 
					        // Handle common bank name variations
 | 
				
			||||||
        switch (formatted) {
 | 
					        switch (formatted) {
 | 
				
			||||||
            // BCA variations
 | 
					 | 
				
			||||||
            case "BCA":
 | 
					            case "BCA":
 | 
				
			||||||
            case "BANK BCA":
 | 
					            case "BANK BCA":
 | 
				
			||||||
            case "BANK CENTRAL ASIA":
 | 
					            case "BANK CENTRAL ASIA":
 | 
				
			||||||
            case "PT BANK CENTRAL ASIA TBK":
 | 
					 | 
				
			||||||
                return "BCA";
 | 
					                return "BCA";
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            // MANDIRI variations  
 | 
					 | 
				
			||||||
            case "MANDIRI":
 | 
					            case "MANDIRI":
 | 
				
			||||||
            case "BANK MANDIRI":
 | 
					            case "BANK MANDIRI":
 | 
				
			||||||
            case "PT BANK MANDIRI (PERSERO) TBK":
 | 
					                return "Mandiri";
 | 
				
			||||||
            case "MANDIRI BANK":
 | 
					 | 
				
			||||||
                return "MANDIRI";
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            // BNI variations
 | 
					 | 
				
			||||||
            case "BNI":
 | 
					            case "BNI":
 | 
				
			||||||
            case "BANK BNI":
 | 
					            case "BANK BNI":
 | 
				
			||||||
            case "BANK NEGARA INDONESIA":
 | 
					            case "BANK NEGARA INDONESIA":
 | 
				
			||||||
            case "PT BANK NEGARA INDONESIA (PERSERO) TBK":
 | 
					 | 
				
			||||||
                return "BNI";
 | 
					                return "BNI";
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            // BRI variations
 | 
					 | 
				
			||||||
            case "BRI":
 | 
					            case "BRI":
 | 
				
			||||||
            case "BANK BRI":
 | 
					            case "BANK BRI":
 | 
				
			||||||
            case "BANK RAKYAT INDONESIA":
 | 
					            case "BANK RAKYAT INDONESIA":
 | 
				
			||||||
            case "PT BANK RAKYAT INDONESIA (PERSERO) TBK":
 | 
					 | 
				
			||||||
                return "BRI";
 | 
					                return "BRI";
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            // CIMB variations
 | 
					 | 
				
			||||||
            case "CIMB":
 | 
					            case "CIMB":
 | 
				
			||||||
            case "CIMB NIAGA":
 | 
					            case "CIMB NIAGA":
 | 
				
			||||||
            case "BANK CIMB NIAGA":
 | 
					            case "BANK CIMB NIAGA":
 | 
				
			||||||
            case "PT BANK CIMB NIAGA TBK":
 | 
					                return "CIMB Niaga";
 | 
				
			||||||
                return "CIMB NIAGA";
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            // DANAMON variations
 | 
					 | 
				
			||||||
            case "DANAMON":
 | 
					            case "DANAMON":
 | 
				
			||||||
            case "BANK DANAMON":
 | 
					            case "BANK DANAMON":
 | 
				
			||||||
            case "PT BANK DANAMON INDONESIA TBK":
 | 
					                return "Danamon";
 | 
				
			||||||
                return "DANAMON";
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            // PERMATA variations
 | 
					 | 
				
			||||||
            case "PERMATA":
 | 
					            case "PERMATA":
 | 
				
			||||||
            case "BANK PERMATA":
 | 
					            case "BANK PERMATA":
 | 
				
			||||||
            case "PT BANK PERMATA TBK":
 | 
					                return "Permata";
 | 
				
			||||||
                return "PERMATA";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
            // MEGA variations
 | 
					 | 
				
			||||||
            case "MEGA":
 | 
					 | 
				
			||||||
            case "BANK MEGA":
 | 
					 | 
				
			||||||
            case "PT BANK MEGA TBK":
 | 
					 | 
				
			||||||
                return "MEGA";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
            // BTN variations
 | 
					 | 
				
			||||||
            case "BTN":
 | 
					 | 
				
			||||||
            case "BANK BTN":
 | 
					 | 
				
			||||||
            case "BANK TABUNGAN NEGARA":
 | 
					 | 
				
			||||||
                return "BTN";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
            // MAYBANK variations
 | 
					 | 
				
			||||||
            case "MAYBANK":
 | 
					 | 
				
			||||||
            case "MAYBANK INDONESIA":
 | 
					 | 
				
			||||||
            case "PT BANK MAYBANK INDONESIA TBK":
 | 
					 | 
				
			||||||
                return "MAYBANK";
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                // For unknown banks, return as-is but log it
 | 
					                return capitalizeFirstLetter(bankName);
 | 
				
			||||||
                Log.d(TAG, "Unknown bank name, returning as-is: " + formatted);
 | 
					 | 
				
			||||||
                return formatted;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private String getBankFromBin(String bin) {
 | 
					 | 
				
			||||||
        // Indonesian Bank BIN mapping - return bank names
 | 
					 | 
				
			||||||
        // BCA
 | 
					 | 
				
			||||||
        if (bin.startsWith("4621") || bin.startsWith("4699") || 
 | 
					 | 
				
			||||||
            bin.startsWith("5221") || bin.startsWith("6277")) return "BCA";
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // MANDIRI  
 | 
					 | 
				
			||||||
        if (bin.startsWith("4313") || bin.startsWith("5573") || 
 | 
					 | 
				
			||||||
            bin.startsWith("6011") || bin.startsWith("6234")) return "MANDIRI";
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // BNI
 | 
					 | 
				
			||||||
        if (bin.startsWith("4603") || bin.startsWith("1946") || 
 | 
					 | 
				
			||||||
            bin.startsWith("5264")) return "BNI";
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // BRI
 | 
					 | 
				
			||||||
        if (bin.startsWith("4578") || bin.startsWith("4479") || 
 | 
					 | 
				
			||||||
            bin.startsWith("5208")) return "BRI";
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // CIMB NIAGA
 | 
					 | 
				
			||||||
        if (bin.startsWith("4599") || bin.startsWith("5249")) return "CIMB NIAGA";
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // DANAMON
 | 
					 | 
				
			||||||
        if (bin.startsWith("4055") || bin.startsWith("5108")) return "DANAMON";
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // Generic fallback based on first digit
 | 
					 | 
				
			||||||
        if (bin.startsWith("4") || bin.startsWith("5")) {
 | 
					 | 
				
			||||||
            // Check more specific patterns if needed
 | 
					 | 
				
			||||||
            return "BCA"; // Default for unknown Visa/Mastercard
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        return "BCA"; // Ultimate fallback
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    private String getBankFromAid(String aid) {
 | 
					    private String getBankFromAid(String aid) {
 | 
				
			||||||
        // AID to Indonesian bank mapping
 | 
					        // AID to Indonesian bank mapping
 | 
				
			||||||
        // Note: AID identifies card scheme, but we want bank name
 | 
					 | 
				
			||||||
        // This is best-effort mapping, real bank detection needs BIN
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (aid.contains("A0000000031010")) {
 | 
					        if (aid.contains("A0000000031010")) {
 | 
				
			||||||
            // VISA - check if we have card number for better detection
 | 
					            // VISA - check if we have card number for better detection
 | 
				
			||||||
            if (cardNo != null && cardNo.length() >= 6) {
 | 
					            if (cardNo != null && cardNo.length() >= 6) {
 | 
				
			||||||
                return getBankFromBin(cardNo.substring(0, 6));
 | 
					                return getBankFromComprehensiveBin(cardNo.substring(0, 6));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return "BCA"; // Default for VISA
 | 
					            return "BCA"; // Default for VISA
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (aid.contains("A0000000041010")) {
 | 
					        if (aid.contains("A0000000041010")) {
 | 
				
			||||||
            // MASTERCARD - check if we have card number for better detection  
 | 
					            // MASTERCARD
 | 
				
			||||||
            if (cardNo != null && cardNo.length() >= 6) {
 | 
					            if (cardNo != null && cardNo.length() >= 6) {
 | 
				
			||||||
                return getBankFromBin(cardNo.substring(0, 6));
 | 
					                return getBankFromComprehensiveBin(cardNo.substring(0, 6));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return "MANDIRI"; // Default for Mastercard
 | 
					            return "Mandiri"; // Default for Mastercard
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return "BCA"; // Ultimate fallback
 | 
					        return "BCA"; // Ultimate fallback
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ✅ ENHANCED: More comprehensive Indonesian bank BIN mapping
 | 
					    // ✅ ENHANCED: Comprehensive Indonesian bank BIN mapping
 | 
				
			||||||
    private String getBankFromComprehensiveBin(String bin) {
 | 
					    private String getBankFromComprehensiveBin(String bin) {
 | 
				
			||||||
        if (bin == null || bin.length() < 4) {
 | 
					        if (bin == null || bin.length() < 4) {
 | 
				
			||||||
            return "BCA"; // Default
 | 
					            return "BCA"; // Default
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // More comprehensive Indonesian bank BIN mapping
 | 
					 | 
				
			||||||
        String bin4 = bin.substring(0, 4);
 | 
					        String bin4 = bin.substring(0, 4);
 | 
				
			||||||
        String bin6 = bin.length() >= 6 ? bin.substring(0, 6) : bin4;
 | 
					        String bin6 = bin.length() >= 6 ? bin.substring(0, 6) : bin4;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // BCA patterns
 | 
					        // BCA patterns
 | 
				
			||||||
        if (bin4.equals("4621") || bin4.equals("4699") || bin4.equals("5221") || bin4.equals("6277") ||
 | 
					        if (bin4.equals("4621") || bin4.equals("4699") || bin4.equals("5221") || bin4.equals("6277")) {
 | 
				
			||||||
            bin6.startsWith("462117") || bin6.startsWith("469929") || bin6.startsWith("522156")) {
 | 
					 | 
				
			||||||
            return "BCA";
 | 
					            return "BCA";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // MANDIRI patterns
 | 
					        // MANDIRI patterns
 | 
				
			||||||
        if (bin4.equals("4313") || bin4.equals("5573") || bin4.equals("6011") || bin4.equals("6234") ||
 | 
					        if (bin4.equals("4313") || bin4.equals("5573") || bin4.equals("6011") || bin4.equals("6234")) {
 | 
				
			||||||
            bin4.equals("5406") || bin4.equals("4097") || bin6.startsWith("431360") || bin6.startsWith("557347")) {
 | 
					            return "Mandiri";
 | 
				
			||||||
            return "MANDIRI";
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // BNI patterns  
 | 
					        // BNI patterns  
 | 
				
			||||||
        if (bin4.equals("4603") || bin4.equals("1946") || bin4.equals("5264") ||
 | 
					        if (bin4.equals("4603") || bin4.equals("1946") || bin4.equals("5264")) {
 | 
				
			||||||
            bin6.startsWith("460347") || bin6.startsWith("194637") || bin6.startsWith("526435")) {
 | 
					 | 
				
			||||||
            return "BNI";
 | 
					            return "BNI";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // BRI patterns
 | 
					        // BRI patterns
 | 
				
			||||||
        if (bin4.equals("4578") || bin4.equals("4479") || bin4.equals("5208") || bin4.equals("4486") ||
 | 
					        if (bin4.equals("4578") || bin4.equals("4479") || bin4.equals("5208")) {
 | 
				
			||||||
            bin6.startsWith("457865") || bin6.startsWith("447935") || bin6.startsWith("520834")) {
 | 
					 | 
				
			||||||
            return "BRI";
 | 
					            return "BRI";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // CIMB NIAGA patterns
 | 
					        // CIMB NIAGA patterns
 | 
				
			||||||
        if (bin4.equals("4599") || bin4.equals("5249") || bin4.equals("4543") ||
 | 
					        if (bin4.equals("4599") || bin4.equals("5249")) {
 | 
				
			||||||
            bin6.startsWith("459923") || bin6.startsWith("524901") || bin6.startsWith("454347")) {
 | 
					            return "CIMB Niaga";
 | 
				
			||||||
            return "CIMB NIAGA";
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // DANAMON patterns
 | 
					        // DANAMON patterns
 | 
				
			||||||
        if (bin4.equals("4055") || bin4.equals("5108") || bin4.equals("4631") ||
 | 
					        if (bin4.equals("4055") || bin4.equals("5108")) {
 | 
				
			||||||
            bin6.startsWith("405512") || bin6.startsWith("510834") || bin6.startsWith("463178")) {
 | 
					            return "Danamon";
 | 
				
			||||||
            return "DANAMON";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // PERMATA patterns
 | 
					 | 
				
			||||||
        if (bin4.equals("5399") || bin4.equals("4723") || 
 | 
					 | 
				
			||||||
            bin6.startsWith("539923") || bin6.startsWith("472345")) {
 | 
					 | 
				
			||||||
            return "PERMATA";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // MEGA patterns
 | 
					 | 
				
			||||||
        if (bin4.equals("5221") || bin4.equals("4128") ||
 | 
					 | 
				
			||||||
            bin6.startsWith("522145") || bin6.startsWith("412834")) {
 | 
					 | 
				
			||||||
            return "MEGA";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // BTN patterns
 | 
					 | 
				
			||||||
        if (bin4.equals("4058") || bin4.equals("5258") ||
 | 
					 | 
				
			||||||
            bin6.startsWith("405834") || bin6.startsWith("525823")) {
 | 
					 | 
				
			||||||
            return "BTN";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // MAYBANK patterns
 | 
					 | 
				
			||||||
        if (bin4.equals("5108") || bin4.equals("4055") ||
 | 
					 | 
				
			||||||
            bin6.startsWith("510856") || bin6.startsWith("405523")) {
 | 
					 | 
				
			||||||
            return "MAYBANK";
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Default fallback
 | 
					        // Default fallback
 | 
				
			||||||
@ -663,47 +540,20 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
        return "BCA";
 | 
					        return "BCA";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Update hidden components for backward compatibility
 | 
					    private String capitalizeFirstLetter(String input) {
 | 
				
			||||||
    private void updateCompatibilityComponents() {
 | 
					        if (input == null || input.isEmpty()) {
 | 
				
			||||||
        if (tvAmount != null) {
 | 
					            return input;
 | 
				
			||||||
            NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
 | 
					        }
 | 
				
			||||||
            tvAmount.setText("Rp " + formatter.format(subtotalAmount + taxAmount + serviceFeeAmount));
 | 
					        return input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        if (tvStatus != null) {
 | 
					    // ✅ Debug methods
 | 
				
			||||||
            tvStatus.setText(paymentSuccess ? "SUCCESS" : "FAILED");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (tvReference != null) {
 | 
					 | 
				
			||||||
            tvReference.setText(referenceId != null ? referenceId : "N/A");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (tvCardInfo != null) {
 | 
					 | 
				
			||||||
            tvCardInfo.setText(cardNo != null ? maskCardNumber(cardNo) : "N/A");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (tvPaymentMethod != null) {
 | 
					 | 
				
			||||||
            tvPaymentMethod.setText(getPaymentMethodDisplay());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (tvTransactionId != null) {
 | 
					 | 
				
			||||||
            tvTransactionId.setText(extractTransactionNumberFromResponse());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (tvTimestamp != null) {
 | 
					 | 
				
			||||||
            tvTimestamp.setText(formatTransactionDate());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // ✅ ENHANCED: Add method to debug all data sources
 | 
					 | 
				
			||||||
    private void debugAllDataSources() {
 | 
					    private void debugAllDataSources() {
 | 
				
			||||||
        Log.d(TAG, "=== DEBUGGING ALL DATA SOURCES ===");
 | 
					        Log.d(TAG, "=== DEBUGGING ALL DATA SOURCES ===");
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Check Midtrans response
 | 
					 | 
				
			||||||
        if (responseJsonData != null) {
 | 
					        if (responseJsonData != null) {
 | 
				
			||||||
            Log.d(TAG, "Midtrans Response Available:");
 | 
					            Log.d(TAG, "Midtrans Response Available:");
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                // Log all keys and their values
 | 
					 | 
				
			||||||
                java.util.Iterator<String> keys = responseJsonData.keys();
 | 
					                java.util.Iterator<String> keys = responseJsonData.keys();
 | 
				
			||||||
                while (keys.hasNext()) {
 | 
					                while (keys.hasNext()) {
 | 
				
			||||||
                    String key = keys.next();
 | 
					                    String key = keys.next();
 | 
				
			||||||
@ -717,63 +567,35 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
            Log.d(TAG, "❌ No Midtrans Response Data");
 | 
					            Log.d(TAG, "❌ No Midtrans Response Data");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Check EMV data
 | 
					 | 
				
			||||||
        Log.d(TAG, "EMV Data:");
 | 
					        Log.d(TAG, "EMV Data:");
 | 
				
			||||||
        Log.d(TAG, "  Card Number: " + (cardNo != null ? maskCardNumber(cardNo) : "null"));
 | 
					        Log.d(TAG, "  Card Number: " + (cardNo != null ? maskCardNumber(cardNo) : "null"));
 | 
				
			||||||
        Log.d(TAG, "  EMV AID: " + emvAid);
 | 
					        Log.d(TAG, "  EMV AID: " + emvAid);
 | 
				
			||||||
        Log.d(TAG, "  EMV Cardholder: " + emvCardholderName);
 | 
					        Log.d(TAG, "  EMV Cardholder: " + emvCardholderName);
 | 
				
			||||||
        Log.d(TAG, "  EMV Expiry: " + emvExpiry);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        // Check card type
 | 
					 | 
				
			||||||
        Log.d(TAG, "Card Type: " + cardType);
 | 
					 | 
				
			||||||
        Log.d(TAG, "  EMV Mode: " + emvMode);
 | 
					        Log.d(TAG, "  EMV Mode: " + emvMode);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        Log.d(TAG, "==================================");
 | 
					        Log.d(TAG, "==================================");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // ✅ ENHANCED: Method to manually set bank for testing
 | 
					    private void logTransactionDetails() {
 | 
				
			||||||
    public void debugSetBank(String bankName) {
 | 
					        Log.d(TAG, "=== RECEIPT DETAILS ===");
 | 
				
			||||||
        try {
 | 
					        Log.d(TAG, "Reference ID: " + referenceId);
 | 
				
			||||||
            if (responseJsonData == null) {
 | 
					        Log.d(TAG, "Card Number: " + (cardNo != null ? maskCardNumber(cardNo) : "N/A"));
 | 
				
			||||||
                responseJsonData = new JSONObject();
 | 
					        Log.d(TAG, "Subtotal: " + subtotalAmount);
 | 
				
			||||||
            }
 | 
					        Log.d(TAG, "Tax: " + taxAmount);
 | 
				
			||||||
            responseJsonData.put("bank", bankName);
 | 
					        Log.d(TAG, "Service Fee: " + serviceFeeAmount);
 | 
				
			||||||
            Log.d(TAG, "Debug: Manually set bank to: " + bankName);
 | 
					        Log.d(TAG, "Final Total: " + (subtotalAmount + taxAmount + serviceFeeAmount));
 | 
				
			||||||
            
 | 
					        Log.d(TAG, "======================");
 | 
				
			||||||
            // Refresh display
 | 
					 | 
				
			||||||
            displayReceiptData();
 | 
					 | 
				
			||||||
        } catch (JSONException e) {
 | 
					 | 
				
			||||||
            Log.e(TAG, "Error setting debug bank: " + e.getMessage());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // ✅ ENHANCED: Method to test different bank displays
 | 
					 | 
				
			||||||
    private void testBankDisplay() {
 | 
					 | 
				
			||||||
        // Test different bank values
 | 
					 | 
				
			||||||
        String[] testBanks = {"BCA", "MANDIRI", "BNI", "BRI", "CIMB NIAGA"};
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        for (String bank : testBanks) {
 | 
					 | 
				
			||||||
            debugSetBank(bank);
 | 
					 | 
				
			||||||
            Log.d(TAG, "Test bank '" + bank + "' -> Display: " + getCardTypeDisplay());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // ✅ ENHANCED: Get last response for debugging
 | 
					 | 
				
			||||||
    public JSONObject getLastMidtransResponse() {
 | 
					 | 
				
			||||||
        return responseJsonData;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Action Methods
 | 
					    // Action Methods
 | 
				
			||||||
    private void printReceipt() {
 | 
					    private void printReceipt() {
 | 
				
			||||||
        Log.d(TAG, "Print receipt requested");
 | 
					        Log.d(TAG, "Print receipt requested");
 | 
				
			||||||
        // TODO: Implement actual printing logic
 | 
					 | 
				
			||||||
        showToast("Fitur cetak akan segera tersedia");
 | 
					        showToast("Fitur cetak akan segera tersedia");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    private void emailReceipt() {
 | 
					    private void emailReceipt() {
 | 
				
			||||||
        Log.d(TAG, "Email receipt requested");
 | 
					        Log.d(TAG, "Email receipt requested");
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Create email intent
 | 
					 | 
				
			||||||
        Intent emailIntent = new Intent(Intent.ACTION_SEND);
 | 
					        Intent emailIntent = new Intent(Intent.ACTION_SEND);
 | 
				
			||||||
        emailIntent.setType("text/plain");
 | 
					        emailIntent.setType("text/plain");
 | 
				
			||||||
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Struk Pembayaran - " + extractTransactionNumberFromResponse());
 | 
					        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Struk Pembayaran - " + extractTransactionNumberFromResponse());
 | 
				
			||||||
@ -791,9 +613,8 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
        StringBuilder content = new StringBuilder();
 | 
					        StringBuilder content = new StringBuilder();
 | 
				
			||||||
        NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
 | 
					        NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        content.append("STRUK PEMBAYARAN\n");
 | 
					        content.append("STRUK PEMBAYARAN EMV/CARD\n");
 | 
				
			||||||
        content.append("================\n\n");
 | 
					        content.append("==========================\n\n");
 | 
				
			||||||
        content.append("Payvora PRO\n");
 | 
					 | 
				
			||||||
        content.append("TOKO KLONTONG PAK EKO\n");
 | 
					        content.append("TOKO KLONTONG PAK EKO\n");
 | 
				
			||||||
        content.append("Ciputat Baru, Tangsel\n\n");
 | 
					        content.append("Ciputat Baru, Tangsel\n\n");
 | 
				
			||||||
        content.append("TID: ").append(extractTidFromResponse()).append("\n");
 | 
					        content.append("TID: ").append(extractTidFromResponse()).append("\n");
 | 
				
			||||||
@ -801,6 +622,13 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
        content.append("Tanggal: ").append(formatTransactionDate()).append("\n");
 | 
					        content.append("Tanggal: ").append(formatTransactionDate()).append("\n");
 | 
				
			||||||
        content.append("Metode: ").append(getPaymentMethodDisplay()).append("\n");
 | 
					        content.append("Metode: ").append(getPaymentMethodDisplay()).append("\n");
 | 
				
			||||||
        content.append("Jenis Kartu: ").append(getCardTypeDisplay()).append("\n\n");
 | 
					        content.append("Jenis Kartu: ").append(getCardTypeDisplay()).append("\n\n");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (emvMode && emvCardholderName != null) {
 | 
				
			||||||
 | 
					            content.append("DETAIL EMV:\n");
 | 
				
			||||||
 | 
					            content.append("Cardholder: ").append(emvCardholderName).append("\n");
 | 
				
			||||||
 | 
					            content.append("AID: ").append(emvAid).append("\n\n");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        content.append("RINCIAN PEMBAYARAN:\n");
 | 
					        content.append("RINCIAN PEMBAYARAN:\n");
 | 
				
			||||||
        content.append("Total Transaksi: Rp ").append(formatter.format(subtotalAmount)).append("\n");
 | 
					        content.append("Total Transaksi: Rp ").append(formatter.format(subtotalAmount)).append("\n");
 | 
				
			||||||
        content.append("Pajak (11%): Rp ").append(formatter.format(taxAmount)).append("\n");
 | 
					        content.append("Pajak (11%): Rp ").append(formatter.format(taxAmount)).append("\n");
 | 
				
			||||||
@ -824,7 +652,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
    private void navigateToNewTransaction() {
 | 
					    private void navigateToNewTransaction() {
 | 
				
			||||||
        if (isNavigating) return;
 | 
					        if (isNavigating) return;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Show confirmation dialog
 | 
					 | 
				
			||||||
        new AlertDialog.Builder(this)
 | 
					        new AlertDialog.Builder(this)
 | 
				
			||||||
            .setTitle("Transaksi Baru")
 | 
					            .setTitle("Transaksi Baru")
 | 
				
			||||||
            .setMessage("Apakah Anda ingin melakukan transaksi baru?")
 | 
					            .setMessage("Apakah Anda ingin melakukan transaksi baru?")
 | 
				
			||||||
@ -839,7 +666,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
        Log.d(TAG, "=== NAVIGATING TO NEW TRANSACTION ===");
 | 
					        Log.d(TAG, "=== NAVIGATING TO NEW TRANSACTION ===");
 | 
				
			||||||
        isNavigating = true;
 | 
					        isNavigating = true;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Add small delay for better UX
 | 
					 | 
				
			||||||
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
 | 
					        new Handler(Looper.getMainLooper()).postDelayed(() -> {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                Intent intent = new Intent(this, CreateTransactionActivity.class);
 | 
					                Intent intent = new Intent(this, CreateTransactionActivity.class);
 | 
				
			||||||
@ -874,6 +700,7 @@ public class ResultTransactionActivity extends AppCompatActivity {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        navigateBack();
 | 
					        navigateBack();
 | 
				
			||||||
 | 
					        super.onBackPressed();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
				
			|||||||
@ -104,7 +104,7 @@
 | 
				
			|||||||
                        <TextView
 | 
					                        <TextView
 | 
				
			||||||
                            android:layout_width="wrap_content"
 | 
					                            android:layout_width="wrap_content"
 | 
				
			||||||
                            android:layout_height="wrap_content"
 | 
					                            android:layout_height="wrap_content"
 | 
				
			||||||
                            android:text="EDC "
 | 
					                            android:text="Payvora "
 | 
				
			||||||
                            android:textColor="#E31937"
 | 
					                            android:textColor="#E31937"
 | 
				
			||||||
                            android:textSize="24sp"
 | 
					                            android:textSize="24sp"
 | 
				
			||||||
                            android:textStyle="bold"
 | 
					                            android:textStyle="bold"
 | 
				
			||||||
@ -113,7 +113,7 @@
 | 
				
			|||||||
                        <TextView
 | 
					                        <TextView
 | 
				
			||||||
                            android:layout_width="wrap_content"
 | 
					                            android:layout_width="wrap_content"
 | 
				
			||||||
                            android:layout_height="wrap_content"
 | 
					                            android:layout_height="wrap_content"
 | 
				
			||||||
                            android:text="Merchant"
 | 
					                            android:text="PRO"
 | 
				
			||||||
                            android:textColor="#3F51B5"
 | 
					                            android:textColor="#3F51B5"
 | 
				
			||||||
                            android:textSize="24sp"
 | 
					                            android:textSize="24sp"
 | 
				
			||||||
                            android:textStyle="bold"
 | 
					                            android:textStyle="bold"
 | 
				
			||||||
@ -121,15 +121,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    </LinearLayout>
 | 
					                    </LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <TextView
 | 
					 | 
				
			||||||
                        android:layout_width="wrap_content"
 | 
					 | 
				
			||||||
                        android:layout_height="wrap_content"
 | 
					 | 
				
			||||||
                        android:text="BANK BRI"
 | 
					 | 
				
			||||||
                        android:textColor="#333333"
 | 
					 | 
				
			||||||
                        android:textSize="12sp"
 | 
					 | 
				
			||||||
                        android:fontFamily="@font/inter"
 | 
					 | 
				
			||||||
                        android:layout_marginTop="2dp"/>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                </LinearLayout>
 | 
					                </LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <!-- Merchant Info -->
 | 
					                <!-- Merchant Info -->
 | 
				
			||||||
@ -168,46 +159,36 @@
 | 
				
			|||||||
                    android:layout_width="match_parent"
 | 
					                    android:layout_width="match_parent"
 | 
				
			||||||
                    android:layout_height="wrap_content"
 | 
					                    android:layout_height="wrap_content"
 | 
				
			||||||
                    android:orientation="horizontal"
 | 
					                    android:orientation="horizontal"
 | 
				
			||||||
 | 
					                    android:gravity="center"
 | 
				
			||||||
                    android:layout_marginBottom="8dp">
 | 
					                    android:layout_marginBottom="8dp">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <TextView
 | 
					 | 
				
			||||||
                        android:layout_width="0dp"
 | 
					 | 
				
			||||||
                        android:layout_height="wrap_content"
 | 
					 | 
				
			||||||
                        android:layout_weight="1"
 | 
					 | 
				
			||||||
                        android:text="MID: "
 | 
					 | 
				
			||||||
                        android:textColor="#666666"
 | 
					 | 
				
			||||||
                        android:textSize="12sp"
 | 
					 | 
				
			||||||
                        android:fontFamily="@font/inter"/>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <TextView
 | 
					                    <TextView
 | 
				
			||||||
                        android:id="@+id/mid_text"
 | 
					                        android:id="@+id/mid_text"
 | 
				
			||||||
                        android:layout_width="0dp"
 | 
					                        android:layout_width="wrap_content"
 | 
				
			||||||
                        android:layout_height="wrap_content"
 | 
					                        android:layout_height="wrap_content"
 | 
				
			||||||
                        android:layout_weight="1"
 | 
					                        android:text="MID:12345678901"
 | 
				
			||||||
                        android:text="1234567890"
 | 
					 | 
				
			||||||
                        android:textColor="#333333"
 | 
					                        android:textColor="#333333"
 | 
				
			||||||
                        android:textSize="12sp"
 | 
					                        android:textSize="12sp"
 | 
				
			||||||
                        android:fontFamily="@font/inter"/>
 | 
					                        android:fontFamily="@font/inter"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <!-- Vertical Separator -->
 | 
				
			||||||
                    <TextView
 | 
					                    <TextView
 | 
				
			||||||
                        android:layout_width="0dp"
 | 
					                        android:layout_width="wrap_content"
 | 
				
			||||||
                        android:layout_height="wrap_content"
 | 
					                        android:layout_height="wrap_content"
 | 
				
			||||||
                        android:layout_weight="1"
 | 
					                        android:text="  |  "
 | 
				
			||||||
                        android:text="TID: "
 | 
					                        android:textColor="#999999"
 | 
				
			||||||
                        android:textColor="#666666"
 | 
					 | 
				
			||||||
                        android:textSize="12sp"
 | 
					                        android:textSize="12sp"
 | 
				
			||||||
                        android:fontFamily="@font/inter"/>
 | 
					                        android:fontFamily="@font/inter"
 | 
				
			||||||
 | 
					                        android:paddingHorizontal="8dp"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <TextView
 | 
					                    <TextView
 | 
				
			||||||
                        android:id="@+id/tid_text"
 | 
					                        android:id="@+id/tid_text"
 | 
				
			||||||
                        android:layout_width="0dp"
 | 
					                        android:layout_width="wrap_content"
 | 
				
			||||||
                        android:layout_height="wrap_content"
 | 
					                        android:layout_height="wrap_content"
 | 
				
			||||||
                        android:layout_weight="1"
 | 
					                        android:text="TID:12345678901"
 | 
				
			||||||
                        android:text="1234567890"
 | 
					 | 
				
			||||||
                        android:textColor="#333333"
 | 
					                        android:textColor="#333333"
 | 
				
			||||||
                        android:textSize="12sp"
 | 
					                        android:textSize="12sp"
 | 
				
			||||||
                        android:fontFamily="@font/inter"/>
 | 
					                        android:fontFamily="@font/inter"/>
 | 
				
			||||||
 | 
					 | 
				
			||||||
                </LinearLayout>
 | 
					                </LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <!-- Separator Line -->
 | 
					                <!-- Separator Line -->
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user