transaction update
This commit is contained in:
		
							parent
							
								
									da8bcf17cc
								
							
						
					
					
						commit
						991f77dabe
					
				@ -20,7 +20,9 @@ import java.util.Locale;
 | 
				
			|||||||
import java.io.BufferedReader;
 | 
					import java.io.BufferedReader;
 | 
				
			||||||
import java.io.InputStreamReader;
 | 
					import java.io.InputStreamReader;
 | 
				
			||||||
import java.net.HttpURLConnection;
 | 
					import java.net.HttpURLConnection;
 | 
				
			||||||
 | 
					import java.io.OutputStream;
 | 
				
			||||||
import java.net.URL;
 | 
					import java.net.URL;
 | 
				
			||||||
 | 
					import java.net.URI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class ReceiptActivity extends AppCompatActivity {
 | 
					public class ReceiptActivity extends AppCompatActivity {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -286,10 +288,6 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
        return fallbackPaymentMethod != null ? fallbackPaymentMethod : "QRIS";
 | 
					        return fallbackPaymentMethod != null ? fallbackPaymentMethod : "QRIS";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * ✅ ENHANCED: Dynamic acquirer detection from webhook data
 | 
					 | 
				
			||||||
     * This method tries to get the REAL acquirer instead of defaulting to GoPay
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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")) {
 | 
				
			||||||
@ -323,9 +321,6 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
                case "bsi":
 | 
					                case "bsi":
 | 
				
			||||||
                case "bsi_va": return "BSI";
 | 
					                case "bsi_va": return "BSI";
 | 
				
			||||||
                case "maybank": return "Maybank";
 | 
					                case "maybank": return "Maybank";
 | 
				
			||||||
                case "mega": return "Bank Mega";
 | 
					 | 
				
			||||||
                case "btn": return "BTN";
 | 
					 | 
				
			||||||
                case "bukopin": return "Bukopin";
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Credit card acquirers
 | 
					                // Credit card acquirers
 | 
				
			||||||
                case "visa": return "Visa";
 | 
					                case "visa": return "Visa";
 | 
				
			||||||
@ -343,12 +338,6 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
                case "kredivo": return "Kredivo";
 | 
					                case "kredivo": return "Kredivo";
 | 
				
			||||||
                case "indodana": return "Indodana";
 | 
					                case "indodana": return "Indodana";
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Other acquirers
 | 
					 | 
				
			||||||
                case "emoney": return "E-Money";
 | 
					 | 
				
			||||||
                case "flazz": return "Flazz";
 | 
					 | 
				
			||||||
                case "tapcash": return "TapCash";
 | 
					 | 
				
			||||||
                case "brizzi": return "Brizzi";
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    // Return capitalized version of acquirer if not in mapping
 | 
					                    // Return capitalized version of acquirer if not in mapping
 | 
				
			||||||
                    return capitalizeFirstLetter(acquirer);
 | 
					                    return capitalizeFirstLetter(acquirer);
 | 
				
			||||||
@ -361,11 +350,16 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
            if (referenceId != null && !referenceId.isEmpty()) {
 | 
					            if (referenceId != null && !referenceId.isEmpty()) {
 | 
				
			||||||
                Log.d("ReceiptActivity", "🔍 QRIS detected, fetching real acquirer for: " + referenceId);
 | 
					                Log.d("ReceiptActivity", "🔍 QRIS detected, fetching real acquirer for: " + referenceId);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Try to get real acquirer from webhook data asynchronously
 | 
					                // Try to get real acquirer from webhook data synchronously for initial load
 | 
				
			||||||
                fetchRealAcquirerFromWebhook(referenceId);
 | 
					                String realAcquirer = fetchRealAcquirerSync(referenceId);
 | 
				
			||||||
 | 
					                if (realAcquirer != null && !realAcquirer.isEmpty() && !realAcquirer.equalsIgnoreCase("qris")) {
 | 
				
			||||||
 | 
					                    Log.d("ReceiptActivity", "✅ Found real acquirer synchronously: " + realAcquirer);
 | 
				
			||||||
 | 
					                    return getCardTypeFromAcquirer(realAcquirer, null, null);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // ✅ IMPROVED: Instead of defaulting to GoPay, show generic "QRIS" until real acquirer is found
 | 
					                // If sync fetch failed, try async and show generic QRIS for now
 | 
				
			||||||
                return "QRIS"; // Will be updated when real acquirer is found
 | 
					                fetchRealAcquirerFromWebhook(referenceId);
 | 
				
			||||||
 | 
					                return "QRIS"; // ✅ FIXED: Show QRIS instead of defaulting to GoPay
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -373,7 +367,7 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
        if (channelCode != null && !channelCode.isEmpty()) {
 | 
					        if (channelCode != null && !channelCode.isEmpty()) {
 | 
				
			||||||
            String code = channelCode.toUpperCase();
 | 
					            String code = channelCode.toUpperCase();
 | 
				
			||||||
            switch (code) {
 | 
					            switch (code) {
 | 
				
			||||||
                case "QRIS": return "QRIS"; // ✅ CHANGED: Generic QRIS instead of GoPay
 | 
					                case "QRIS": return "QRIS"; // ✅ FIXED: Generic QRIS instead of GoPay
 | 
				
			||||||
                case "DEBIT": return "Debit";
 | 
					                case "DEBIT": return "Debit";
 | 
				
			||||||
                case "CREDIT": return "Credit";
 | 
					                case "CREDIT": return "Credit";
 | 
				
			||||||
                case "BCA": return "BCA";
 | 
					                case "BCA": return "BCA";
 | 
				
			||||||
@ -385,19 +379,97 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // STEP 4: Final fallback
 | 
					        // STEP 4: Final fallback
 | 
				
			||||||
        return fallbackCardType != null ? fallbackCardType : "Unknown"; // ✅ CHANGED: Unknown instead of GoPay
 | 
					        return fallbackCardType != null ? fallbackCardType : "Unknown"; // ✅ FIXED: Unknown instead of GoPay
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private String fetchRealAcquirerSync(String referenceId) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            Log.d("ReceiptActivity", "🔍 Sync search for acquirer: " + referenceId);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            String queryUrl = "https://be-edc.msvc.app/api-logs?limit=50&sortOrder=DESC&sortColumn=created_at";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            URL url = new URL(queryUrl);
 | 
				
			||||||
 | 
					            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 | 
				
			||||||
 | 
					            conn.setRequestMethod("GET");
 | 
				
			||||||
 | 
					            conn.setRequestProperty("Accept", "application/json");
 | 
				
			||||||
 | 
					            conn.setRequestProperty("User-Agent", "BDKIPOCApp/1.0");
 | 
				
			||||||
 | 
					            conn.setConnectTimeout(5000); // Short timeout for sync call
 | 
				
			||||||
 | 
					            conn.setReadTimeout(5000);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if (conn.getResponseCode() == 200) {
 | 
				
			||||||
 | 
					                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
 | 
				
			||||||
 | 
					                StringBuilder response = new StringBuilder();
 | 
				
			||||||
 | 
					                String line;
 | 
				
			||||||
 | 
					                while ((line = br.readLine()) != null) {
 | 
				
			||||||
 | 
					                    response.append(line);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                org.json.JSONObject json = new org.json.JSONObject(response.toString());
 | 
				
			||||||
 | 
					                org.json.JSONArray results = json.optJSONArray("results");
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if (results != null && results.length() > 0) {
 | 
				
			||||||
 | 
					                    // Search for the most recent settlement/success transaction
 | 
				
			||||||
 | 
					                    for (int i = 0; i < results.length(); i++) {
 | 
				
			||||||
 | 
					                        org.json.JSONObject log = results.getJSONObject(i);
 | 
				
			||||||
 | 
					                        org.json.JSONObject reqBody = log.optJSONObject("request_body");
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        if (reqBody != null) {
 | 
				
			||||||
 | 
					                            String logReferenceId = reqBody.optString("reference_id", "");
 | 
				
			||||||
 | 
					                            String logTransactionStatus = reqBody.optString("transaction_status", "");
 | 
				
			||||||
 | 
					                            String logAcquirer = reqBody.optString("acquirer", "");
 | 
				
			||||||
 | 
					                            String logIssuer = reqBody.optString("issuer", "");
 | 
				
			||||||
 | 
					                            
 | 
				
			||||||
 | 
					                            // Check for direct reference match
 | 
				
			||||||
 | 
					                            boolean isDirectMatch = referenceId.equals(logReferenceId);
 | 
				
			||||||
 | 
					                            
 | 
				
			||||||
 | 
					                            // Check custom_field1 for refresh tracking
 | 
				
			||||||
 | 
					                            boolean isRefreshMatch = false;
 | 
				
			||||||
 | 
					                            String customField1 = reqBody.optString("custom_field1", "");
 | 
				
			||||||
 | 
					                            if (!customField1.isEmpty()) {
 | 
				
			||||||
 | 
					                                try {
 | 
				
			||||||
 | 
					                                    org.json.JSONObject customData = new org.json.JSONObject(customField1);
 | 
				
			||||||
 | 
					                                    String originalReference = customData.optString("original_reference", "");
 | 
				
			||||||
 | 
					                                    String appReferenceId = customData.optString("app_reference_id", "");
 | 
				
			||||||
 | 
					                                    if (referenceId.equals(originalReference) || referenceId.equals(appReferenceId)) {
 | 
				
			||||||
 | 
					                                        isRefreshMatch = true;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                } catch (org.json.JSONException e) {
 | 
				
			||||||
 | 
					                                    // Ignore parsing errors
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            
 | 
				
			||||||
 | 
					                            // Check if this log matches our reference
 | 
				
			||||||
 | 
					                            if (isDirectMatch || isRefreshMatch) {
 | 
				
			||||||
 | 
					                                // Prioritize settlement/success status
 | 
				
			||||||
 | 
					                                if (logTransactionStatus.equals("settlement") || 
 | 
				
			||||||
 | 
					                                    logTransactionStatus.equals("capture") ||
 | 
				
			||||||
 | 
					                                    logTransactionStatus.equals("success")) {
 | 
				
			||||||
 | 
					                                    
 | 
				
			||||||
 | 
					                                    // Extract acquirer (prefer acquirer field over issuer)
 | 
				
			||||||
 | 
					                                    String foundAcquirer = !logAcquirer.isEmpty() ? logAcquirer : logIssuer;
 | 
				
			||||||
 | 
					                                    if (!foundAcquirer.isEmpty() && !foundAcquirer.equalsIgnoreCase("qris")) {
 | 
				
			||||||
 | 
					                                        Log.d("ReceiptActivity", "📋 Sync found acquirer: " + foundAcquirer + " (status: " + logTransactionStatus + ")");
 | 
				
			||||||
 | 
					                                        return foundAcquirer;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            Log.e("ReceiptActivity", "❌ Sync acquirer fetch error: " + e.getMessage());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return null; // No acquirer found
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * ✅ ENHANCED: Fetch real acquirer from webhook data for QRIS transactions
 | 
					 | 
				
			||||||
     * This method searches webhook logs to find the actual acquirer used
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private void fetchRealAcquirerFromWebhook(String referenceId) {
 | 
					    private void fetchRealAcquirerFromWebhook(String referenceId) {
 | 
				
			||||||
        new Thread(() -> {
 | 
					        new Thread(() -> {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                Log.d("ReceiptActivity", "🔍 Searching for real acquirer for reference: " + referenceId);
 | 
					                Log.d("ReceiptActivity", "🔍 Async search for real acquirer: " + referenceId);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // Search webhook logs for this reference with broader search
 | 
					 | 
				
			||||||
                String queryUrl = "https://be-edc.msvc.app/api-logs?limit=100&sortOrder=DESC&sortColumn=created_at";
 | 
					                String queryUrl = "https://be-edc.msvc.app/api-logs?limit=100&sortOrder=DESC&sortColumn=created_at";
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                URL url = new URL(queryUrl);
 | 
					                URL url = new URL(queryUrl);
 | 
				
			||||||
@ -423,7 +495,7 @@ public class ReceiptActivity extends AppCompatActivity {
 | 
				
			|||||||
                        String realAcquirer = searchForRealAcquirer(results, referenceId);
 | 
					                        String realAcquirer = searchForRealAcquirer(results, referenceId);
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
                        if (realAcquirer != null && !realAcquirer.isEmpty() && !realAcquirer.equalsIgnoreCase("qris")) {
 | 
					                        if (realAcquirer != null && !realAcquirer.isEmpty() && !realAcquirer.equalsIgnoreCase("qris")) {
 | 
				
			||||||
                            Log.d("ReceiptActivity", "✅ Found real acquirer: " + realAcquirer + " for reference: " + referenceId);
 | 
					                            Log.d("ReceiptActivity", "✅ Async found real acquirer: " + realAcquirer + " for reference: " + referenceId);
 | 
				
			||||||
                            
 | 
					                            
 | 
				
			||||||
                            // Update UI on main thread
 | 
					                            // Update UI on main thread
 | 
				
			||||||
                            final String displayAcquirer = getCardTypeFromAcquirer(realAcquirer, null, null);
 | 
					                            final String displayAcquirer = getCardTypeFromAcquirer(realAcquirer, null, null);
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@ import androidx.core.content.ContextCompat;
 | 
				
			|||||||
import java.io.BufferedReader;
 | 
					import java.io.BufferedReader;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.io.InputStreamReader;
 | 
					import java.io.InputStreamReader;
 | 
				
			||||||
 | 
					import java.io.OutputStream; // ✅ ADDED: Missing import
 | 
				
			||||||
import java.net.HttpURLConnection;
 | 
					import java.net.HttpURLConnection;
 | 
				
			||||||
import java.net.URL;
 | 
					import java.net.URL;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
@ -211,14 +212,14 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
 | 
				
			|||||||
        return "Rp. " + formatted;
 | 
					        return "Rp. " + formatted;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ✅ FIXED: Enhanced status checking with comprehensive search
 | 
				
			||||||
    private void checkMidtransStatus(String referenceId, TextView statusTextView) {
 | 
					    private void checkMidtransStatus(String referenceId, TextView statusTextView) {
 | 
				
			||||||
        new Thread(() -> {
 | 
					        new Thread(() -> {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                Log.d("TransactionAdapter", "🔍 Comprehensive status check for reference: " + referenceId);
 | 
					                Log.d("TransactionAdapter", "🔍 Comprehensive status check for reference: " + referenceId);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                // STEP 1: Query ALL webhook logs (tidak filter specific order_id)
 | 
					                // STEP 1: Query webhook logs untuk semua order_id yang terkait
 | 
				
			||||||
                // Karena kita perlu cari semua order_id yang terkait dengan reference_id ini
 | 
					                String queryUrl = "https://be-edc.msvc.app/api-logs?limit=200&sortOrder=DESC&sortColumn=created_at";
 | 
				
			||||||
                String queryUrl = "https://be-edc.msvc.app/api-logs?limit=100&sortOrder=DESC&sortColumn=created_at";
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                URL url = new URL(queryUrl);
 | 
					                URL url = new URL(queryUrl);
 | 
				
			||||||
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 | 
					                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 | 
				
			||||||
@ -238,14 +239,14 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
 | 
				
			|||||||
                    JSONObject json = new JSONObject(response.toString());
 | 
					                    JSONObject json = new JSONObject(response.toString());
 | 
				
			||||||
                    JSONArray results = json.optJSONArray("results");
 | 
					                    JSONArray results = json.optJSONArray("results");
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    String realStatus = "INIT"; // Default
 | 
					                    String finalStatus = "INIT"; // Default
 | 
				
			||||||
                    String foundOrderId = null;
 | 
					                    String foundOrderId = null;
 | 
				
			||||||
                    String foundTransactionStatus = "";
 | 
					                    String foundAcquirer = null;
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    if (results != null && results.length() > 0) {
 | 
					                    if (results != null && results.length() > 0) {
 | 
				
			||||||
                        Log.d("TransactionAdapter", "📊 Processing " + results.length() + " log entries");
 | 
					                        Log.d("TransactionAdapter", "📊 Processing " + results.length() + " log entries");
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
                        // STEP 2: Comprehensive search untuk semua kemungkinan relasi
 | 
					                        // STEP 2: Comprehensive search dengan multiple matching strategies
 | 
				
			||||||
                        for (int i = 0; i < results.length(); i++) {
 | 
					                        for (int i = 0; i < results.length(); i++) {
 | 
				
			||||||
                            JSONObject log = results.getJSONObject(i);
 | 
					                            JSONObject log = results.getJSONObject(i);
 | 
				
			||||||
                            JSONObject reqBody = log.optJSONObject("request_body");
 | 
					                            JSONObject reqBody = log.optJSONObject("request_body");
 | 
				
			||||||
@ -254,6 +255,7 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
 | 
				
			|||||||
                                String logOrderId = reqBody.optString("order_id", "");
 | 
					                                String logOrderId = reqBody.optString("order_id", "");
 | 
				
			||||||
                                String logTransactionStatus = reqBody.optString("transaction_status", "");
 | 
					                                String logTransactionStatus = reqBody.optString("transaction_status", "");
 | 
				
			||||||
                                String logReferenceId = reqBody.optString("reference_id", "");
 | 
					                                String logReferenceId = reqBody.optString("reference_id", "");
 | 
				
			||||||
 | 
					                                String logAcquirer = reqBody.optString("acquirer", "");
 | 
				
			||||||
                                
 | 
					                                
 | 
				
			||||||
                                // ✅ METHOD 1: Direct reference_id match
 | 
					                                // ✅ METHOD 1: Direct reference_id match
 | 
				
			||||||
                                boolean isDirectMatch = referenceId.equals(logReferenceId);
 | 
					                                boolean isDirectMatch = referenceId.equals(logReferenceId);
 | 
				
			||||||
@ -265,10 +267,10 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
 | 
				
			|||||||
                                    try {
 | 
					                                    try {
 | 
				
			||||||
                                        JSONObject customData = new JSONObject(customField1);
 | 
					                                        JSONObject customData = new JSONObject(customField1);
 | 
				
			||||||
                                        String originalReference = customData.optString("original_reference", "");
 | 
					                                        String originalReference = customData.optString("original_reference", "");
 | 
				
			||||||
                                        if (referenceId.equals(originalReference)) {
 | 
					                                        String appReferenceId = customData.optString("app_reference_id", "");
 | 
				
			||||||
 | 
					                                        if (referenceId.equals(originalReference) || referenceId.equals(appReferenceId)) {
 | 
				
			||||||
                                            isRefreshMatch = true;
 | 
					                                            isRefreshMatch = true;
 | 
				
			||||||
                                            Log.d("TransactionAdapter", "🔄 Found refresh match: " + logOrderId + 
 | 
					                                            Log.d("TransactionAdapter", "🔄 Found refresh match: " + logOrderId);
 | 
				
			||||||
                                                " (original ref: " + originalReference + ")");
 | 
					 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                    } catch (JSONException e) {
 | 
					                                    } catch (JSONException e) {
 | 
				
			||||||
                                        // Ignore custom field parsing errors
 | 
					                                        // Ignore custom field parsing errors
 | 
				
			||||||
@ -283,10 +285,10 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
 | 
				
			|||||||
                                        JSONObject item = itemDetails.optJSONObject(j);
 | 
					                                        JSONObject item = itemDetails.optJSONObject(j);
 | 
				
			||||||
                                        if (item != null) {
 | 
					                                        if (item != null) {
 | 
				
			||||||
                                            String itemName = item.optString("name", "");
 | 
					                                            String itemName = item.optString("name", "");
 | 
				
			||||||
                                            if (itemName.contains("(Ref: " + referenceId + ")")) {
 | 
					                                            if (itemName.contains("(Ref: " + referenceId + ")") || 
 | 
				
			||||||
 | 
					                                                itemName.contains("- " + referenceId)) {
 | 
				
			||||||
                                                isItemMatch = true;
 | 
					                                                isItemMatch = true;
 | 
				
			||||||
                                                Log.d("TransactionAdapter", "📦 Found item match: " + logOrderId + 
 | 
					                                                Log.d("TransactionAdapter", "📦 Found item match: " + logOrderId);
 | 
				
			||||||
                                                    " (item: " + itemName + ")");
 | 
					 | 
				
			||||||
                                                break;
 | 
					                                                break;
 | 
				
			||||||
                                            }
 | 
					                                            }
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
@ -300,52 +302,63 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
 | 
				
			|||||||
                                    Log.d("TransactionAdapter", "🎯 MATCH FOUND!");
 | 
					                                    Log.d("TransactionAdapter", "🎯 MATCH FOUND!");
 | 
				
			||||||
                                    Log.d("TransactionAdapter", "   Order ID: " + logOrderId);
 | 
					                                    Log.d("TransactionAdapter", "   Order ID: " + logOrderId);
 | 
				
			||||||
                                    Log.d("TransactionAdapter", "   Status: " + logTransactionStatus);
 | 
					                                    Log.d("TransactionAdapter", "   Status: " + logTransactionStatus);
 | 
				
			||||||
                                    Log.d("TransactionAdapter", "   Reference: " + logReferenceId);
 | 
					                                    Log.d("TransactionAdapter", "   Acquirer: " + logAcquirer);
 | 
				
			||||||
                                    Log.d("TransactionAdapter", "   Match Type: " + 
 | 
					                                    Log.d("TransactionAdapter", "   Match Type: " + 
 | 
				
			||||||
                                        (isDirectMatch ? "DIRECT " : "") + 
 | 
					                                        (isDirectMatch ? "DIRECT " : "") + 
 | 
				
			||||||
                                        (isRefreshMatch ? "REFRESH " : "") + 
 | 
					                                        (isRefreshMatch ? "REFRESH " : "") + 
 | 
				
			||||||
                                        (isItemMatch ? "ITEM" : ""));
 | 
					                                        (isItemMatch ? "ITEM" : ""));
 | 
				
			||||||
                                    
 | 
					                                    
 | 
				
			||||||
                                    // Priority check: settlement > capture > success > pending > init
 | 
					                                    // ✅ PRIORITY SYSTEM: settlement > capture > success > pending > init
 | 
				
			||||||
                                    if (logTransactionStatus.equals("settlement") || 
 | 
					                                    if (logTransactionStatus.equals("settlement") || 
 | 
				
			||||||
                                        logTransactionStatus.equals("capture") ||
 | 
					                                        logTransactionStatus.equals("capture") ||
 | 
				
			||||||
                                        logTransactionStatus.equals("success")) {
 | 
					                                        logTransactionStatus.equals("success")) {
 | 
				
			||||||
                                        realStatus = "PAID";
 | 
					                                        finalStatus = "PAID";
 | 
				
			||||||
                                        foundOrderId = logOrderId;
 | 
					                                        foundOrderId = logOrderId;
 | 
				
			||||||
                                        foundTransactionStatus = logTransactionStatus;
 | 
					                                        foundAcquirer = logAcquirer;
 | 
				
			||||||
                                        Log.d("TransactionAdapter", "✅ PAYMENT CONFIRMED: " + logOrderId + " -> " + logTransactionStatus);
 | 
					                                        Log.d("TransactionAdapter", "✅ PAYMENT CONFIRMED: " + logOrderId + " -> " + logTransactionStatus);
 | 
				
			||||||
                                        break; // Found paid status, stop searching
 | 
					                                        break; // Found paid status, stop searching
 | 
				
			||||||
                                    } else if (logTransactionStatus.equals("pending") && realStatus.equals("INIT")) {
 | 
					                                    } else if (logTransactionStatus.equals("pending") && finalStatus.equals("INIT")) {
 | 
				
			||||||
                                        realStatus = "PENDING";
 | 
					                                        finalStatus = "PENDING";
 | 
				
			||||||
                                        foundOrderId = logOrderId;
 | 
					                                        foundOrderId = logOrderId;
 | 
				
			||||||
                                        foundTransactionStatus = logTransactionStatus;
 | 
					                                        foundAcquirer = logAcquirer;
 | 
				
			||||||
                                        Log.d("TransactionAdapter", "⏳ PENDING found: " + logOrderId);
 | 
					                                        Log.d("TransactionAdapter", "⏳ PENDING found: " + logOrderId);
 | 
				
			||||||
 | 
					                                    } else if (logTransactionStatus.equals("expire") || logTransactionStatus.equals("cancel")) {
 | 
				
			||||||
 | 
					                                        if (finalStatus.equals("INIT")) { // Only update if no better status found
 | 
				
			||||||
 | 
					                                            finalStatus = "FAILED";
 | 
				
			||||||
 | 
					                                            foundOrderId = logOrderId;
 | 
				
			||||||
 | 
					                                            foundAcquirer = logAcquirer;
 | 
				
			||||||
 | 
					                                            Log.d("TransactionAdapter", "❌ FAILED status: " + logOrderId + " -> " + logTransactionStatus);
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
                        Log.d("TransactionAdapter", "🔍 FINAL RESULT for " + referenceId + ":");
 | 
					                        Log.d("TransactionAdapter", "🔍 FINAL RESULT for " + referenceId + ":");
 | 
				
			||||||
                        Log.d("TransactionAdapter", "   Status: " + realStatus);
 | 
					                        Log.d("TransactionAdapter", "   Status: " + finalStatus);
 | 
				
			||||||
                        Log.d("TransactionAdapter", "   Order ID: " + (foundOrderId != null ? foundOrderId : "N/A"));
 | 
					                        Log.d("TransactionAdapter", "   Order ID: " + (foundOrderId != null ? foundOrderId : "N/A"));
 | 
				
			||||||
                        Log.d("TransactionAdapter", "   Midtrans Status: " + (foundTransactionStatus != null ? foundTransactionStatus : "N/A"));
 | 
					                        Log.d("TransactionAdapter", "   Acquirer: " + (foundAcquirer != null ? foundAcquirer : "N/A"));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    // STEP 3: Update UI di main thread
 | 
					                    // STEP 3: Update UI di main thread
 | 
				
			||||||
                    final String finalStatus = realStatus;
 | 
					                    final String displayStatus = finalStatus;
 | 
				
			||||||
                    final String finalOrderId = foundOrderId;
 | 
					                    final String detectedAcquirer = foundAcquirer;
 | 
				
			||||||
                    final String finalTransactionStatus = foundTransactionStatus;
 | 
					 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    statusTextView.post(() -> {
 | 
					                    statusTextView.post(() -> {
 | 
				
			||||||
                        statusTextView.setText(finalStatus);
 | 
					                        statusTextView.setText(displayStatus);
 | 
				
			||||||
                        StyleHelper.applyStatusTextColor(statusTextView, statusTextView.getContext(), finalStatus);
 | 
					                        StyleHelper.applyStatusTextColor(statusTextView, statusTextView.getContext(), displayStatus);
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
                        Log.d("TransactionAdapter", "🎨 UI UPDATED:");
 | 
					                        Log.d("TransactionAdapter", "🎨 UI UPDATED:");
 | 
				
			||||||
                        Log.d("TransactionAdapter", "   Reference: " + referenceId);
 | 
					                        Log.d("TransactionAdapter", "   Reference: " + referenceId);
 | 
				
			||||||
                        Log.d("TransactionAdapter", "   Display Status: " + finalStatus);
 | 
					                        Log.d("TransactionAdapter", "   Display Status: " + displayStatus);
 | 
				
			||||||
                        Log.d("TransactionAdapter", "   Found Order: " + (finalOrderId != null ? finalOrderId : "N/A"));
 | 
					                        Log.d("TransactionAdapter", "   Detected Acquirer: " + (detectedAcquirer != null ? detectedAcquirer : "Unknown"));
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
 | 
					                    // ✅ BONUS: Update backend jika status berubah ke PAID
 | 
				
			||||||
 | 
					                    if (finalStatus.equals("PAID")) {
 | 
				
			||||||
 | 
					                        updateBackendTransactionStatus(referenceId, finalStatus, foundOrderId, detectedAcquirer);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Log.w("TransactionAdapter", "⚠️ API call failed with code: " + conn.getResponseCode());
 | 
					                    Log.w("TransactionAdapter", "⚠️ API call failed with code: " + conn.getResponseCode());
 | 
				
			||||||
                    statusTextView.post(() -> {
 | 
					                    statusTextView.post(() -> {
 | 
				
			||||||
@ -364,6 +377,57 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
 | 
				
			|||||||
        }).start();
 | 
					        }).start();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * ✅ NEW METHOD: Update backend transaction status when payment confirmed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void updateBackendTransactionStatus(String referenceId, String status, String orderId, String acquirer) {
 | 
				
			||||||
 | 
					        new Thread(() -> {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                Log.d("TransactionAdapter", "🔄 Updating backend status for reference: " + referenceId);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                JSONObject updatePayload = new JSONObject();
 | 
				
			||||||
 | 
					                updatePayload.put("status", status);
 | 
				
			||||||
 | 
					                updatePayload.put("payment_status", status);
 | 
				
			||||||
 | 
					                updatePayload.put("paid_order_id", orderId);
 | 
				
			||||||
 | 
					                updatePayload.put("detected_acquirer", acquirer);
 | 
				
			||||||
 | 
					                updatePayload.put("updated_at", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date()));
 | 
				
			||||||
 | 
					                updatePayload.put("settlement_time", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date()));
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                String updateUrl = "https://be-edc.msvc.app/transactions/update-by-reference";
 | 
				
			||||||
 | 
					                URL url = new URL(updateUrl);
 | 
				
			||||||
 | 
					                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 | 
				
			||||||
 | 
					                conn.setRequestMethod("POST");
 | 
				
			||||||
 | 
					                conn.setRequestProperty("Content-Type", "application/json");
 | 
				
			||||||
 | 
					                conn.setRequestProperty("Accept", "application/json");
 | 
				
			||||||
 | 
					                conn.setRequestProperty("User-Agent", "BDKIPOCApp/1.0");
 | 
				
			||||||
 | 
					                conn.setDoOutput(true);
 | 
				
			||||||
 | 
					                conn.setConnectTimeout(15000);
 | 
				
			||||||
 | 
					                conn.setReadTimeout(15000);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                JSONObject requestBody = new JSONObject();
 | 
				
			||||||
 | 
					                requestBody.put("reference_id", referenceId);
 | 
				
			||||||
 | 
					                requestBody.put("update_data", updatePayload);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                try (OutputStream os = conn.getOutputStream()) {
 | 
				
			||||||
 | 
					                    byte[] input = requestBody.toString().getBytes("utf-8");
 | 
				
			||||||
 | 
					                    os.write(input, 0, input.length);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                int responseCode = conn.getResponseCode();
 | 
				
			||||||
 | 
					                Log.d("TransactionAdapter", "📥 Backend update response: " + responseCode);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if (responseCode == 200 || responseCode == 201) {
 | 
				
			||||||
 | 
					                    Log.d("TransactionAdapter", "✅ Backend status updated successfully");
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    Log.e("TransactionAdapter", "❌ Backend update failed: " + responseCode);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            } catch (Exception e) {
 | 
				
			||||||
 | 
					                Log.e("TransactionAdapter", "❌ Backend update error: " + e.getMessage(), e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }).start();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Format created_at date to readable format
 | 
					     * Format created_at date to readable format
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user