From d34cdbec13891f8b1444548dedb535f032541e99 Mon Sep 17 00:00:00 2001
From: ahmadAlfhajri <82349749+ahmadAlfhajri@users.noreply.github.com>
Date: Fri, 24 Jan 2025 16:04:35 +0800
Subject: [PATCH 1/2] fix: Handle 3DS authentication edge case and version
 tracking

- Fix premature webview dismissal caused by unexpected callback responses before 3DS OTP authentication
- Correct version name tracking implementation
---
 .../src/main/java/com/xendit/Xendit.java      |  3 +-
 .../main/java/com/xendit/XenditActivity.java  |  9 ++--
 .../xendit/utils/Auth3DSEventValidator.java   | 43 +++++++++++++++++++
 3 files changed, 49 insertions(+), 6 deletions(-)
 create mode 100644 xendit-android/src/main/java/com/xendit/utils/Auth3DSEventValidator.java

diff --git a/xendit-android/src/main/java/com/xendit/Xendit.java b/xendit-android/src/main/java/com/xendit/Xendit.java
index 9f100fb..81d7dbe 100644
--- a/xendit-android/src/main/java/com/xendit/Xendit.java
+++ b/xendit-android/src/main/java/com/xendit/Xendit.java
@@ -75,7 +75,6 @@ public class Xendit {
     private static final String GET_3DS_URL = PRODUCTION_XENDIT_BASE_URL + "/3ds_bin_recommendation";
     private static final String DSN_SERVER = "https://7190a1331444434eb6aed7b5a8d776f0@o30316.ingest.sentry.io/6314580";
     private static final String CLIENT_IDENTIFIER = "Xendit Android SDK";
-    private static final String CLIENT_API_VERSION = "2.0.0";
     private static final String CLIENT_TYPE = "SDK";
     static final String ACTION_KEY = "ACTION_KEY";
 
@@ -1499,7 +1498,7 @@ private BaseRequest buildBaseRequest(int method, String url, String onBehalfOf,
         }
         request.addHeader("Authorization", basicAuthCredentials.replace("\n", ""));
         request.addHeader("x-client-identifier", CLIENT_IDENTIFIER);
-        request.addHeader("client-version", CLIENT_API_VERSION);
+        request.addHeader("client-version", BuildConfig.VERSION_NAME);
         request.addHeader("client-type", CLIENT_TYPE);
         return request;
     }
diff --git a/xendit-android/src/main/java/com/xendit/XenditActivity.java b/xendit-android/src/main/java/com/xendit/XenditActivity.java
index 57fd0f9..79691d6 100644
--- a/xendit-android/src/main/java/com/xendit/XenditActivity.java
+++ b/xendit-android/src/main/java/com/xendit/XenditActivity.java
@@ -13,8 +13,8 @@
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 import android.widget.ProgressBar;
-
 import com.xendit.Models.HasAuthenticationUrl;
+import com.xendit.utils.Auth3DSEventValidator;
 
 /**
  * Created by Sergey on 3/23/17.
@@ -99,9 +99,10 @@ public void postMessage(String message) {
             handler.post(new Runnable() {
                 @Override
                 public void run() {
-                    sendBroadcastReceiver(message);
-
-                    finish();
+                    if (Auth3DSEventValidator.is3DSResultEventFromXendit(message, XenditActivity.this)) {
+                        sendBroadcastReceiver(message);
+                        finish();
+                    }
                 }
             });
         }
diff --git a/xendit-android/src/main/java/com/xendit/utils/Auth3DSEventValidator.java b/xendit-android/src/main/java/com/xendit/utils/Auth3DSEventValidator.java
new file mode 100644
index 0000000..c5b4eef
--- /dev/null
+++ b/xendit-android/src/main/java/com/xendit/utils/Auth3DSEventValidator.java
@@ -0,0 +1,43 @@
+package com.xendit.utils;
+
+import android.content.Context;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.xendit.R;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Auth3DSEventValidator {
+  private static final String ID_FIELD = "id";
+  private static final String STATUS_FIELD = "status";
+
+  private Auth3DSEventValidator() {
+    // Private constructor to prevent instantiation
+  }
+
+  public static boolean is3DSResultEventFromXendit(String message, Context context) {
+    if (message.isEmpty()) return false;
+
+    return isValidJsonMessage(message) || isKnownErrorMessage(message, context);
+  }
+
+  private static boolean isValidJsonMessage(String message) {
+    try {
+      Map<String, Object> messageInJson = new Gson().fromJson(
+          message,
+          new TypeToken<HashMap<String, Object>>() {}.getType()
+      );
+
+      // A valid 3ds callback payload from Xendit, should contain required fields: id and status.
+      return messageInJson.get(ID_FIELD) != null && messageInJson.get(STATUS_FIELD) != null;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  private static boolean isKnownErrorMessage(String message, Context context) {
+    return message.equals(context.getString(R.string.create_token_error_validation)) ||
+        message.equals(context.getString(R.string.tokenization_error));
+  }
+
+}

From 8b54a94388b3d0ff3f3ecb822ac7d89e8411bbd3 Mon Sep 17 00:00:00 2001
From: ahmadAlfhajri <82349749+ahmadAlfhajri@users.noreply.github.com>
Date: Fri, 24 Jan 2025 16:24:01 +0800
Subject: [PATCH 2/2] Bump version to 4.2.3

---
 CHANGELOG.md                | 3 +++
 README.md                   | 8 ++++----
 xendit-android/build.gradle | 4 ++--
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 70bb1d1..0c890b6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
 # CHANGELOG
 
+## 4.2.3 (2025-01-24)
+- Fix: Handle 3DS authentication edge case and version tracking
+
 ## 4.2.2 (2024-11-21)
 - Fixed app crash related to unregistered AuthenticationBroadcastReceiver by implementing proper lifecycle-aware receiver management
 
diff --git a/README.md b/README.md
index 4ce084e..0203315 100644
--- a/README.md
+++ b/README.md
@@ -31,24 +31,24 @@ Maven:
 <dependency>
   <groupId>com.xendit</groupId>
   <artifactId>xendit-android</artifactId>
-  <version>4.2.2</version>
+  <version>4.2.3</version>
   <type>pom</type>
 </dependency>
 ```
 
 Gradle:
 ```
-compile 'com.xendit:xendit-android:4.2.2'
+compile 'com.xendit:xendit-android:4.2.3'
 ```
 
 Ivy:
 ```
-<dependency org='com.xendit' name='xendit-android' rev='4.2.2'>
+<dependency org='com.xendit' name='xendit-android' rev='4.2.3'>
   <artifact name='xendit-android' ext='pom' ></artifact>
 </dependency>
 ```
 
-For more information, visit https://central.sonatype.com/artifact/com.xendit/xendit-android/4.2.2/versions
+For more information, visit https://central.sonatype.com/artifact/com.xendit/xendit-android/4.2.3/versions
 
 **Note**:
 
diff --git a/xendit-android/build.gradle b/xendit-android/build.gradle
index 8da1720..df02fbe 100644
--- a/xendit-android/build.gradle
+++ b/xendit-android/build.gradle
@@ -3,7 +3,7 @@ apply plugin: 'maven-publish'
 apply plugin: 'signing'
 
 group 'com.xendit'
-version '4.2.2'
+version '4.2.3'
 
 ext {
     bintrayOrg = 'xendit'
@@ -37,7 +37,7 @@ android {
         minSdkVersion 21
         targetSdkVersion 34
         versionCode 1
-        versionName '4.2.2'
+        versionName '4.2.3'
         testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
     }
     buildTypes {