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.net.URL;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.example.bdkipoc.cetakulang.ReprintActivity;
|
||||
|
||||
@ -52,6 +54,28 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
private LinearLayout emailButton;
|
||||
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
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -118,10 +142,27 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
finishButton.setOnClickListener(v -> handleFinish());
|
||||
}
|
||||
|
||||
/**
|
||||
* ✅ ENHANCED: Load transaction data with support for both EMV/Card and QRIS
|
||||
*/
|
||||
private void loadTransactionData() {
|
||||
Intent intent = getIntent();
|
||||
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
|
||||
String amount = intent.getStringExtra("transaction_amount");
|
||||
@ -135,99 +176,154 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
String createdAt = intent.getStringExtra("created_at");
|
||||
String paymentMethodStr = intent.getStringExtra("payment_method");
|
||||
String cardTypeStr = intent.getStringExtra("card_type");
|
||||
String channelCode = intent.getStringExtra("channel_code");
|
||||
String channelCategory = intent.getStringExtra("channel_category");
|
||||
String acquirer = intent.getStringExtra("acquirer");
|
||||
String mid = intent.getStringExtra("mid");
|
||||
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.d("ReceiptActivity", "🔍 RECEIVED DATA:");
|
||||
Log.d("ReceiptActivity", " amount: " + amount);
|
||||
Log.d("ReceiptActivity", " referenceId: " + referenceId);
|
||||
Log.d("ReceiptActivity", " orderId: " + orderId);
|
||||
Log.d("ReceiptActivity", " channelCode: " + channelCode);
|
||||
Log.d("ReceiptActivity", " acquirer (from intent): " + acquirer);
|
||||
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
|
||||
merchantName.setText(merchantNameStr != null ? merchantNameStr : "Marcel Panjaitan");
|
||||
merchantLocation.setText(merchantLocationStr != null ? merchantLocationStr : "Jakarta, Indonesia");
|
||||
merchantName.setText(merchantNameStr != null ? merchantNameStr : "TOKO KLONTONG PAK EKO");
|
||||
merchantLocation.setText(merchantLocationStr != null ? merchantLocationStr : "Ciputat Baru, Tangsel");
|
||||
|
||||
// 2. Set MID and TID
|
||||
midText.setText(mid != null ? mid : "71000026521");
|
||||
tidText.setText(tid != null ? tid : "73001500");
|
||||
midText.setText("MID: " + (mid != null ? mid : "123456789901"));
|
||||
tidText.setText("TID: " + (tid != null ? tid : "123456789901"));
|
||||
|
||||
// 3. Set transaction number
|
||||
String displayTransactionNumber = null;
|
||||
if (referenceId != null && !referenceId.isEmpty()) {
|
||||
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");
|
||||
String displayTransactionNumber = getDisplayTransactionNumber(referenceId, transactionId, orderId);
|
||||
transactionNumber.setText(displayTransactionNumber);
|
||||
|
||||
// 4. Set transaction date
|
||||
String displayDate = null;
|
||||
if (createdAt != null && !createdAt.isEmpty()) {
|
||||
displayDate = formatDateFromCreatedAt(createdAt);
|
||||
} else if (transactionDateStr != null && !transactionDateStr.isEmpty()) {
|
||||
displayDate = transactionDateStr;
|
||||
} else {
|
||||
displayDate = getCurrentDateTime();
|
||||
}
|
||||
String displayDate = getDisplayTransactionDate(createdAt, transactionDateStr, isEmvTransaction);
|
||||
transactionDate.setText(displayDate);
|
||||
|
||||
// 5. Set payment method
|
||||
String displayPaymentMethod = getPaymentMethodFromChannelCode(channelCode, paymentMethodStr);
|
||||
// 5. ✅ ENHANCED: Set payment method based on transaction type
|
||||
String displayPaymentMethod = getDisplayPaymentMethod(channelCode, paymentMethodStr, isEmvTransaction, emvMode);
|
||||
paymentMethod.setText(displayPaymentMethod);
|
||||
|
||||
// 6. ✅ IMPROVED: Enhanced card type detection for QRIS
|
||||
String displayCardType = null;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 6. ✅ ENHANCED: Set card type with EMV and QRIS priority
|
||||
String displayCardType = getDisplayCardType(cardTypeStr, acquirer, channelCode, isEmvTransaction,
|
||||
isQrisTransaction, midtransResponse, referenceId);
|
||||
cardType.setText(displayCardType);
|
||||
Log.d("ReceiptActivity", "💳 FINAL CARD TYPE: " + displayCardType);
|
||||
|
||||
// 7. Format and set amounts
|
||||
setAmountData(amount, grossAmount);
|
||||
// 7. ✅ Format and set amounts with proper calculation
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatDateFromCreatedAt(String createdAt) {
|
||||
try {
|
||||
// Input format from database: "yyyy-MM-dd HH:mm:ss"
|
||||
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
|
||||
|
||||
// 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);
|
||||
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
|
||||
*/
|
||||
@ -291,6 +420,78 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
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) {
|
||||
// STEP 1: If we have a valid acquirer that's not generic "qris", use it
|
||||
if (acquirer != null && !acquirer.isEmpty() && !acquirer.equalsIgnoreCase("qris")) {
|
||||
@ -299,88 +500,14 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
Log.d("ReceiptActivity", "🔍 Mapping acquirer: '" + acquirer + "' -> '" + acq + "'");
|
||||
|
||||
// ✅ 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) {
|
||||
// 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
|
||||
case "visa": return "Visa";
|
||||
case "mastercard":
|
||||
@ -740,6 +867,78 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
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) {
|
||||
if (input == null || input.isEmpty()) {
|
||||
return input;
|
||||
@ -758,51 +957,79 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
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;
|
||||
|
||||
Log.d("ReceiptActivity", "Setting amount data - amount: " + amount +
|
||||
", grossAmount: " + grossAmount + ", using: " + amountToUse);
|
||||
Log.d("ReceiptActivity", "Setting enhanced amount data - amount: " + amount +
|
||||
", grossAmount: " + grossAmount + ", using: " + amountToUse +
|
||||
", isEMV: " + isEmvTransaction + ", isQRIS: " + isQrisTransaction);
|
||||
|
||||
if (amountToUse != null) {
|
||||
try {
|
||||
// Clean and parse the amount
|
||||
String cleanAmount = cleanAmountString(amountToUse);
|
||||
Log.d("ReceiptActivity", "Cleaned amount: " + cleanAmount);
|
||||
|
||||
// Parse as long integer (Indonesian Rupiah doesn't use decimal cents)
|
||||
long amountLong = Long.parseLong(cleanAmount);
|
||||
|
||||
// Set transaction total
|
||||
transactionTotal.setText("Rp " + formatCurrency(amountLong));
|
||||
transactionTotal.setText(formatCurrency(amountLong));
|
||||
|
||||
// Calculate tax and service fee (for QRIS, typically no additional fees)
|
||||
long tax = 0; // QRIS usually doesn't have tax
|
||||
long serviceFeeValue = 0; // QRIS usually doesn't have service fee
|
||||
long total = amountLong + tax + serviceFeeValue;
|
||||
// ✅ CALCULATE FEES BASED ON TRANSACTION TYPE
|
||||
long tax = 0;
|
||||
long serviceFeeValue = 0;
|
||||
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
|
||||
taxPercentage.setText("Rp 0");
|
||||
serviceFee.setText("Rp 0");
|
||||
finalTotal.setText("Rp " + formatCurrency(total));
|
||||
taxPercentage.setText(tax > 0 ? "11%" : "0%");
|
||||
serviceFee.setText(formatCurrency(serviceFeeValue));
|
||||
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) {
|
||||
Log.e("ReceiptActivity", "Error parsing amount: " + amountToUse, e);
|
||||
Log.e("ReceiptActivity", "Error parsing enhanced amount: " + amountToUse, e);
|
||||
// Fallback if parsing fails
|
||||
transactionTotal.setText("Rp " + amountToUse);
|
||||
taxPercentage.setText("Rp 0");
|
||||
serviceFee.setText("Rp 0");
|
||||
finalTotal.setText("Rp " + amountToUse);
|
||||
transactionTotal.setText(amountToUse);
|
||||
taxPercentage.setText("0%");
|
||||
serviceFee.setText("0");
|
||||
finalTotal.setText(amountToUse);
|
||||
}
|
||||
} else {
|
||||
// Default values if no amount provided
|
||||
transactionTotal.setText("Rp 0");
|
||||
taxPercentage.setText("Rp 0");
|
||||
serviceFee.setText("Rp 0");
|
||||
finalTotal.setText("Rp 0");
|
||||
transactionTotal.setText("0");
|
||||
taxPercentage.setText("0%");
|
||||
serviceFee.setText("0");
|
||||
finalTotal.setText("0");
|
||||
}
|
||||
}
|
||||
|
||||
@ -876,7 +1103,7 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@ -916,6 +1143,11 @@ public class ReceiptActivity extends AppCompatActivity {
|
||||
navigateToHomePage();
|
||||
break;
|
||||
|
||||
case "ResultTransactionActivity":
|
||||
// ✅ NEW: Handle back from ResultTransactionActivity
|
||||
navigateToHomePage();
|
||||
break;
|
||||
|
||||
case "PaymentActivity":
|
||||
case "QrisActivity":
|
||||
// Go back to payment/qris activity
|
||||
|
@ -78,15 +78,15 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
private String currentQrImageUrl;
|
||||
private int originalAmount;
|
||||
|
||||
// ✅ ADD: QR String untuk validasi QRIS
|
||||
// ✅ QR String untuk validasi QRIS
|
||||
private String currentQrString = "";
|
||||
private String qrStringFromMidtrans = "";
|
||||
|
||||
// ✅ FIXED: Store actual issuer/acquirer from Midtrans response
|
||||
// ✅ Store actual issuer/acquirer from Midtrans response
|
||||
private String actualIssuerFromMidtrans = "";
|
||||
private String actualAcquirerFromMidtrans = "";
|
||||
|
||||
// ✅ ADD: Track QR refresh transaction for payment monitoring
|
||||
// ✅ Track QR refresh transaction for payment monitoring
|
||||
private String currentQrTransactionId = "";
|
||||
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_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>() {{
|
||||
put("airpay shopee", "ShopeePay");
|
||||
put("shopeepay", "ShopeePay");
|
||||
@ -125,6 +125,8 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// ✅ TETAP MENGGUNAKAN LAYOUT ASLI UNTUK QR DISPLAY
|
||||
setContentView(R.layout.activity_qris_result);
|
||||
|
||||
// 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() {
|
||||
try {
|
||||
Log.d("QrisResultFlow", "🔧 Refreshing QR code for existing transaction");
|
||||
@ -807,7 +809,7 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
return fallbackName;
|
||||
}
|
||||
|
||||
// ✅ COMPLETELY FIXED: Use actual issuer from Midtrans response
|
||||
// ✅ ENHANCED: Use actual issuer from Midtrans response
|
||||
private void syncTransactionStatusToBackend(String finalStatus) {
|
||||
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.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
@ -14,7 +16,6 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.example.bdkipoc.R;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -25,30 +26,39 @@ import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* ResultTransactionActivity - Enhanced Receipt-style Display with Better Bank Detection
|
||||
* Shows transaction results in a professional receipt format with improved debugging
|
||||
* ResultTransactionActivity - Enhanced Receipt-style Display using activity_receipt.xml
|
||||
* Shows EMV/Card transaction results using the same layout as QRIS receipts
|
||||
*/
|
||||
public class ResultTransactionActivity extends AppCompatActivity {
|
||||
private static final String TAG = "ResultTransaction";
|
||||
|
||||
// UI Components - New Receipt Layout
|
||||
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;
|
||||
// ✅ UI Components using activity_receipt.xml IDs
|
||||
private LinearLayout backNavigation;
|
||||
private ImageView backArrow;
|
||||
private TextView toolbarTitle;
|
||||
|
||||
// Hidden compatibility components
|
||||
private TextView tvAmount, tvStatus, tvReference, tvCardInfo;
|
||||
private TextView tvPaymentMethod, tvTransactionId, tvOrderId, tvTimestamp;
|
||||
private TextView tvResponseData, tvErrorDetails;
|
||||
private LinearLayout layoutErrorDetails;
|
||||
// Receipt details
|
||||
private TextView merchantName;
|
||||
private TextView merchantLocation;
|
||||
private TextView midText;
|
||||
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
|
||||
private String transactionAmount;
|
||||
private String cardType;
|
||||
private String cardTypeFromIntent;
|
||||
private boolean emvMode;
|
||||
private String referenceId;
|
||||
private String cardNo;
|
||||
@ -66,18 +76,21 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
private long subtotalAmount = 0;
|
||||
private long taxAmount = 0;
|
||||
private long serviceFeeAmount = 500; // Default service fee
|
||||
private double taxPercentage = 0.11; // 11% tax
|
||||
private double taxPercentageValue = 0.11; // 11% tax
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle 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, "✅ Using activity_receipt.xml layout");
|
||||
|
||||
initViews();
|
||||
extractIntentData();
|
||||
debugAllDataSources(); // ✅ ENHANCED: Debug all available data
|
||||
debugAllDataSources();
|
||||
setupListeners();
|
||||
calculateAmounts();
|
||||
displayReceiptData();
|
||||
@ -86,47 +99,40 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
// ✅ Initialize views using activity_receipt.xml IDs
|
||||
|
||||
// Navigation
|
||||
backNavigation = findViewById(R.id.back_navigation);
|
||||
backArrow = findViewById(R.id.backArrow);
|
||||
toolbarTitle = findViewById(R.id.toolbarTitle);
|
||||
|
||||
// New Receipt Layout Components
|
||||
tvMerchantName = findViewById(R.id.tv_merchant_name);
|
||||
tvMerchantLocation = findViewById(R.id.tv_merchant_location);
|
||||
tvTid = findViewById(R.id.tv_tid);
|
||||
tvTransactionNumber = findViewById(R.id.tv_transaction_number);
|
||||
tvTransactionDate = findViewById(R.id.tv_transaction_date);
|
||||
tvPaymentMethodDetail = findViewById(R.id.tv_payment_method_detail);
|
||||
tvCardType = findViewById(R.id.tv_card_type);
|
||||
tvSubtotal = findViewById(R.id.tv_subtotal);
|
||||
tvTax = findViewById(R.id.tv_tax);
|
||||
tvServiceFee = findViewById(R.id.tv_service_fee);
|
||||
tvFinalTotal = findViewById(R.id.tv_final_total);
|
||||
// Receipt details
|
||||
merchantName = findViewById(R.id.merchant_name);
|
||||
merchantLocation = findViewById(R.id.merchant_location);
|
||||
midText = findViewById(R.id.mid_text);
|
||||
tidText = findViewById(R.id.tid_text);
|
||||
transactionNumber = findViewById(R.id.transaction_number);
|
||||
transactionDate = findViewById(R.id.transaction_date);
|
||||
paymentMethod = findViewById(R.id.payment_method);
|
||||
cardType = findViewById(R.id.card_type);
|
||||
transactionTotal = findViewById(R.id.transaction_total);
|
||||
taxPercentage = findViewById(R.id.tax_percentage);
|
||||
serviceFee = findViewById(R.id.service_fee);
|
||||
finalTotal = findViewById(R.id.final_total);
|
||||
|
||||
// Action buttons
|
||||
btnPrint = findViewById(R.id.btn_print);
|
||||
btnEmail = findViewById(R.id.btn_email);
|
||||
btnFinish = findViewById(R.id.btn_finish);
|
||||
printButton = findViewById(R.id.print_button);
|
||||
emailButton = findViewById(R.id.email_button);
|
||||
finishButton = findViewById(R.id.finish_button);
|
||||
|
||||
// Hidden compatibility components
|
||||
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);
|
||||
Log.d(TAG, "✅ All views initialized using activity_receipt.xml");
|
||||
}
|
||||
|
||||
// ✅ ENHANCED: Better intent data extraction with comprehensive debugging
|
||||
private void extractIntentData() {
|
||||
Intent intent = getIntent();
|
||||
|
||||
transactionAmount = intent.getStringExtra("TRANSACTION_AMOUNT");
|
||||
cardType = intent.getStringExtra("CARD_TYPE");
|
||||
cardTypeFromIntent = intent.getStringExtra("CARD_TYPE");
|
||||
emvMode = intent.getBooleanExtra("EMV_MODE", false);
|
||||
referenceId = intent.getStringExtra("REFERENCE_ID");
|
||||
cardNo = intent.getStringExtra("CARD_NO");
|
||||
@ -136,41 +142,29 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
emvAid = intent.getStringExtra("EMV_AID");
|
||||
emvExpiry = intent.getStringExtra("EMV_EXPIRY");
|
||||
|
||||
// ✅ ENHANCED: Better debugging for Midtrans response
|
||||
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, "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));
|
||||
|
||||
// Parse Midtrans response if available
|
||||
if (midtransResponse != null && !midtransResponse.isEmpty()) {
|
||||
try {
|
||||
responseJsonData = new JSONObject(midtransResponse);
|
||||
|
||||
// ✅ ENHANCED: Debug all fields in response
|
||||
Log.d(TAG, "✅ Midtrans Response parsed successfully!");
|
||||
Log.d(TAG, "Response keys: " + responseJsonData.keys().toString());
|
||||
|
||||
// Check for bank field specifically
|
||||
if (responseJsonData.has("bank")) {
|
||||
String bankValue = responseJsonData.getString("bank");
|
||||
Log.d(TAG, "✅ Bank field found: '" + bankValue + "' (length: " + bankValue.length() + ")");
|
||||
Log.d(TAG, "✅ Bank field found: '" + bankValue + "'");
|
||||
} else {
|
||||
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) {
|
||||
Log.e(TAG, "❌ Error parsing Midtrans response: " + e.getMessage());
|
||||
Log.e(TAG, "Raw response causing error: " + midtransResponse);
|
||||
responseJsonData = null;
|
||||
}
|
||||
} else {
|
||||
@ -181,17 +175,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
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() {
|
||||
// Back navigation
|
||||
backNavigation.setOnClickListener(v -> {
|
||||
@ -199,25 +182,35 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
navigateBack();
|
||||
});
|
||||
|
||||
backArrow.setOnClickListener(v -> {
|
||||
if (isNavigating) return;
|
||||
navigateBack();
|
||||
});
|
||||
|
||||
toolbarTitle.setOnClickListener(v -> {
|
||||
if (isNavigating) return;
|
||||
navigateBack();
|
||||
});
|
||||
|
||||
// Print button
|
||||
btnPrint.setOnClickListener(v -> {
|
||||
printButton.setOnClickListener(v -> {
|
||||
showToast("Mencetak struk...");
|
||||
// TODO: Implement print functionality
|
||||
printReceipt();
|
||||
});
|
||||
|
||||
// Email button
|
||||
btnEmail.setOnClickListener(v -> {
|
||||
emailButton.setOnClickListener(v -> {
|
||||
showToast("Mengirim email...");
|
||||
// TODO: Implement email functionality
|
||||
emailReceipt();
|
||||
});
|
||||
|
||||
// Finish button
|
||||
btnFinish.setOnClickListener(v -> {
|
||||
// ✅ Finish button - Navigate to new transaction
|
||||
finishButton.setOnClickListener(v -> {
|
||||
if (isNavigating) return;
|
||||
navigateToNewTransaction();
|
||||
});
|
||||
|
||||
Log.d(TAG, "✅ All click listeners setup");
|
||||
}
|
||||
|
||||
private void calculateAmounts() {
|
||||
@ -229,7 +222,7 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
// Calculate tax (11%)
|
||||
taxAmount = Math.round(subtotalAmount * taxPercentage);
|
||||
taxAmount = Math.round(subtotalAmount * taxPercentageValue);
|
||||
|
||||
// Service fee is fixed
|
||||
serviceFeeAmount = 500;
|
||||
@ -247,48 +240,50 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void displayReceiptData() {
|
||||
// ✅ ENHANCED: Add debugging at start
|
||||
Log.d(TAG, "=== DISPLAYING RECEIPT DATA ===");
|
||||
debugAllDataSources();
|
||||
|
||||
// Merchant Information
|
||||
tvMerchantName.setText("TOKO KLONTONG PAK EKO");
|
||||
tvMerchantLocation.setText("Ciputat Baru, Tangsel");
|
||||
// ✅ 1. Set merchant data
|
||||
merchantName.setText("TOKO KLONTONG PAK EKO");
|
||||
merchantLocation.setText("Ciputat Baru, Tangsel");
|
||||
|
||||
// Generate or extract transaction details
|
||||
// ✅ 2. Set MID and TID
|
||||
String tid = extractTidFromResponse();
|
||||
String transactionNumber = extractTransactionNumberFromResponse();
|
||||
String transactionDate = formatTransactionDate();
|
||||
midText.setText("MID: " + tid);
|
||||
tidText.setText("TID: " + tid);
|
||||
|
||||
tvTid.setText("TID: " + tid);
|
||||
tvTransactionNumber.setText(transactionNumber);
|
||||
tvTransactionDate.setText(transactionDate);
|
||||
// ✅ 3. Set transaction number
|
||||
String displayTransactionNumber = extractTransactionNumberFromResponse();
|
||||
transactionNumber.setText(displayTransactionNumber);
|
||||
|
||||
// Payment method details
|
||||
String paymentMethod = getPaymentMethodDisplay();
|
||||
String cardTypeDisplay = getCardTypeDisplay();
|
||||
|
||||
// ✅ ENHANCED: Add debugging for final values
|
||||
Log.d(TAG, "Payment Method: " + paymentMethod);
|
||||
Log.d(TAG, "Final Card Type Display: " + cardTypeDisplay);
|
||||
Log.d(TAG, "================================");
|
||||
// ✅ 4. Set transaction date
|
||||
String displayDate = formatTransactionDate();
|
||||
transactionDate.setText(displayDate);
|
||||
|
||||
tvPaymentMethodDetail.setText(paymentMethod);
|
||||
tvCardType.setText(cardTypeDisplay);
|
||||
// ✅ 5. Set payment method
|
||||
String displayPaymentMethod = getPaymentMethodDisplay();
|
||||
paymentMethod.setText(displayPaymentMethod);
|
||||
|
||||
// Amount details
|
||||
// ✅ 6. ENHANCED: Set card type with comprehensive detection
|
||||
String displayCardType = getCardTypeDisplay();
|
||||
cardType.setText(displayCardType);
|
||||
|
||||
// ✅ 7. Set amount details
|
||||
NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
|
||||
|
||||
tvSubtotal.setText(formatter.format(subtotalAmount));
|
||||
tvTax.setText(Math.round(taxPercentage * 100) + "%");
|
||||
tvServiceFee.setText(formatter.format(serviceFeeAmount));
|
||||
transactionTotal.setText(formatter.format(subtotalAmount));
|
||||
taxPercentage.setText(Math.round(taxPercentageValue * 100) + "%");
|
||||
serviceFee.setText(formatter.format(serviceFeeAmount));
|
||||
|
||||
// Final total
|
||||
long finalTotal = subtotalAmount + taxAmount + serviceFeeAmount;
|
||||
tvFinalTotal.setText(formatter.format(finalTotal));
|
||||
long finalTotalAmount = subtotalAmount + taxAmount + serviceFeeAmount;
|
||||
finalTotal.setText(formatter.format(finalTotalAmount));
|
||||
|
||||
// Update hidden compatibility components for backward compatibility
|
||||
updateCompatibilityComponents();
|
||||
Log.d(TAG, "✅ Receipt data displayed successfully");
|
||||
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() {
|
||||
@ -331,7 +326,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
try {
|
||||
if (responseJsonData.has("transaction_time")) {
|
||||
String transactionTime = responseJsonData.getString("transaction_time");
|
||||
// Parse and reformat if needed
|
||||
return formatDateForDisplay(transactionTime);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
@ -345,7 +339,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
|
||||
private String formatDateForDisplay(String dateString) {
|
||||
try {
|
||||
// Try to parse the input date string and reformat
|
||||
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"));
|
||||
Date date = inputFormat.parse(dateString);
|
||||
@ -362,32 +355,31 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
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 "IC":
|
||||
case "NFC":
|
||||
return "Kartu Kredit";
|
||||
return emvMode ? "Kartu Kredit (EMV)" : "Kartu Kredit";
|
||||
case "DEBIT":
|
||||
return "Kartu Debit";
|
||||
return emvMode ? "Kartu Debit (EMV)" : "Kartu Debit";
|
||||
case "MAGNETIC":
|
||||
return "Kartu Magnetic";
|
||||
return "Kartu Kredit";
|
||||
default:
|
||||
return "Kartu Kredit";
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ ENHANCED: Comprehensive bank detection with multiple fallbacks
|
||||
// ✅ ENHANCED: Comprehensive bank detection for EMV transactions
|
||||
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)
|
||||
if (responseJsonData != null) {
|
||||
Log.d(TAG, "✅ Midtrans response available, checking for bank...");
|
||||
|
||||
try {
|
||||
// ✅ ENHANCED: Check multiple possible bank fields
|
||||
String bankFromResponse = null;
|
||||
|
||||
if (responseJsonData.has("bank")) {
|
||||
@ -405,15 +397,11 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
String formattedBank = formatBankName(bankFromResponse);
|
||||
Log.d(TAG, "✅ Bank from Midtrans response: '" + bankFromResponse + "' -> '" + formattedBank + "'");
|
||||
return formattedBank;
|
||||
} else {
|
||||
Log.w(TAG, "⚠️ Bank field exists but is empty/null");
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "❌ Error extracting bank from response: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "⚠️ No Midtrans response data available");
|
||||
}
|
||||
|
||||
// Priority 2: EMV AID detection
|
||||
@ -424,9 +412,6 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
Log.d(TAG, "✅ Bank from EMV AID: " + 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
|
||||
@ -436,226 +421,118 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
String bankFromBin = getBankFromComprehensiveBin(cardBin);
|
||||
Log.d(TAG, "✅ Bank from BIN (" + cardBin + "): " + 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, "====================================");
|
||||
return "BCA"; // Default fallback
|
||||
}
|
||||
|
||||
// ✅ ENHANCED: Better bank name formatting with more variations
|
||||
|
||||
// ✅ ENHANCED: Better bank name formatting
|
||||
private String formatBankName(String bankName) {
|
||||
if (bankName == null || bankName.trim().isEmpty()) {
|
||||
Log.d(TAG, "Bank name is null/empty, using default BCA");
|
||||
return "BCA"; // Default
|
||||
}
|
||||
|
||||
// Clean and normalize input
|
||||
String formatted = bankName.trim().toUpperCase();
|
||||
Log.d(TAG, "Formatting bank name: '" + bankName + "' -> '" + formatted + "'");
|
||||
|
||||
// Handle common bank name variations
|
||||
switch (formatted) {
|
||||
// BCA variations
|
||||
case "BCA":
|
||||
case "BANK BCA":
|
||||
case "BANK CENTRAL ASIA":
|
||||
case "PT BANK CENTRAL ASIA TBK":
|
||||
return "BCA";
|
||||
|
||||
// MANDIRI variations
|
||||
case "MANDIRI":
|
||||
case "BANK MANDIRI":
|
||||
case "PT BANK MANDIRI (PERSERO) TBK":
|
||||
case "MANDIRI BANK":
|
||||
return "MANDIRI";
|
||||
return "Mandiri";
|
||||
|
||||
// BNI variations
|
||||
case "BNI":
|
||||
case "BANK BNI":
|
||||
case "BANK NEGARA INDONESIA":
|
||||
case "PT BANK NEGARA INDONESIA (PERSERO) TBK":
|
||||
return "BNI";
|
||||
|
||||
// BRI variations
|
||||
case "BRI":
|
||||
case "BANK BRI":
|
||||
case "BANK RAKYAT INDONESIA":
|
||||
case "PT BANK RAKYAT INDONESIA (PERSERO) TBK":
|
||||
return "BRI";
|
||||
|
||||
// CIMB variations
|
||||
case "CIMB":
|
||||
case "CIMB NIAGA":
|
||||
case "BANK CIMB NIAGA":
|
||||
case "PT BANK CIMB NIAGA TBK":
|
||||
return "CIMB NIAGA";
|
||||
return "CIMB Niaga";
|
||||
|
||||
// DANAMON variations
|
||||
case "DANAMON":
|
||||
case "BANK DANAMON":
|
||||
case "PT BANK DANAMON INDONESIA TBK":
|
||||
return "DANAMON";
|
||||
return "Danamon";
|
||||
|
||||
// PERMATA variations
|
||||
case "PERMATA":
|
||||
case "BANK PERMATA":
|
||||
case "PT BANK PERMATA TBK":
|
||||
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";
|
||||
return "Permata";
|
||||
|
||||
default:
|
||||
// For unknown banks, return as-is but log it
|
||||
Log.d(TAG, "Unknown bank name, returning as-is: " + formatted);
|
||||
return formatted;
|
||||
return capitalizeFirstLetter(bankName);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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")) {
|
||||
// VISA - check if we have card number for better detection
|
||||
if (cardNo != null && cardNo.length() >= 6) {
|
||||
return getBankFromBin(cardNo.substring(0, 6));
|
||||
return getBankFromComprehensiveBin(cardNo.substring(0, 6));
|
||||
}
|
||||
return "BCA"; // Default for VISA
|
||||
}
|
||||
|
||||
if (aid.contains("A0000000041010")) {
|
||||
// MASTERCARD - check if we have card number for better detection
|
||||
// MASTERCARD
|
||||
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
|
||||
}
|
||||
|
||||
// ✅ ENHANCED: More comprehensive Indonesian bank BIN mapping
|
||||
|
||||
// ✅ ENHANCED: Comprehensive Indonesian bank BIN mapping
|
||||
private String getBankFromComprehensiveBin(String bin) {
|
||||
if (bin == null || bin.length() < 4) {
|
||||
return "BCA"; // Default
|
||||
}
|
||||
|
||||
// More comprehensive Indonesian bank BIN mapping
|
||||
String bin4 = bin.substring(0, 4);
|
||||
String bin6 = bin.length() >= 6 ? bin.substring(0, 6) : bin4;
|
||||
|
||||
// BCA patterns
|
||||
if (bin4.equals("4621") || bin4.equals("4699") || bin4.equals("5221") || bin4.equals("6277") ||
|
||||
bin6.startsWith("462117") || bin6.startsWith("469929") || bin6.startsWith("522156")) {
|
||||
if (bin4.equals("4621") || bin4.equals("4699") || bin4.equals("5221") || bin4.equals("6277")) {
|
||||
return "BCA";
|
||||
}
|
||||
|
||||
// MANDIRI patterns
|
||||
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";
|
||||
if (bin4.equals("4313") || bin4.equals("5573") || bin4.equals("6011") || bin4.equals("6234")) {
|
||||
return "Mandiri";
|
||||
}
|
||||
|
||||
// BNI patterns
|
||||
if (bin4.equals("4603") || bin4.equals("1946") || bin4.equals("5264") ||
|
||||
bin6.startsWith("460347") || bin6.startsWith("194637") || bin6.startsWith("526435")) {
|
||||
if (bin4.equals("4603") || bin4.equals("1946") || bin4.equals("5264")) {
|
||||
return "BNI";
|
||||
}
|
||||
|
||||
// BRI patterns
|
||||
if (bin4.equals("4578") || bin4.equals("4479") || bin4.equals("5208") || bin4.equals("4486") ||
|
||||
bin6.startsWith("457865") || bin6.startsWith("447935") || bin6.startsWith("520834")) {
|
||||
if (bin4.equals("4578") || bin4.equals("4479") || bin4.equals("5208")) {
|
||||
return "BRI";
|
||||
}
|
||||
|
||||
// CIMB NIAGA patterns
|
||||
if (bin4.equals("4599") || bin4.equals("5249") || bin4.equals("4543") ||
|
||||
bin6.startsWith("459923") || bin6.startsWith("524901") || bin6.startsWith("454347")) {
|
||||
return "CIMB NIAGA";
|
||||
if (bin4.equals("4599") || bin4.equals("5249")) {
|
||||
return "CIMB Niaga";
|
||||
}
|
||||
|
||||
// DANAMON patterns
|
||||
if (bin4.equals("4055") || bin4.equals("5108") || bin4.equals("4631") ||
|
||||
bin6.startsWith("405512") || bin6.startsWith("510834") || bin6.startsWith("463178")) {
|
||||
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";
|
||||
if (bin4.equals("4055") || bin4.equals("5108")) {
|
||||
return "Danamon";
|
||||
}
|
||||
|
||||
// Default fallback
|
||||
@ -663,47 +540,20 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
return "BCA";
|
||||
}
|
||||
|
||||
// Update hidden components for backward compatibility
|
||||
private void updateCompatibilityComponents() {
|
||||
if (tvAmount != null) {
|
||||
NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
|
||||
tvAmount.setText("Rp " + formatter.format(subtotalAmount + taxAmount + serviceFeeAmount));
|
||||
}
|
||||
|
||||
if (tvStatus != null) {
|
||||
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());
|
||||
private String capitalizeFirstLetter(String input) {
|
||||
if (input == null || input.isEmpty()) {
|
||||
return input;
|
||||
}
|
||||
return input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
// ✅ ENHANCED: Add method to debug all data sources
|
||||
// ✅ Debug methods
|
||||
private void debugAllDataSources() {
|
||||
Log.d(TAG, "=== DEBUGGING ALL DATA SOURCES ===");
|
||||
|
||||
// Check Midtrans response
|
||||
if (responseJsonData != null) {
|
||||
Log.d(TAG, "Midtrans Response Available:");
|
||||
try {
|
||||
// Log all keys and their values
|
||||
java.util.Iterator<String> keys = responseJsonData.keys();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
@ -717,63 +567,35 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
Log.d(TAG, "❌ No Midtrans Response Data");
|
||||
}
|
||||
|
||||
// Check EMV data
|
||||
Log.d(TAG, "EMV Data:");
|
||||
Log.d(TAG, " Card Number: " + (cardNo != null ? maskCardNumber(cardNo) : "null"));
|
||||
Log.d(TAG, " EMV AID: " + emvAid);
|
||||
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, "==================================");
|
||||
}
|
||||
|
||||
// ✅ ENHANCED: Method to manually set bank for testing
|
||||
public void debugSetBank(String bankName) {
|
||||
try {
|
||||
if (responseJsonData == null) {
|
||||
responseJsonData = new JSONObject();
|
||||
}
|
||||
responseJsonData.put("bank", bankName);
|
||||
Log.d(TAG, "Debug: Manually set bank to: " + bankName);
|
||||
|
||||
// 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;
|
||||
|
||||
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, "======================");
|
||||
}
|
||||
|
||||
// Action Methods
|
||||
private void printReceipt() {
|
||||
Log.d(TAG, "Print receipt requested");
|
||||
// TODO: Implement actual printing logic
|
||||
showToast("Fitur cetak akan segera tersedia");
|
||||
}
|
||||
|
||||
private void emailReceipt() {
|
||||
Log.d(TAG, "Email receipt requested");
|
||||
|
||||
// Create email intent
|
||||
Intent emailIntent = new Intent(Intent.ACTION_SEND);
|
||||
emailIntent.setType("text/plain");
|
||||
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Struk Pembayaran - " + extractTransactionNumberFromResponse());
|
||||
@ -791,9 +613,8 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
StringBuilder content = new StringBuilder();
|
||||
NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
|
||||
|
||||
content.append("STRUK PEMBAYARAN\n");
|
||||
content.append("================\n\n");
|
||||
content.append("Payvora PRO\n");
|
||||
content.append("STRUK PEMBAYARAN EMV/CARD\n");
|
||||
content.append("==========================\n\n");
|
||||
content.append("TOKO KLONTONG PAK EKO\n");
|
||||
content.append("Ciputat Baru, Tangsel\n\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("Metode: ").append(getPaymentMethodDisplay()).append("\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("Total Transaksi: Rp ").append(formatter.format(subtotalAmount)).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() {
|
||||
if (isNavigating) return;
|
||||
|
||||
// Show confirmation dialog
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("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 ===");
|
||||
isNavigating = true;
|
||||
|
||||
// Add small delay for better UX
|
||||
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||
try {
|
||||
Intent intent = new Intent(this, CreateTransactionActivity.class);
|
||||
@ -874,6 +700,7 @@ public class ResultTransactionActivity extends AppCompatActivity {
|
||||
return;
|
||||
}
|
||||
navigateBack();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -104,7 +104,7 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="EDC "
|
||||
android:text="Payvora "
|
||||
android:textColor="#E31937"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
@ -113,7 +113,7 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Merchant"
|
||||
android:text="PRO"
|
||||
android:textColor="#3F51B5"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
@ -121,15 +121,6 @@
|
||||
|
||||
</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>
|
||||
|
||||
<!-- Merchant Info -->
|
||||
@ -168,46 +159,36 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
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
|
||||
android:id="@+id/mid_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="1234567890"
|
||||
android:text="MID:12345678901"
|
||||
android:textColor="#333333"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<!-- Vertical Separator -->
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="TID: "
|
||||
android:textColor="#666666"
|
||||
android:text=" | "
|
||||
android:textColor="#999999"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
android:fontFamily="@font/inter"
|
||||
android:paddingHorizontal="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tid_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="1234567890"
|
||||
android:text="TID:12345678901"
|
||||
android:textColor="#333333"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Separator Line -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user