diff --git a/app/build.gradle b/app/build.gradle index dae55838..79ebfb52 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -109,5 +109,6 @@ dependencies { implementation jscFlavor } implementation project(':hyperswitch-sdk-android-logger') + implementation project(':hyperswitch-sdk-android-superposition') api project(':hyperswitch-sdk-android-api') } \ No newline at end of file diff --git a/app/src/main/kotlin/io/hyperswitch/paymentsession/DefaultPaymentSessionLauncher.kt b/app/src/main/kotlin/io/hyperswitch/paymentsession/DefaultPaymentSessionLauncher.kt index cc65f5d7..398c4553 100644 --- a/app/src/main/kotlin/io/hyperswitch/paymentsession/DefaultPaymentSessionLauncher.kt +++ b/app/src/main/kotlin/io/hyperswitch/paymentsession/DefaultPaymentSessionLauncher.kt @@ -6,6 +6,7 @@ import io.hyperswitch.PaymentEventSubscriptionBuilder import io.hyperswitch.logs.HyperLogManager import io.hyperswitch.logs.LogFileManager import io.hyperswitch.logs.LogUtils.getLoggingUrl +import io.hyperswitch.superposition.SuperpositionManager import io.hyperswitch.paymentsheet.PaymentSheet import io.hyperswitch.paymentsheet.PaymentResult import io.hyperswitch.react.HyperEventEmitter @@ -37,6 +38,14 @@ class DefaultPaymentSessionLauncher( } HyperLogManager.initialise(publishableKey, loggingEndPoint) HyperLogManager.sendLogsFromFile(LogFileManager(activity)) + + // Initialize and fetch Superposition config + SuperpositionManager.initialise( + host = "http://10.0.2.2:5252", + profileId = "test-id", + apiKey = publishableKey + ) + SuperpositionManager.fetchConfig() } paymentSessionReactLauncher.initializeReactNativeInstance() } diff --git a/app/src/main/kotlin/io/hyperswitch/paymentsession/PaymentSessionReactLauncher.kt b/app/src/main/kotlin/io/hyperswitch/paymentsession/PaymentSessionReactLauncher.kt index a6885ad4..75a3fefe 100644 --- a/app/src/main/kotlin/io/hyperswitch/paymentsession/PaymentSessionReactLauncher.kt +++ b/app/src/main/kotlin/io/hyperswitch/paymentsession/PaymentSessionReactLauncher.kt @@ -21,6 +21,7 @@ import com.facebook.react.uimanager.PixelUtil import io.hyperswitch.BuildConfig import io.hyperswitch.react.ReactNativeController import io.hyperswitch.paymentsession.DefaultPaymentSessionLauncher.Companion.sdkAuthorization +import io.hyperswitch.superposition.SuperpositionManager import io.hyperswitch.paymentsheet.PaymentSheet import io.hyperswitch.react.HyperActivity import io.hyperswitch.react.HyperFragment @@ -123,26 +124,31 @@ class PaymentSessionReactLauncher(private val activity: Activity) : SDKInterface } } + private fun injectSuperpositionConfig(bundle: Bundle) { + SuperpositionManager.getCachedConfig()?.configJson?.let { + bundle.getBundle("props")?.getBundle("hyperParams")?.putString("superpositionConfigRaw", it) + } + } + override fun presentSheet( sdkAuthorization: String, configuration: PaymentSheet.Configuration? ): Boolean { val subscribedEvents = getSubscribedEventsSafely() val bundle = launchOptions.getBundle(sdkAuthorization, configuration,subscribedEvents) + injectSuperpositionConfig(bundle) applyFonts(configuration, bundle) return presentSheet(bottomInsetToDIPFromPixel(bundle)) } override fun presentSheet(configurationMap: Map): Boolean { val subscribedEvents = getSubscribedEventsSafely() - return presentSheet( - bottomInsetToDIPFromPixel( - launchOptions.getBundleWithHyperParams( - configurationMap, - subscribedEvents - ) - ) + val bundle = launchOptions.getBundleWithHyperParams( + configurationMap, + subscribedEvents ) + injectSuperpositionConfig(bundle) + return presentSheet(bottomInsetToDIPFromPixel(bundle)) } private fun presentSheet(bundle: Bundle): Boolean { diff --git a/gradle.properties b/gradle.properties index 84361838..6c36ea50 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,3 +40,4 @@ scancardVersion=1.0.0 webviewVersion=1.0.5 rnlibVersion=1.0.1 airBorneVersion=1.0.0 +superpositionVersion=1.0.0 diff --git a/hyperswitch-sdk-android-common/build.gradle b/hyperswitch-sdk-android-common/build.gradle index 1f996580..c81b8fa1 100644 --- a/hyperswitch-sdk-android-common/build.gradle +++ b/hyperswitch-sdk-android-common/build.gradle @@ -26,4 +26,5 @@ android { dependencies { api libs.playServicesWallet api libs.eventBus + implementation libs.okhttp } \ No newline at end of file diff --git a/hyperswitch-sdk-android-logger/src/main/kotlin/io/hyperswitch/networking/HyperNetworking.kt b/hyperswitch-sdk-android-common/src/main/kotlin/io/hyperswitch/networking/HyperNetworking.kt similarity index 88% rename from hyperswitch-sdk-android-logger/src/main/kotlin/io/hyperswitch/networking/HyperNetworking.kt rename to hyperswitch-sdk-android-common/src/main/kotlin/io/hyperswitch/networking/HyperNetworking.kt index e1b31284..28930911 100644 --- a/hyperswitch-sdk-android-logger/src/main/kotlin/io/hyperswitch/networking/HyperNetworking.kt +++ b/hyperswitch-sdk-android-common/src/main/kotlin/io/hyperswitch/networking/HyperNetworking.kt @@ -53,7 +53,7 @@ object HyperNetworking { override fun onResponse(call: Call, response: Response) { response.use { when { - it.isSuccessful -> callback(Result.success(it.body?.string() ?: "success")) + it.isSuccessful -> callback(Result.success(it.body?.string().orEmpty())) it.code == 401 -> callback(Result.failure(Exception("Unauthorized (401) - Check API Key"))) it.code == 500 -> callback(Result.failure(Exception("Server Error (500) - Try again later"))) else -> callback(Result.failure(Exception("HTTP Error: ${it.code} - ${it.message}"))) @@ -75,4 +75,18 @@ object HyperNetworking { callback = callback ) } + + fun makeGetRequest( + urlString: String, + headers: Map = emptyMap(), + callback: (Result) -> Unit + ) { + makeHttpRequest( + urlString = urlString, + method = "GET", + headers = headers, + body = null, + callback = callback + ) + } } \ No newline at end of file diff --git a/hyperswitch-sdk-android-logger/build.gradle b/hyperswitch-sdk-android-logger/build.gradle index bc4ac3e6..542d4cd0 100644 --- a/hyperswitch-sdk-android-logger/build.gradle +++ b/hyperswitch-sdk-android-logger/build.gradle @@ -24,6 +24,6 @@ android { } dependencies { - implementation libs.okhttp + implementation project(':hyperswitch-sdk-android-common') implementation libs.androidx.preference } \ No newline at end of file diff --git a/hyperswitch-sdk-android-superposition/.gitignore b/hyperswitch-sdk-android-superposition/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/hyperswitch-sdk-android-superposition/.gitignore @@ -0,0 +1 @@ +/build diff --git a/hyperswitch-sdk-android-superposition/build.gradle b/hyperswitch-sdk-android-superposition/build.gradle new file mode 100644 index 00000000..88ca0dfd --- /dev/null +++ b/hyperswitch-sdk-android-superposition/build.gradle @@ -0,0 +1,28 @@ +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' +} + +group = "io.hyperswitch" +version = superpositionVersion + +android { + namespace 'io.hyperswitch.superposition' + compileSdk rootProject.ext.compileSdkVersion + + defaultConfig { + minSdk rootProject.ext.minSdkVersion + consumerProguardFiles "consumer-rules.pro" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation project(':hyperswitch-sdk-android-common') +} diff --git a/hyperswitch-sdk-android-superposition/consumer-rules.pro b/hyperswitch-sdk-android-superposition/consumer-rules.pro new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/hyperswitch-sdk-android-superposition/consumer-rules.pro @@ -0,0 +1 @@ + diff --git a/hyperswitch-sdk-android-superposition/proguard-rules.pro b/hyperswitch-sdk-android-superposition/proguard-rules.pro new file mode 100644 index 00000000..97b1005e --- /dev/null +++ b/hyperswitch-sdk-android-superposition/proguard-rules.pro @@ -0,0 +1,9 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Keep SuperpositionManager public API +-keep class io.hyperswitch.superposition.SuperpositionManager { *; } diff --git a/hyperswitch-sdk-android-superposition/src/main/kotlin/io/hyperswitch/superposition/SuperpositionConfig.kt b/hyperswitch-sdk-android-superposition/src/main/kotlin/io/hyperswitch/superposition/SuperpositionConfig.kt new file mode 100644 index 00000000..90e23fc8 --- /dev/null +++ b/hyperswitch-sdk-android-superposition/src/main/kotlin/io/hyperswitch/superposition/SuperpositionConfig.kt @@ -0,0 +1,5 @@ +package io.hyperswitch.superposition + +data class SuperpositionConfig( + val configJson: String? = null +) diff --git a/hyperswitch-sdk-android-superposition/src/main/kotlin/io/hyperswitch/superposition/SuperpositionManager.kt b/hyperswitch-sdk-android-superposition/src/main/kotlin/io/hyperswitch/superposition/SuperpositionManager.kt new file mode 100644 index 00000000..da9e7a9c --- /dev/null +++ b/hyperswitch-sdk-android-superposition/src/main/kotlin/io/hyperswitch/superposition/SuperpositionManager.kt @@ -0,0 +1,42 @@ +package io.hyperswitch.superposition + +import android.util.Log +import io.hyperswitch.networking.HyperNetworking + +object SuperpositionManager { + + private const val TAG = "SuperpositionManager" + + private var host: String? = null + private var profileId: String? = null + private var apiKey: String? = null + @Volatile private var cachedConfig: SuperpositionConfig? = null + + fun initialise(host: String, profileId: String, apiKey: String) { + this.host = host + this.profileId = profileId + this.apiKey = apiKey + cachedConfig = null + } + + fun fetchConfig() { + val h = host ?: return + val pid = profileId ?: return + val ak = apiKey ?: return + + val url = "$h/v1/sdk/configs/$pid/web/sandbox.json" + Log.d(TAG, "Fetching superposition config from: $url") + HyperNetworking.makeGetRequest(url, mapOf("Content-Type" to "application/json", "api-key" to ak)) { result -> + result.onSuccess { json -> + if (json.isNotBlank()) { + cachedConfig = SuperpositionConfig(configJson = json) + Log.d(TAG, "Config fetched successfully") + Log.d(TAG, "Superposition config response: $json") + } + } + result.onFailure { e -> Log.e(TAG, "Config fetch failed: ${e.message}") } + } + } + + fun getCachedConfig(): SuperpositionConfig? = cachedConfig +} diff --git a/settings.gradle b/settings.gradle index c0dbfe08..8d7519c5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,6 +21,7 @@ include ':hyperswitch-sdk-android-click-to-pay' include ':hyperswitch-sdk-android-common' include ':hyperswitch-sdk-android-lite' include ':hyperswitch-sdk-android-logger' +include ':hyperswitch-sdk-android-superposition' include ':hyperswitch-sdk-android-scancard' include ':hyperswitch-sdk-android-webview-utils' include ':hyperswitch-sdk-android-airborne'