diff --git a/.gitignore b/.gitignore
index eb5751cfb..02923dd7b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,3 +90,6 @@ lint/reports/
# Sandbox stuff
_sandbox
+
+# Since Kotlin 2.0.0
+.kotlin/
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 148fdd246..6d0ee1c2a 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 8fd7fd87e..dfe216554 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,9 +2,9 @@
buildscript {
ext {
- androidGradlePluginVersion = '8.4.1'
- kotlinVersion = '1.9.24'
- kspVersion = '1.9.24-1.0.20'
+ androidGradlePluginVersion = '8.4.2'
+ kotlinVersion = '2.0.0'
+ kspVersion = '2.0.0-1.0.22'
dokkaVersion = '1.9.20'
androidxNavigationVersion = '2.7.7'
nexusPublishPluginVersion = '2.0.0'
@@ -18,6 +18,7 @@ plugins {
id 'com.android.application' version "$androidGradlePluginVersion" apply false
id 'com.android.library' version "$androidGradlePluginVersion" apply false
id 'org.jetbrains.kotlin.android' version "$kotlinVersion" apply false
+ id 'org.jetbrains.kotlin.plugin.compose' version "$kotlinVersion" apply false
id 'org.jetbrains.dokka' version "$dokkaVersion" apply true
id 'com.google.devtools.ksp' version "$kspVersion" apply false
id 'io.github.gradle-nexus.publish-plugin' version "$nexusPublishPluginVersion" apply true
@@ -36,7 +37,7 @@ ext {
publishVersion = file('version.resolved').getText().trim()
androidxCoreVersion = '1.13.1'
- androidxAppCompatVersion = '1.6.1'
+ androidxAppCompatVersion = '1.7.0'
androidxConstraintLayoutVersion = '2.1.4'
androidxActivityVersion = '1.9.0'
androidxFragmentVersion = '1.7.1'
@@ -46,11 +47,10 @@ ext {
androidxBrowserVersion = '1.8.0'
androidxComposeBOMVersion = '2024.05.00'
- androidxComposeCompilerVersion = '1.5.14'
materialVersion = '1.12.0'
- gmsWalletVersion = '19.3.0'
+ gmsWalletVersion = '19.4.0'
kotlinxCoroutinesPlayServicesVersion = '1.8.1'
retrofitVersion = '2.11.0'
@@ -59,7 +59,7 @@ ext {
okioVersion = '3.9.0'
coilVersion = '2.6.0'
commonMarkVersion = '0.22.0'
- libphonenumberVersion = '8.13.37'
+ libphonenumberVersion = '8.13.38'
checkout3dsSdkVersion = '3.2.2'
adyen3dsSdkVersion = '2.2.15'
diff --git a/checkout-3ds/build.gradle b/checkout-3ds/build.gradle
index 255120470..bae7ef0bd 100644
--- a/checkout-3ds/build.gradle
+++ b/checkout-3ds/build.gradle
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
@@ -51,10 +53,6 @@ android {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = '17'
- freeCompilerArgs += '-opt-in=com.processout.sdk.core.annotation.ProcessOutInternalApi'
- }
publishing {
singleVariant("productionRelease") {
@@ -66,6 +64,13 @@ android {
}
}
+kotlin {
+ compilerOptions {
+ jvmTarget.set(JvmTarget.JVM_17)
+ optIn.add("com.processout.sdk.core.annotation.ProcessOutInternalApi")
+ }
+}
+
@SuppressWarnings('GrMethodMayBeStatic')
def setBuildConfig(buildType) {
buildType.buildConfigField("String", "LIBRARY_NAME", "\"ProcessOut Android SDK - Checkout 3DS\"")
diff --git a/example/build.gradle b/example/build.gradle
index b7abc4600..fad795f47 100644
--- a/example/build.gradle
+++ b/example/build.gradle
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
@@ -52,10 +54,13 @@ android {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = '17'
- freeCompilerArgs += '-opt-in=com.processout.sdk.core.annotation.ProcessOutInternalApi'
- freeCompilerArgs += '-opt-in=com.processout.sdk.ui.core.annotation.ProcessOutInternalApi'
+}
+
+kotlin {
+ compilerOptions {
+ jvmTarget.set(JvmTarget.JVM_17)
+ optIn.add("com.processout.sdk.core.annotation.ProcessOutInternalApi")
+ optIn.add("com.processout.sdk.ui.core.annotation.ProcessOutInternalApi")
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 1f3e86b56..8dda536a2 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Wed Oct 05 19:43:19 EEST 2022
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/sdk/build.gradle b/sdk/build.gradle
index 808f4f837..bd07057e7 100644
--- a/sdk/build.gradle
+++ b/sdk/build.gradle
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
@@ -63,10 +65,6 @@ android {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = '17'
- freeCompilerArgs += '-opt-in=com.processout.sdk.core.annotation.ProcessOutInternalApi'
- }
testOptions {
unitTests {
@@ -88,6 +86,13 @@ android {
}
}
+kotlin {
+ compilerOptions {
+ jvmTarget.set(JvmTarget.JVM_17)
+ optIn.add("com.processout.sdk.core.annotation.ProcessOutInternalApi")
+ }
+}
+
@SuppressWarnings('GrMethodMayBeStatic')
def setBuildConfig(buildType) {
buildType.buildConfigField("String", "LIBRARY_NAME", "\"ProcessOut Android SDK\"")
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/ProcessOut.kt b/sdk/src/main/kotlin/com/processout/sdk/api/ProcessOut.kt
index f1ca4f1c2..698a24fb1 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/api/ProcessOut.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/ProcessOut.kt
@@ -9,6 +9,7 @@ import com.processout.sdk.api.dispatcher.POEventDispatchers
import com.processout.sdk.api.dispatcher.PONativeAlternativePaymentMethodEventDispatcher
import com.processout.sdk.api.dispatcher.napm.PODefaultNativeAlternativePaymentMethodEventDispatcher
import com.processout.sdk.api.network.ApiConstants
+import com.processout.sdk.api.preferences.Preferences
import com.processout.sdk.api.repository.POCardsRepository
import com.processout.sdk.api.repository.POGatewayConfigurationsRepository
import com.processout.sdk.api.service.POAlternativePaymentMethodsService
@@ -58,6 +59,9 @@ class ProcessOut private constructor(
apiGraph.serviceGraph.browserCapabilitiesService
}
+ /** Dispatchers that allows to handle events during various payment flows. */
+ val dispatchers: POEventDispatchers by lazy { DefaultEventDispatchers }
+
/** Dispatcher that allows to handle events during native alternative payments. */
@Deprecated(
message = "Use replacement property.",
@@ -67,9 +71,6 @@ class ProcessOut private constructor(
PODefaultNativeAlternativePaymentMethodEventDispatcher
}
- /** Dispatchers that allows to handle events during various payment flows. */
- val dispatchers: POEventDispatchers by lazy { DefaultEventDispatchers }
-
/**
* Entry point to ProcessOut Android SDK.
* Provides configuration and access to services.
@@ -103,26 +104,27 @@ class ProcessOut private constructor(
* the configuration applies only on first invocation and all subsequent calls are ignored.
* When set to _true_, the existing instances will be reconfigured.
*/
- fun configure(configuration: ProcessOutConfiguration, force: Boolean = false) {
+ fun configure(
+ configuration: ProcessOutConfiguration,
+ force: Boolean = false
+ ) {
if (isConfigured) {
- if (force) {
- with(instance.apiGraph) {
- contextGraph.configuration = configuration
- POLogger.clear()
- if (configuration.debug) {
- POLogger.add(serviceGraph.systemLoggerService)
- POLogger.info("Applied new ProcessOut configuration.")
- }
- }
- } else {
+ if (!force) {
POLogger.info("ProcessOut is already configured.")
+ return
}
+ with(instance.apiGraph) {
+ contextGraph.configuration = configuration
+ configureLogger(configuration, serviceGraph)
+ }
+ POLogger.info("Applied new ProcessOut configuration.")
} else {
val contextGraph = DefaultContextGraph(
configuration = configuration
)
val networkGraph = DefaultNetworkGraph(
contextGraph = contextGraph,
+ preferences = Preferences(contextGraph),
baseUrl = ApiConstants.BASE_URL,
sdkVersion = VERSION
)
@@ -145,10 +147,21 @@ class ProcessOut private constructor(
instance = lazy { ProcessOut(apiGraph) }.value
legacyInstance = lazy { ProcessOutLegacyAccessor.configure(contextGraph) }.value
- if (configuration.debug) {
- POLogger.add(serviceGraph.systemLoggerService)
- POLogger.info("ProcessOut configuration is complete.")
- }
+ configureLogger(configuration, serviceGraph)
+ POLogger.info("ProcessOut configuration is complete.")
+ }
+ }
+
+ private fun configureLogger(
+ configuration: ProcessOutConfiguration,
+ serviceGraph: ServiceGraph
+ ) {
+ POLogger.clear()
+ if (configuration.debug) {
+ POLogger.add(serviceGraph.systemLoggerService)
+ }
+ if (configuration.enableTelemetry) {
+ POLogger.add(serviceGraph.telemetryService)
}
}
}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/ProcessOutConfiguration.kt b/sdk/src/main/kotlin/com/processout/sdk/api/ProcessOutConfiguration.kt
index a7d8f4333..1e792bd6a 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/api/ProcessOutConfiguration.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/ProcessOutConfiguration.kt
@@ -3,6 +3,7 @@ package com.processout.sdk.api
import android.app.Application
import androidx.annotation.VisibleForTesting
import com.processout.sdk.core.annotation.ProcessOutInternalApi
+import java.util.UUID
/**
* Defines ProcessOut configuration.
@@ -10,12 +11,30 @@ import com.processout.sdk.core.annotation.ProcessOutInternalApi
* @param[application] Instance of the [Application].
* @param[projectId] Project ID.
* @param[debug] Enables debug mode. Default value is _false_. __Note:__ debug logs may contain sensitive data.
+ * @param[enableTelemetry] Enables sending telemetry data to ProcessOut. Default value is _false_.
+ * @param[applicationInformation] Application information that helps ProcessOut to troubleshoot potential issues.
*/
data class ProcessOutConfiguration(
val application: Application,
val projectId: String,
- val debug: Boolean = false
+ val debug: Boolean = false,
+ val enableTelemetry: Boolean = false,
+ val applicationInformation: ApplicationInformation? = null
) {
+
+ /**
+ * Application information that helps ProcessOut to troubleshoot potential issues.
+ *
+ * @param[name] Application name.
+ * @param[version] Application version.
+ */
+ data class ApplicationInformation(
+ val name: String? = null,
+ val version: String? = null
+ )
+
+ internal val sessionId = UUID.randomUUID().toString()
+
/**
* __Warning:__ Intended to be used only for testing purposes.
* Storing private key inside application is extremely dangerous and is highly discouraged.
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/request/DeviceData.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/DeviceData.kt
index cc6c5611b..268a15eff 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/api/model/request/DeviceData.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/DeviceData.kt
@@ -1,5 +1,6 @@
package com.processout.sdk.api.model.request
+import android.os.Build
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@@ -8,10 +9,14 @@ internal data class DeviceData(
@Json(name = "app_language")
val appLanguage: String,
@Json(name = "app_screen_width")
- val appScreenWidth: Int,
+ val screenWidth: Int,
@Json(name = "app_screen_height")
- val appScreenHeight: Int,
+ val screenHeight: Int,
@Json(name = "app_timezone_offset")
- val appTimeZoneOffset: Int,
- val channel: String = "android"
+ val timeZoneOffset: Int,
+ val channel: String = "android",
+ @Json(ignore = true)
+ val model: String = "${Build.MANUFACTURER} ${Build.MODEL}",
+ @Json(ignore = true)
+ val systemApiLevel: String = Build.VERSION.SDK_INT.toString()
)
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/request/LogRequest.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/LogRequest.kt
deleted file mode 100644
index 6d17f781f..000000000
--- a/sdk/src/main/kotlin/com/processout/sdk/api/model/request/LogRequest.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.processout.sdk.api.model.request
-
-import com.squareup.moshi.JsonClass
-import java.util.Date
-
-@JsonClass(generateAdapter = true)
-internal data class LogRequest(
- val level: String,
- val tag: String,
- val message: String,
- val timestamp: Date,
- val attributes: Map
-)
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/request/TelemetryRequest.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/TelemetryRequest.kt
new file mode 100644
index 000000000..6e6ac5c9c
--- /dev/null
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/TelemetryRequest.kt
@@ -0,0 +1,58 @@
+package com.processout.sdk.api.model.request
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+import java.util.Date
+
+@JsonClass(generateAdapter = true)
+internal data class TelemetryRequest(
+ val events: List,
+ val metadata: Metadata
+) {
+
+ /**
+ * @param[timestamp] RFC3339 encoded timestamp.
+ * @param[level] Event level: debug, info, warn, error.
+ */
+ @JsonClass(generateAdapter = true)
+ data class Event(
+ val timestamp: Date,
+ val level: String,
+ val message: String,
+ @Json(name = "gateway_configuration_id")
+ val gatewayConfigurationId: String?,
+ @Json(name = "customer_id")
+ val customerId: String?,
+ @Json(name = "customer_token_id")
+ val customerTokenId: String?,
+ @Json(name = "card_id")
+ val cardId: String?,
+ @Json(name = "invoice_id")
+ val invoiceId: String?,
+ val attributes: Map
+ )
+
+ @JsonClass(generateAdapter = true)
+ data class Metadata(
+ val application: ApplicationMetadata,
+ val device: DeviceMetadata
+ )
+
+ @JsonClass(generateAdapter = true)
+ data class ApplicationMetadata(
+ val name: String?,
+ val version: String?
+ )
+
+ /**
+ * @param[language] Default locale of the client device.
+ * @param[timeZone] UTC offset of the device time zone.
+ */
+ @JsonClass(generateAdapter = true)
+ data class DeviceMetadata(
+ val language: String,
+ val model: String,
+ @Json(name = "time_zone")
+ val timeZone: Int
+ )
+}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/response/TelemetryResponse.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/response/TelemetryResponse.kt
new file mode 100644
index 000000000..98b72b445
--- /dev/null
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/model/response/TelemetryResponse.kt
@@ -0,0 +1,8 @@
+package com.processout.sdk.api.model.response
+
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class TelemetryResponse(
+ val success: Boolean
+)
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/network/LogsApi.kt b/sdk/src/main/kotlin/com/processout/sdk/api/network/LogsApi.kt
deleted file mode 100644
index b5e10aed9..000000000
--- a/sdk/src/main/kotlin/com/processout/sdk/api/network/LogsApi.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.processout.sdk.api.network
-
-import com.processout.sdk.api.model.request.LogRequest
-import retrofit2.Response
-import retrofit2.http.Body
-import retrofit2.http.POST
-
-internal interface LogsApi {
-
- @POST("/logs")
- suspend fun send(@Body request: LogRequest): Response
-}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/network/TelemetryApi.kt b/sdk/src/main/kotlin/com/processout/sdk/api/network/TelemetryApi.kt
new file mode 100644
index 000000000..ae350489d
--- /dev/null
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/network/TelemetryApi.kt
@@ -0,0 +1,13 @@
+package com.processout.sdk.api.network
+
+import com.processout.sdk.api.model.request.TelemetryRequest
+import com.processout.sdk.api.model.response.TelemetryResponse
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.POST
+
+internal interface TelemetryApi {
+
+ @POST("/telemetry")
+ suspend fun send(@Body request: TelemetryRequest): Response
+}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/network/interceptor/UserAgentInterceptor.kt b/sdk/src/main/kotlin/com/processout/sdk/api/network/interceptor/UserAgentInterceptor.kt
index 9c516093b..1fd50491d 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/api/network/interceptor/UserAgentInterceptor.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/network/interceptor/UserAgentInterceptor.kt
@@ -1,5 +1,6 @@
package com.processout.sdk.api.network.interceptor
+import com.processout.sdk.api.preferences.Preferences
import com.processout.sdk.core.locale.currentSdkLocale
import com.processout.sdk.di.ContextGraph
import okhttp3.Interceptor
@@ -10,6 +11,7 @@ import java.util.UUID
internal class UserAgentInterceptor(
private val contextGraph: ContextGraph,
+ private val preferences: Preferences,
private val sdkVersion: String
) : Interceptor {
@@ -24,6 +26,11 @@ internal class UserAgentInterceptor(
.header("Idempotency-Key", UUID.randomUUID().toString())
.header("User-Agent", userAgentComponents.joinToString(separator = "/"))
.header("Accept-Language", contextGraph.configuration.application.currentSdkLocale().toLanguageTag())
+ .header("Session-Id", contextGraph.configuration.sessionId)
+ .header("Installation-Id", preferences.installationId)
+ .header("Device-System-Name", contextGraph.deviceData.channel)
+ .header("Device-System-Version", contextGraph.deviceData.systemApiLevel)
+ .header("Product-Version", sdkVersion)
.build()
return chain.proceed(userAgentRequest)
}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/preferences/Preferences.kt b/sdk/src/main/kotlin/com/processout/sdk/api/preferences/Preferences.kt
new file mode 100644
index 000000000..237bb3d5f
--- /dev/null
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/preferences/Preferences.kt
@@ -0,0 +1,38 @@
+package com.processout.sdk.api.preferences
+
+import android.content.Context
+import androidx.core.content.edit
+import com.processout.sdk.BuildConfig
+import com.processout.sdk.di.ContextGraph
+import kotlinx.coroutines.*
+import java.util.UUID
+
+internal class Preferences(
+ contextGraph: ContextGraph,
+ scope: CoroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob()),
+ workDispatcher: CoroutineDispatcher = Dispatchers.IO
+) {
+
+ private companion object {
+ const val FILENAME = "${BuildConfig.LIBRARY_PACKAGE_NAME}.preferences"
+ const val KEY_INSTALLATION_ID = "InstallationId"
+ }
+
+ private val sharedPreferences = contextGraph.configuration.application
+ .getSharedPreferences(FILENAME, Context.MODE_PRIVATE)
+
+ var installationId = String()
+ private set
+
+ init {
+ scope.launch(workDispatcher) {
+ installationId = sharedPreferences.getString(KEY_INSTALLATION_ID, String()) ?: String()
+ if (installationId.isEmpty()) {
+ installationId = UUID.randomUUID().toString()
+ sharedPreferences.edit(commit = true) {
+ putString(KEY_INSTALLATION_ID, installationId)
+ }
+ }
+ }
+ }
+}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultLogsRepository.kt b/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultLogsRepository.kt
deleted file mode 100644
index da908ee43..000000000
--- a/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultLogsRepository.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.processout.sdk.api.repository
-
-import com.processout.sdk.api.model.request.LogRequest
-import com.processout.sdk.api.network.LogsApi
-import kotlinx.coroutines.launch
-
-internal class DefaultLogsRepository(
- failureMapper: ApiFailureMapper,
- private val api: LogsApi
-) : BaseRepository(failureMapper), LogsRepository {
-
- override fun send(request: LogRequest) {
- repositoryScope.launch {
- apiCall { api.send(request) }
- }
- }
-}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultTelemetryRepository.kt b/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultTelemetryRepository.kt
new file mode 100644
index 000000000..ca69b1ad9
--- /dev/null
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultTelemetryRepository.kt
@@ -0,0 +1,13 @@
+package com.processout.sdk.api.repository
+
+import com.processout.sdk.api.model.request.TelemetryRequest
+import com.processout.sdk.api.network.TelemetryApi
+
+internal class DefaultTelemetryRepository(
+ failureMapper: ApiFailureMapper,
+ private val api: TelemetryApi
+) : BaseRepository(failureMapper), TelemetryRepository {
+
+ override suspend fun send(request: TelemetryRequest) =
+ apiCall { api.send(request) }
+}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/repository/LogsRepository.kt b/sdk/src/main/kotlin/com/processout/sdk/api/repository/LogsRepository.kt
deleted file mode 100644
index 4463f33b4..000000000
--- a/sdk/src/main/kotlin/com/processout/sdk/api/repository/LogsRepository.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.processout.sdk.api.repository
-
-import com.processout.sdk.api.model.request.LogRequest
-
-internal interface LogsRepository {
-
- fun send(request: LogRequest)
-}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/repository/TelemetryRepository.kt b/sdk/src/main/kotlin/com/processout/sdk/api/repository/TelemetryRepository.kt
new file mode 100644
index 000000000..2aeacd232
--- /dev/null
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/repository/TelemetryRepository.kt
@@ -0,0 +1,10 @@
+package com.processout.sdk.api.repository
+
+import com.processout.sdk.api.model.request.TelemetryRequest
+import com.processout.sdk.api.model.response.TelemetryResponse
+import com.processout.sdk.core.ProcessOutResult
+
+internal interface TelemetryRepository {
+
+ suspend fun send(request: TelemetryRequest): ProcessOutResult
+}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/service/RemoteLoggerService.kt b/sdk/src/main/kotlin/com/processout/sdk/api/service/RemoteLoggerService.kt
deleted file mode 100644
index 6694b9897..000000000
--- a/sdk/src/main/kotlin/com/processout/sdk/api/service/RemoteLoggerService.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.processout.sdk.api.service
-
-import com.processout.sdk.api.model.request.LogRequest
-import com.processout.sdk.api.repository.LogsRepository
-import com.processout.sdk.core.logger.BaseLoggerService
-import com.processout.sdk.core.logger.LogEvent
-import com.processout.sdk.core.logger.POLogLevel
-
-internal class RemoteLoggerService(
- minimumLevel: POLogLevel,
- private val repository: LogsRepository
-) : BaseLoggerService(minimumLevel) {
-
- companion object {
- private const val ATTRIBUTE_LINE = "Line"
- }
-
- override fun log(event: LogEvent) {
- repository.send(event.toRequest())
- }
-
- private fun LogEvent.toRequest() = LogRequest(
- level = level.name.lowercase(),
- tag = simpleClassName,
- message = message,
- timestamp = timestamp,
- attributes = mutableMapOf(
- ATTRIBUTE_LINE to lineNumber.toString()
- ).apply { attributes?.let { putAll(it) } }
- )
-}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/service/TelemetryService.kt b/sdk/src/main/kotlin/com/processout/sdk/api/service/TelemetryService.kt
new file mode 100644
index 000000000..368775f47
--- /dev/null
+++ b/sdk/src/main/kotlin/com/processout/sdk/api/service/TelemetryService.kt
@@ -0,0 +1,79 @@
+package com.processout.sdk.api.service
+
+import com.processout.sdk.api.ProcessOutConfiguration.ApplicationInformation
+import com.processout.sdk.api.model.request.DeviceData
+import com.processout.sdk.api.model.request.TelemetryRequest
+import com.processout.sdk.api.model.request.TelemetryRequest.*
+import com.processout.sdk.api.repository.TelemetryRepository
+import com.processout.sdk.core.logger.BaseLoggerService
+import com.processout.sdk.core.logger.LogEvent
+import com.processout.sdk.core.logger.POLogAttribute.CARD_ID
+import com.processout.sdk.core.logger.POLogAttribute.CUSTOMER_ID
+import com.processout.sdk.core.logger.POLogAttribute.CUSTOMER_TOKEN_ID
+import com.processout.sdk.core.logger.POLogAttribute.FILE
+import com.processout.sdk.core.logger.POLogAttribute.GATEWAY_CONFIGURATION_ID
+import com.processout.sdk.core.logger.POLogAttribute.INVOICE_ID
+import com.processout.sdk.core.logger.POLogAttribute.LINE
+import com.processout.sdk.core.logger.POLogLevel
+import com.processout.sdk.di.ContextGraph
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+internal class TelemetryService(
+ minimumLevel: POLogLevel,
+ private val scope: CoroutineScope,
+ private val repository: TelemetryRepository,
+ private val contextGraph: ContextGraph
+) : BaseLoggerService(minimumLevel) {
+
+ override fun log(event: LogEvent) {
+ scope.launch {
+ repository.send(
+ event.toRequest(
+ deviceData = contextGraph.deviceData,
+ appInfo = contextGraph.configuration.applicationInformation
+ )
+ )
+ }
+ }
+
+ private fun LogEvent.toRequest(
+ deviceData: DeviceData,
+ appInfo: ApplicationInformation?,
+ ): TelemetryRequest {
+ val additionalAttributes = mutableMapOf(
+ FILE to simpleClassName,
+ LINE to lineNumber.toString()
+ )
+ val standaloneAttributes = listOf(GATEWAY_CONFIGURATION_ID, CUSTOMER_ID, CUSTOMER_TOKEN_ID, CARD_ID, INVOICE_ID)
+ attributes?.filterKeys { !standaloneAttributes.contains(it) }?.let {
+ additionalAttributes.putAll(it)
+ }
+ return TelemetryRequest(
+ events = listOf(
+ Event(
+ timestamp = timestamp,
+ level = level.name.lowercase(),
+ message = message,
+ gatewayConfigurationId = attributes?.get(GATEWAY_CONFIGURATION_ID),
+ customerId = attributes?.get(CUSTOMER_ID),
+ customerTokenId = attributes?.get(CUSTOMER_TOKEN_ID),
+ cardId = attributes?.get(CARD_ID),
+ invoiceId = attributes?.get(INVOICE_ID),
+ attributes = additionalAttributes
+ )
+ ),
+ metadata = Metadata(
+ application = ApplicationMetadata(
+ name = appInfo?.name,
+ version = appInfo?.version
+ ),
+ device = DeviceMetadata(
+ language = deviceData.appLanguage,
+ model = deviceData.model,
+ timeZone = deviceData.timeZoneOffset
+ )
+ )
+ )
+ }
+}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/core/logger/BaseLoggerService.kt b/sdk/src/main/kotlin/com/processout/sdk/core/logger/BaseLoggerService.kt
index f9428d763..d20264130 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/core/logger/BaseLoggerService.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/core/logger/BaseLoggerService.kt
@@ -20,8 +20,8 @@ internal abstract class BaseLoggerService(
val formattedMessage = if (args.isNotEmpty()) message.format(*args) else message
val stackTraceElement = Throwable().stackTrace.find { element ->
- // Find first element in the stack trace that do not belongs to logger package.
- // This element refers to the class that actually invoked logging.
+ // Find first element in the stack trace that do not belong to logger package.
+ // This element refers to the class that actually invoked the logging.
loggerPackageName?.let {
element.className.startsWith(it).not()
} ?: false
diff --git a/sdk/src/main/kotlin/com/processout/sdk/core/logger/POLogAttribute.kt b/sdk/src/main/kotlin/com/processout/sdk/core/logger/POLogAttribute.kt
new file mode 100644
index 000000000..0b40fdc30
--- /dev/null
+++ b/sdk/src/main/kotlin/com/processout/sdk/core/logger/POLogAttribute.kt
@@ -0,0 +1,19 @@
+package com.processout.sdk.core.logger
+
+import com.processout.sdk.core.annotation.ProcessOutInternalApi
+
+/** @suppress */
+@ProcessOutInternalApi
+object POLogAttribute {
+ // Generic
+ const val FILE = "File"
+ const val LINE = "Line"
+
+ // Specific
+ const val IIN = "IIN"
+ const val CARD_ID = "CardId"
+ const val INVOICE_ID = "InvoiceId"
+ const val CUSTOMER_ID = "CustomerId"
+ const val CUSTOMER_TOKEN_ID = "CustomerTokenId"
+ const val GATEWAY_CONFIGURATION_ID = "GatewayConfigurationId"
+}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/di/ContextGraph.kt b/sdk/src/main/kotlin/com/processout/sdk/di/ContextGraph.kt
index 5e122ea98..7e2e39701 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/di/ContextGraph.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/di/ContextGraph.kt
@@ -35,9 +35,9 @@ internal class DefaultContextGraph(
}
return DeviceData(
appLanguage = configuration.application.currentAppLocale().toLanguageTag(),
- appScreenWidth = screenSize.width,
- appScreenHeight = screenSize.height,
- appTimeZoneOffset = timeZoneOffset
+ screenWidth = screenSize.width,
+ screenHeight = screenSize.height,
+ timeZoneOffset = timeZoneOffset
)
}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/di/NetworkGraph.kt b/sdk/src/main/kotlin/com/processout/sdk/di/NetworkGraph.kt
index 988010254..d4ec40d13 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/di/NetworkGraph.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/di/NetworkGraph.kt
@@ -3,6 +3,7 @@ package com.processout.sdk.di
import com.processout.sdk.api.network.*
import com.processout.sdk.api.network.interceptor.BasicAuthInterceptor
import com.processout.sdk.api.network.interceptor.UserAgentInterceptor
+import com.processout.sdk.api.preferences.Preferences
import com.processout.sdk.core.logger.POLogger
import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter
@@ -19,11 +20,12 @@ internal interface NetworkGraph {
val invoicesApi: InvoicesApi
val cardsApi: CardsApi
val customerTokensApi: CustomerTokensApi
- val logsApi: LogsApi
+ val telemetryApi: TelemetryApi
}
internal class DefaultNetworkGraph(
contextGraph: ContextGraph,
+ preferences: Preferences,
baseUrl: String,
sdkVersion: String
) : NetworkGraph {
@@ -34,7 +36,7 @@ internal class DefaultNetworkGraph(
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(BasicAuthInterceptor(contextGraph))
- .addInterceptor(UserAgentInterceptor(contextGraph, sdkVersion))
+ .addInterceptor(UserAgentInterceptor(contextGraph, preferences, sdkVersion))
.addInterceptor(HttpLoggingInterceptor { message ->
if (contextGraph.configuration.debug) {
POLogger.debug(message)
@@ -73,7 +75,7 @@ internal class DefaultNetworkGraph(
retrofit.create(CustomerTokensApi::class.java)
}
- override val logsApi: LogsApi by lazy {
- retrofit.create(LogsApi::class.java)
+ override val telemetryApi: TelemetryApi by lazy {
+ retrofit.create(TelemetryApi::class.java)
}
}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/di/RepositoryGraph.kt b/sdk/src/main/kotlin/com/processout/sdk/di/RepositoryGraph.kt
index 922e3d3a1..c1c69b9e0 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/di/RepositoryGraph.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/di/RepositoryGraph.kt
@@ -8,7 +8,7 @@ internal interface RepositoryGraph {
val invoicesRepository: InvoicesRepository
val cardsRepository: POCardsRepository
val customerTokensRepository: CustomerTokensRepository
- val logsRepository: LogsRepository
+ val telemetryRepository: TelemetryRepository
}
internal class DefaultRepositoryGraph(
@@ -35,7 +35,7 @@ internal class DefaultRepositoryGraph(
DefaultCustomerTokensRepository(failureMapper, networkGraph.customerTokensApi, contextGraph)
}
- override val logsRepository: LogsRepository by lazy {
- DefaultLogsRepository(failureMapper, networkGraph.logsApi)
+ override val telemetryRepository: TelemetryRepository by lazy {
+ DefaultTelemetryRepository(failureMapper, networkGraph.telemetryApi)
}
}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/di/ServiceGraph.kt b/sdk/src/main/kotlin/com/processout/sdk/di/ServiceGraph.kt
index ff2c4643e..b9bb103a3 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/di/ServiceGraph.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/di/ServiceGraph.kt
@@ -14,7 +14,7 @@ internal interface ServiceGraph {
val alternativePaymentMethodsService: POAlternativePaymentMethodsService
val browserCapabilitiesService: POBrowserCapabilitiesService
val systemLoggerService: POLoggerService
- val remoteLoggerService: POLoggerService
+ val telemetryService: POLoggerService
}
internal class DefaultServiceGraph(
@@ -59,7 +59,12 @@ internal class DefaultServiceGraph(
SystemLoggerService(minimumLevel = POLogLevel.DEBUG)
}
- override val remoteLoggerService: POLoggerService by lazy {
- RemoteLoggerService(minimumLevel = POLogLevel.WARN, repositoryGraph.logsRepository)
+ override val telemetryService: POLoggerService by lazy {
+ TelemetryService(
+ minimumLevel = POLogLevel.WARN,
+ scope = mainCoroutineScope,
+ repository = repositoryGraph.telemetryRepository,
+ contextGraph = contextGraph
+ )
}
}
diff --git a/sdk/src/main/kotlin/com/processout/sdk/ui/nativeapm/NativeAlternativePaymentMethodViewModel.kt b/sdk/src/main/kotlin/com/processout/sdk/ui/nativeapm/NativeAlternativePaymentMethodViewModel.kt
index 898ab8855..cde6eeea9 100644
--- a/sdk/src/main/kotlin/com/processout/sdk/ui/nativeapm/NativeAlternativePaymentMethodViewModel.kt
+++ b/sdk/src/main/kotlin/com/processout/sdk/ui/nativeapm/NativeAlternativePaymentMethodViewModel.kt
@@ -32,6 +32,7 @@ import com.processout.sdk.api.service.POInvoicesService
import com.processout.sdk.core.POFailure
import com.processout.sdk.core.POFailure.Code.*
import com.processout.sdk.core.ProcessOutResult
+import com.processout.sdk.core.logger.POLogAttribute
import com.processout.sdk.core.logger.POLogger
import com.processout.sdk.core.retry.PORetryStrategy
import com.processout.sdk.core.retry.PORetryStrategy.Exponential
@@ -85,8 +86,8 @@ internal class NativeAlternativePaymentMethodViewModel(
),
options = options.validate(),
logAttributes = mapOf(
- LOG_ATTRIBUTE_INVOICE_ID to invoiceId,
- LOG_ATTRIBUTE_GATEWAY_CONFIGURATION_ID to gatewayConfigurationId
+ POLogAttribute.INVOICE_ID to invoiceId,
+ POLogAttribute.GATEWAY_CONFIGURATION_ID to gatewayConfigurationId
)
)
} as T
@@ -98,11 +99,6 @@ internal class NativeAlternativePaymentMethodViewModel(
)
}
- companion object {
- private const val LOG_ATTRIBUTE_INVOICE_ID = "InvoiceId"
- private const val LOG_ATTRIBUTE_GATEWAY_CONFIGURATION_ID = "GatewayConfigurationId"
- }
-
private val _uiState = MutableStateFlow(Loading)
val uiState = _uiState.asStateFlow()
diff --git a/sdk/src/test/kotlin/com/processout/sdk/AlternativePaymentMethodsServiceTests.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/AlternativePaymentMethodsServiceTests.kt
similarity index 95%
rename from sdk/src/test/kotlin/com/processout/sdk/AlternativePaymentMethodsServiceTests.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/AlternativePaymentMethodsServiceTests.kt
index 80e3454f9..e36123b30 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/AlternativePaymentMethodsServiceTests.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/AlternativePaymentMethodsServiceTests.kt
@@ -6,9 +6,9 @@ import com.processout.sdk.api.model.request.POAlternativePaymentMethodRequest
import com.processout.sdk.api.model.response.POAlternativePaymentMethodResponse
import com.processout.sdk.api.network.ApiConstants
import com.processout.sdk.api.service.POAlternativePaymentMethodsService
-import com.processout.sdk.config.SetupRule
-import com.processout.sdk.config.TestApplication
-import com.processout.sdk.config.assertFailure
+import com.processout.sdk.configuration.TestApplication
+import com.processout.sdk.configuration.TestSetupRule
+import com.processout.sdk.configuration.assertFailure
import com.processout.sdk.core.onSuccess
import org.junit.Before
import org.junit.Rule
@@ -23,7 +23,7 @@ class AlternativePaymentMethodsServiceTests {
@Rule
@JvmField
- val setupRule = SetupRule()
+ val setupRule = TestSetupRule()
private lateinit var apmService: POAlternativePaymentMethodsService
diff --git a/sdk/src/test/kotlin/com/processout/sdk/CardsRepositoryTests.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/CardsRepositoryTests.kt
similarity index 93%
rename from sdk/src/test/kotlin/com/processout/sdk/CardsRepositoryTests.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/CardsRepositoryTests.kt
index 3c66e9498..e41ea581e 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/CardsRepositoryTests.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/CardsRepositoryTests.kt
@@ -5,9 +5,9 @@ import com.processout.sdk.api.model.request.POCardTokenizationRequest
import com.processout.sdk.api.model.request.POCardUpdateCVCRequest
import com.processout.sdk.api.model.request.POCardUpdateRequest
import com.processout.sdk.api.repository.POCardsRepository
-import com.processout.sdk.config.SetupRule
-import com.processout.sdk.config.TestApplication
-import com.processout.sdk.config.assertFailure
+import com.processout.sdk.configuration.TestApplication
+import com.processout.sdk.configuration.TestSetupRule
+import com.processout.sdk.configuration.assertFailure
import com.processout.sdk.core.onSuccess
import kotlinx.coroutines.runBlocking
import org.junit.Before
@@ -23,7 +23,7 @@ class CardsRepositoryTests {
@Rule
@JvmField
- val setupRule = SetupRule()
+ val setupRule = TestSetupRule()
private lateinit var cards: POCardsRepository
diff --git a/sdk/src/test/kotlin/com/processout/sdk/CustomerTokensRepositoryTests.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/CustomerTokensRepositoryTests.kt
similarity index 95%
rename from sdk/src/test/kotlin/com/processout/sdk/CustomerTokensRepositoryTests.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/CustomerTokensRepositoryTests.kt
index d89931ba6..ba8de68bb 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/CustomerTokensRepositoryTests.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/CustomerTokensRepositoryTests.kt
@@ -5,9 +5,9 @@ import com.processout.sdk.api.model.request.*
import com.processout.sdk.api.repository.CustomerTokensRepository
import com.processout.sdk.api.repository.InvoicesRepository
import com.processout.sdk.api.repository.POCardsRepository
-import com.processout.sdk.config.SetupRule
-import com.processout.sdk.config.TestApplication
-import com.processout.sdk.config.assertFailure
+import com.processout.sdk.configuration.TestApplication
+import com.processout.sdk.configuration.TestSetupRule
+import com.processout.sdk.configuration.assertFailure
import com.processout.sdk.core.onSuccess
import kotlinx.coroutines.runBlocking
import org.junit.Before
@@ -23,7 +23,7 @@ class CustomerTokensRepositoryTests {
@Rule
@JvmField
- val setupRule = SetupRule()
+ val setupRule = TestSetupRule()
private lateinit var customerTokens: CustomerTokensRepository
private lateinit var invoices: InvoicesRepository
diff --git a/sdk/src/test/kotlin/com/processout/sdk/GatewayConfigurationsRepositoryTests.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/GatewayConfigurationsRepositoryTests.kt
similarity index 83%
rename from sdk/src/test/kotlin/com/processout/sdk/GatewayConfigurationsRepositoryTests.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/GatewayConfigurationsRepositoryTests.kt
index 4ee83a2b5..3754947a8 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/GatewayConfigurationsRepositoryTests.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/GatewayConfigurationsRepositoryTests.kt
@@ -4,10 +4,10 @@ import com.processout.sdk.api.ProcessOut
import com.processout.sdk.api.model.request.POAllGatewayConfigurationsRequest
import com.processout.sdk.api.model.request.POGatewayConfigurationRequest
import com.processout.sdk.api.repository.POGatewayConfigurationsRepository
-import com.processout.sdk.config.PROCESSOUT_GATEWAY_CONFIGURATION_ID
-import com.processout.sdk.config.SetupRule
-import com.processout.sdk.config.TestApplication
-import com.processout.sdk.config.assertFailure
+import com.processout.sdk.configuration.PROCESSOUT_GATEWAY_CONFIGURATION_ID
+import com.processout.sdk.configuration.TestApplication
+import com.processout.sdk.configuration.TestSetupRule
+import com.processout.sdk.configuration.assertFailure
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
@@ -22,7 +22,7 @@ class GatewayConfigurationsRepositoryTests {
@Rule
@JvmField
- val setupRule = SetupRule()
+ val setupRule = TestSetupRule()
private lateinit var gatewayConfigurations: POGatewayConfigurationsRepository
diff --git a/sdk/src/test/kotlin/com/processout/sdk/InvoicesRepositoryTests.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/InvoicesRepositoryTests.kt
similarity index 89%
rename from sdk/src/test/kotlin/com/processout/sdk/InvoicesRepositoryTests.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/InvoicesRepositoryTests.kt
index 9213fcae0..75fc4431c 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/InvoicesRepositoryTests.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/InvoicesRepositoryTests.kt
@@ -1,14 +1,17 @@
package com.processout.sdk
import com.processout.sdk.api.ProcessOut
-import com.processout.sdk.api.model.request.*
+import com.processout.sdk.api.model.request.POCardTokenizationRequest
+import com.processout.sdk.api.model.request.POCreateInvoiceRequest
+import com.processout.sdk.api.model.request.POInvoiceAuthorizationRequest
+import com.processout.sdk.api.model.request.PONativeAlternativePaymentMethodRequest
import com.processout.sdk.api.model.response.CustomerAction
import com.processout.sdk.api.repository.InvoicesRepository
import com.processout.sdk.api.repository.POCardsRepository
-import com.processout.sdk.config.PROCESSOUT_GATEWAY_CONFIGURATION_ID
-import com.processout.sdk.config.SetupRule
-import com.processout.sdk.config.TestApplication
-import com.processout.sdk.config.assertFailure
+import com.processout.sdk.configuration.PROCESSOUT_GATEWAY_CONFIGURATION_ID
+import com.processout.sdk.configuration.TestApplication
+import com.processout.sdk.configuration.TestSetupRule
+import com.processout.sdk.configuration.assertFailure
import com.processout.sdk.core.POFailure
import com.processout.sdk.core.onFailure
import com.processout.sdk.core.onSuccess
@@ -27,7 +30,7 @@ class InvoicesRepositoryTests {
@Rule
@JvmField
- val setupRule = SetupRule()
+ val setupRule = TestSetupRule()
private lateinit var invoices: InvoicesRepository
private lateinit var cards: POCardsRepository
diff --git a/sdk/src/test/kotlin/com/processout/sdk/config/TestApplication.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestApplication.kt
similarity index 63%
rename from sdk/src/test/kotlin/com/processout/sdk/config/TestApplication.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestApplication.kt
index 9f560d4a6..c6ea28755 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/config/TestApplication.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestApplication.kt
@@ -1,4 +1,4 @@
-package com.processout.sdk.config
+package com.processout.sdk.configuration
import android.app.Application
diff --git a/sdk/src/test/kotlin/com/processout/sdk/config/TestConfiguration.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestConfiguration.kt
similarity index 87%
rename from sdk/src/test/kotlin/com/processout/sdk/config/TestConfiguration.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestConfiguration.kt
index 76542a3b1..5220f602b 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/config/TestConfiguration.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestConfiguration.kt
@@ -1,4 +1,6 @@
-package com.processout.sdk.config
+@file:Suppress("RestrictedApi")
+
+package com.processout.sdk.configuration
import com.processout.sdk.BuildConfig
import com.processout.sdk.api.ProcessOut
diff --git a/sdk/src/test/kotlin/com/processout/sdk/config/TestConstants.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestConstants.kt
similarity index 71%
rename from sdk/src/test/kotlin/com/processout/sdk/config/TestConstants.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestConstants.kt
index 837fd3bf1..f41739150 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/config/TestConstants.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestConstants.kt
@@ -1,3 +1,3 @@
-package com.processout.sdk.config
+package com.processout.sdk.configuration
internal const val PROCESSOUT_GATEWAY_CONFIGURATION_ID = "gway_conf_VJEp8Y6ZCqiiwkSa3JioJrwdVM3bVgJd"
diff --git a/sdk/src/test/kotlin/com/processout/sdk/config/TestExtensions.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestExtensions.kt
similarity index 89%
rename from sdk/src/test/kotlin/com/processout/sdk/config/TestExtensions.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestExtensions.kt
index c7d21b5c5..6c03a1f55 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/config/TestExtensions.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestExtensions.kt
@@ -1,4 +1,4 @@
-package com.processout.sdk.config
+package com.processout.sdk.configuration
import com.processout.sdk.core.ProcessOutResult
import com.processout.sdk.core.onFailure
diff --git a/sdk/src/test/kotlin/com/processout/sdk/config/SetupRule.kt b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestSetupRule.kt
similarity index 86%
rename from sdk/src/test/kotlin/com/processout/sdk/config/SetupRule.kt
rename to sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestSetupRule.kt
index cb6d66826..252f95dbb 100644
--- a/sdk/src/test/kotlin/com/processout/sdk/config/SetupRule.kt
+++ b/sdk/src/testProductionDebug/kotlin/com/processout/sdk/configuration/TestSetupRule.kt
@@ -1,11 +1,11 @@
-package com.processout.sdk.config
+package com.processout.sdk.configuration
import androidx.test.core.app.ApplicationProvider
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
-class SetupRule : TestRule {
+class TestSetupRule : TestRule {
override fun apply(base: Statement, description: Description) =
object : Statement() {
diff --git a/ui-core/build.gradle b/ui-core/build.gradle
index 139cd060c..4634128d2 100644
--- a/ui-core/build.gradle
+++ b/ui-core/build.gradle
@@ -1,6 +1,9 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
+ id 'org.jetbrains.kotlin.plugin.compose'
id 'kotlin-parcelize'
}
@@ -47,24 +50,11 @@ android {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = '17'
- freeCompilerArgs += '-opt-in=com.processout.sdk.ui.core.annotation.ProcessOutInternalApi'
- if (project.findProperty("composeCompilerReports") == "true") {
- freeCompilerArgs += [
- "-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
- project.buildDir.absolutePath + "/compose"
- ]
- }
- }
buildFeatures {
buildConfig true
compose true
}
- composeOptions {
- kotlinCompilerExtensionVersion = rootProject.ext.androidxComposeCompilerVersion
- }
publishing {
singleVariant("productionRelease") {
@@ -74,6 +64,17 @@ android {
}
}
+kotlin {
+ compilerOptions {
+ jvmTarget.set(JvmTarget.JVM_17)
+ optIn.add("com.processout.sdk.ui.core.annotation.ProcessOutInternalApi")
+ }
+}
+
+composeCompiler {
+ reportsDestination = layout.buildDirectory.dir("compose")
+}
+
@SuppressWarnings('GrMethodMayBeStatic')
def setBuildConfig(buildType) {
buildType.buildConfigField("String", "LIBRARY_NAME", "\"ProcessOut Android SDK - UI Core\"")
diff --git a/ui/build.gradle b/ui/build.gradle
index 06c58be10..f37cc7709 100644
--- a/ui/build.gradle
+++ b/ui/build.gradle
@@ -1,6 +1,9 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
+ id 'org.jetbrains.kotlin.plugin.compose'
id 'org.jetbrains.dokka'
id 'kotlin-parcelize'
id 'com.google.devtools.ksp'
@@ -49,25 +52,11 @@ android {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = '17'
- freeCompilerArgs += '-opt-in=com.processout.sdk.core.annotation.ProcessOutInternalApi'
- freeCompilerArgs += '-opt-in=com.processout.sdk.ui.core.annotation.ProcessOutInternalApi'
- if (project.findProperty("composeCompilerReports") == "true") {
- freeCompilerArgs += [
- "-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
- project.buildDir.absolutePath + "/compose"
- ]
- }
- }
buildFeatures {
buildConfig true
compose true
}
- composeOptions {
- kotlinCompilerExtensionVersion = rootProject.ext.androidxComposeCompilerVersion
- }
publishing {
singleVariant("productionRelease") {
@@ -79,6 +68,18 @@ android {
}
}
+kotlin {
+ compilerOptions {
+ jvmTarget.set(JvmTarget.JVM_17)
+ optIn.add("com.processout.sdk.core.annotation.ProcessOutInternalApi")
+ optIn.add("com.processout.sdk.ui.core.annotation.ProcessOutInternalApi")
+ }
+}
+
+composeCompiler {
+ reportsDestination = layout.buildDirectory.dir("compose")
+}
+
@SuppressWarnings('GrMethodMayBeStatic')
def setBuildConfig(buildType) {
buildType.buildConfigField("String", "LIBRARY_NAME", "\"ProcessOut Android SDK - UI\"")
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/CardTokenizationInteractor.kt b/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/CardTokenizationInteractor.kt
index e5e4cee27..f297be1cf 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/CardTokenizationInteractor.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/CardTokenizationInteractor.kt
@@ -19,6 +19,7 @@ import com.processout.sdk.core.POFailure.Code.Generic
import com.processout.sdk.core.POFailure.GenericCode.*
import com.processout.sdk.core.ProcessOutResult
import com.processout.sdk.core.getOrNull
+import com.processout.sdk.core.logger.POLogAttribute
import com.processout.sdk.core.logger.POLogger
import com.processout.sdk.core.onFailure
import com.processout.sdk.core.onSuccess
@@ -53,8 +54,6 @@ internal class CardTokenizationInteractor(
private companion object {
const val IIN_LENGTH = 6
const val EXPIRATION_DATE_PART_LENGTH = 2
- const val LOG_ATTRIBUTE_IIN = "IIN"
- const val LOG_ATTRIBUTE_CARD_ID = "CardId"
}
private data class Expiration(
@@ -260,7 +259,7 @@ internal class CardTokenizationInteractor(
.onFailure {
POLogger.info(
message = "Failed to fetch issuer information: %s", it,
- attributes = mapOf(LOG_ATTRIBUTE_IIN to iin)
+ attributes = mapOf(POLogAttribute.IIN to iin)
)
}.getOrNull()
@@ -533,7 +532,7 @@ internal class CardTokenizationInteractor(
_state.update { it.copy(tokenizedCard = card) }
POLogger.info(
message = "Card tokenized successfully.",
- attributes = mapOf(LOG_ATTRIBUTE_CARD_ID to card.id)
+ attributes = mapOf(POLogAttribute.CARD_ID to card.id)
)
dispatch(DidTokenize(card))
if (eventDispatcher.subscribedForProcessTokenizedCard()) {
@@ -541,7 +540,7 @@ internal class CardTokenizationInteractor(
} else {
POLogger.info(
message = "Completed successfully.",
- attributes = mapOf(LOG_ATTRIBUTE_CARD_ID to card.id)
+ attributes = mapOf(POLogAttribute.CARD_ID to card.id)
)
_completion.update { Success(card) }
}
@@ -561,7 +560,7 @@ internal class CardTokenizationInteractor(
eventDispatcher.processTokenizedCard(card)
POLogger.info(
message = "Requested to process tokenized card.",
- attributes = mapOf(LOG_ATTRIBUTE_CARD_ID to card.id)
+ attributes = mapOf(POLogAttribute.CARD_ID to card.id)
)
}
}
@@ -573,7 +572,7 @@ internal class CardTokenizationInteractor(
_state.value.tokenizedCard?.let { card ->
POLogger.info(
message = "Completed successfully.",
- attributes = mapOf(LOG_ATTRIBUTE_CARD_ID to card.id)
+ attributes = mapOf(POLogAttribute.CARD_ID to card.id)
)
_completion.update { Success(card) }
}.orElse {
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/card/update/CardUpdateViewModel.kt b/ui/src/main/kotlin/com/processout/sdk/ui/card/update/CardUpdateViewModel.kt
index c0ac277ba..3967a46e9 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/card/update/CardUpdateViewModel.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/card/update/CardUpdateViewModel.kt
@@ -21,6 +21,7 @@ import com.processout.sdk.core.POFailure.Code.Cancelled
import com.processout.sdk.core.POFailure.Code.Generic
import com.processout.sdk.core.POFailure.GenericCode.*
import com.processout.sdk.core.ProcessOutResult
+import com.processout.sdk.core.logger.POLogAttribute
import com.processout.sdk.core.logger.POLogger
import com.processout.sdk.core.onFailure
import com.processout.sdk.core.onSuccess
@@ -59,14 +60,10 @@ internal class CardUpdateViewModel(
options = options,
cardsRepository = ProcessOut.instance.cards,
eventDispatcher = PODefaultCardUpdateEventDispatcher,
- logAttributes = mapOf(LOG_ATTRIBUTE_CARD_ID to cardId)
+ logAttributes = mapOf(POLogAttribute.CARD_ID to cardId)
) as T
}
- private companion object {
- const val LOG_ATTRIBUTE_CARD_ID = "CardId"
- }
-
private object CardFieldId {
const val NUMBER = "card-number"
const val CVC = "card-cvc"
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/napm/NativeAlternativePaymentInteractor.kt b/ui/src/main/kotlin/com/processout/sdk/ui/napm/NativeAlternativePaymentInteractor.kt
index 03e6bef95..b547cbcd0 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/napm/NativeAlternativePaymentInteractor.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/napm/NativeAlternativePaymentInteractor.kt
@@ -61,8 +61,6 @@ internal class NativeAlternativePaymentInteractor(
companion object {
const val SUCCESS_DELAY_MS = 3000L
- const val LOG_ATTRIBUTE_INVOICE_ID = "InvoiceId"
- const val LOG_ATTRIBUTE_GATEWAY_CONFIGURATION_ID = "GatewayConfigurationId"
}
private val _completion = MutableStateFlow(Awaiting)
diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/napm/NativeAlternativePaymentViewModel.kt b/ui/src/main/kotlin/com/processout/sdk/ui/napm/NativeAlternativePaymentViewModel.kt
index 9565c3058..91ccab6c5 100644
--- a/ui/src/main/kotlin/com/processout/sdk/ui/napm/NativeAlternativePaymentViewModel.kt
+++ b/ui/src/main/kotlin/com/processout/sdk/ui/napm/NativeAlternativePaymentViewModel.kt
@@ -15,12 +15,11 @@ import com.processout.sdk.api.dispatcher.napm.PODefaultNativeAlternativePaymentM
import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodParameter.ParameterType
import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodParameter.ParameterType.*
import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodTransactionDetails.Invoice
+import com.processout.sdk.core.logger.POLogAttribute
import com.processout.sdk.core.retry.PORetryStrategy.Exponential
import com.processout.sdk.ui.core.state.POActionState
import com.processout.sdk.ui.core.state.POActionState.Confirmation
import com.processout.sdk.ui.core.state.POImmutableList
-import com.processout.sdk.ui.napm.NativeAlternativePaymentInteractor.Companion.LOG_ATTRIBUTE_GATEWAY_CONFIGURATION_ID
-import com.processout.sdk.ui.napm.NativeAlternativePaymentInteractor.Companion.LOG_ATTRIBUTE_INVOICE_ID
import com.processout.sdk.ui.napm.NativeAlternativePaymentInteractorState.*
import com.processout.sdk.ui.napm.NativeAlternativePaymentViewModelState.Field.*
import com.processout.sdk.ui.napm.PONativeAlternativePaymentConfiguration.Options
@@ -67,8 +66,8 @@ internal class NativeAlternativePaymentViewModel(
),
eventDispatcher = PODefaultNativeAlternativePaymentMethodEventDispatcher,
logAttributes = mapOf(
- LOG_ATTRIBUTE_INVOICE_ID to invoiceId,
- LOG_ATTRIBUTE_GATEWAY_CONFIGURATION_ID to gatewayConfigurationId
+ POLogAttribute.INVOICE_ID to invoiceId,
+ POLogAttribute.GATEWAY_CONFIGURATION_ID to gatewayConfigurationId
)
)
) as T