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);
|
||||||
|
cardType.setText(displayCardType);
|
||||||
|
|
||||||
if (channelCode != null && channelCode.equalsIgnoreCase("QRIS")) {
|
// 7. ✅ Format and set amounts with proper calculation
|
||||||
Log.d("ReceiptActivity", "🔍 QRIS transaction detected - searching for real acquirer");
|
setAmountDataEnhanced(amount, grossAmount, isEmvTransaction, isQrisTransaction);
|
||||||
|
|
||||||
// For QRIS, try to get real acquirer from webhook data
|
Log.d("ReceiptActivity", "💳 FINAL DISPLAY VALUES:");
|
||||||
if (referenceId != null && !referenceId.isEmpty()) {
|
Log.d("ReceiptActivity", " Payment Method: " + displayPaymentMethod);
|
||||||
String realAcquirer = fetchRealAcquirerSync(referenceId);
|
Log.d("ReceiptActivity", " Card Type: " + displayCardType);
|
||||||
if (realAcquirer != null && !realAcquirer.isEmpty() && !realAcquirer.equalsIgnoreCase("qris")) {
|
Log.d("ReceiptActivity", " Transaction Number: " + displayTransactionNumber);
|
||||||
displayCardType = getCardTypeFromAcquirer(realAcquirer, null, null);
|
Log.d("ReceiptActivity", "=== ENHANCED TRANSACTION DATA LOADED ===");
|
||||||
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);
|
* Get display transaction number with priority
|
||||||
}
|
*/
|
||||||
} else {
|
private String getDisplayTransactionNumber(String referenceId, String transactionId, String orderId) {
|
||||||
displayCardType = "QRIS";
|
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 {
|
} else {
|
||||||
// Non-QRIS transaction
|
return formatDateFromCreatedAt(dateToFormat);
|
||||||
displayCardType = getCardTypeFromAcquirer(acquirer, channelCode, cardTypeStr);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cardType.setText(displayCardType);
|
// If all formats fail, return as-is
|
||||||
Log.d("ReceiptActivity", "💳 FINAL CARD TYPE: " + displayCardType);
|
Log.w("ReceiptActivity", "Could not format EMV date: " + dateString);
|
||||||
|
return dateString;
|
||||||
|
|
||||||
// 7. Format and set amounts
|
} catch (Exception e) {
|
||||||
setAmountData(amount, grossAmount);
|
Log.e("ReceiptActivity", "Error formatting EMV date: " + dateString, e);
|
||||||
|
return dateString;
|
||||||
Log.d("ReceiptActivity", "=== TRANSACTION DATA LOADED ===");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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));
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
return input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ENHANCED: Add method to debug all data sources
|
// ✅ Debug methods
|
||||||
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);
|
Log.d(TAG, " EMV Mode: " + emvMode);
|
||||||
|
|
||||||
// Check card type
|
|
||||||
Log.d(TAG, "Card Type: " + cardType);
|
|
||||||
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