Skip to content

Commit

Permalink
Track error event when /payments call failed
Browse files Browse the repository at this point in the history
COAND-1007
  • Loading branch information
araratthehero committed Jan 3, 2025
1 parent b9a47e1 commit e91f5fe
Show file tree
Hide file tree
Showing 30 changed files with 85 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

return SessionComponentEventHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<BacsDirectDebitComponentState>(
sessionInteractor = sessionInteractor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionComponentEventHandler = SessionComponentEventHandler<BcmcComponentState>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionComponentEventHandler = SessionComponentEventHandler<BlikComponentState>(
Expand Down Expand Up @@ -425,6 +426,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionComponentEventHandler =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionComponentEventHandler =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<CardComponentState>(
sessionInteractor = sessionInteractor,
Expand Down Expand Up @@ -504,6 +505,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<CardComponentState>(
sessionInteractor = sessionInteractor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

return SessionComponentEventHandler(
Expand Down
2 changes: 1 addition & 1 deletion drop-in/api/drop-in.api
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ public final class com/adyen/checkout/dropin/SessionDropInResultContract : andro

public class com/adyen/checkout/dropin/SessionDropInService : com/adyen/checkout/dropin/internal/service/BaseDropInService, com/adyen/checkout/dropin/SessionDropInServiceContract, com/adyen/checkout/dropin/internal/service/SessionDropInServiceInterface {
public fun <init> ()V
public final fun initialize (Lcom/adyen/checkout/sessions/core/SessionModel;Ljava/lang/String;Lcom/adyen/checkout/core/Environment;Z)V
public final fun initialize (Lcom/adyen/checkout/sessions/core/SessionModel;Ljava/lang/String;Lcom/adyen/checkout/core/Environment;ZLcom/adyen/checkout/components/core/internal/analytics/AnalyticsManager;)V
public final fun isFlowTakenOver ()Z
public fun onAdditionalDetails (Lcom/adyen/checkout/components/core/ActionComponentData;)Z
public fun onBalanceCheck (Lcom/adyen/checkout/components/core/PaymentComponentState;)Z
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.adyen.checkout.components.core.OrderRequest
import com.adyen.checkout.components.core.OrderResponse
import com.adyen.checkout.components.core.PaymentComponentState
import com.adyen.checkout.components.core.StoredPaymentMethod
import com.adyen.checkout.components.core.internal.analytics.AnalyticsManager
import com.adyen.checkout.core.AdyenLogLevel
import com.adyen.checkout.core.Environment
import com.adyen.checkout.core.internal.data.api.HttpClientFactory
Expand Down Expand Up @@ -50,7 +51,8 @@ open class SessionDropInService : BaseDropInService(), SessionDropInServiceInter
sessionModel: SessionModel,
clientKey: String,
environment: Environment,
isFlowTakenOver: Boolean
isFlowTakenOver: Boolean,
analyticsManager: AnalyticsManager,
) {
val httpClient = HttpClientFactory.getHttpClient(environment)
val sessionService = SessionService(httpClient)
Expand All @@ -61,6 +63,7 @@ open class SessionDropInService : BaseDropInService(), SessionDropInServiceInter
),
sessionModel = sessionModel,
isFlowTakenOver = isFlowTakenOver,
analyticsManager = analyticsManager,
)
this.isFlowTakenOver = isFlowTakenOver

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.adyen.checkout.components.core.LookupAddress
import com.adyen.checkout.components.core.OrderRequest
import com.adyen.checkout.components.core.PaymentComponentState
import com.adyen.checkout.components.core.StoredPaymentMethod
import com.adyen.checkout.components.core.internal.analytics.AnalyticsManager
import com.adyen.checkout.core.Environment
import com.adyen.checkout.dropin.BaseDropInServiceResult
import com.adyen.checkout.sessions.core.SessionModel
Expand All @@ -39,6 +40,7 @@ internal interface SessionDropInServiceInterface : BaseDropInServiceInterface {
sessionModel: SessionModel,
clientKey: String,
environment: Environment,
isFlowTakenOver: Boolean
isFlowTakenOver: Boolean,
analyticsManager: AnalyticsManager,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ internal class DropInActivity :
clientKey = event.clientKey,
environment = event.environment,
isFlowTakenOver = event.isFlowTakenOver,
analyticsManager = event.analyticsManager,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ internal class DropInViewModel(
clientKey = dropInParams.clientKey,
environment = dropInParams.environment,
isFlowTakenOver = isSessionsFlowTakenOver,
analyticsManager = analyticsManager,
)
sendEvent(event)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package com.adyen.checkout.dropin.internal.ui.model
import com.adyen.checkout.components.core.OrderRequest
import com.adyen.checkout.components.core.PaymentComponentState
import com.adyen.checkout.components.core.PaymentMethod
import com.adyen.checkout.components.core.internal.analytics.AnalyticsManager
import com.adyen.checkout.core.Environment
import com.adyen.checkout.sessions.core.SessionModel

Expand All @@ -25,6 +26,7 @@ internal sealed class DropInActivityEvent {
val clientKey: String,
val environment: Environment,
val isFlowTakenOver: Boolean,
val analyticsManager: AnalyticsManager,
) : DropInActivityEvent()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<ComponentStateT>(
sessionInteractor = sessionInteractor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionsGiftCardComponentEventHandler = SessionsGiftCardComponentEventHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionComponentEventHandler = SessionComponentEventHandler<GooglePayComponentState>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<IdealComponentState>(
sessionInteractor = sessionInteractor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<InstantComponentState>(
sessionInteractor = sessionInteractor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<ComponentStateT>(
sessionInteractor = sessionInteractor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionComponentEventHandler = SessionComponentEventHandler<MBWayComponentState>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionsGiftCardComponentEventHandler = SessionsGiftCardComponentEventHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<ComponentStateT>(
sessionInteractor = sessionInteractor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<PayByBankUSComponentState>(
sessionInteractor = sessionInteractor,
Expand Down Expand Up @@ -425,6 +426,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

val sessionComponentEventHandler =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<PayByBankComponentState>(
sessionInteractor = sessionInteractor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)
val sessionComponentEventHandler = SessionComponentEventHandler<SepaComponentState>(
sessionInteractor = sessionInteractor,
Expand Down
1 change: 1 addition & 0 deletions sessions-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {

//Tests
testImplementation testFixtures(project(':test-core'))
testImplementation testFixtures(project(':components-core'))
testImplementation libs.androidx.test.lifecycle
testImplementation libs.bundles.junit
testImplementation libs.bundles.kotlin.coroutines.test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import com.adyen.checkout.components.core.BalanceResult
import com.adyen.checkout.components.core.OrderRequest
import com.adyen.checkout.components.core.OrderResponse
import com.adyen.checkout.components.core.PaymentComponentState
import com.adyen.checkout.components.core.internal.analytics.AnalyticsManager
import com.adyen.checkout.components.core.internal.analytics.ErrorEvent
import com.adyen.checkout.components.core.internal.analytics.GenericEvents
import com.adyen.checkout.components.core.internal.util.StatusResponseUtils
import com.adyen.checkout.core.exception.CheckoutException
import com.adyen.checkout.core.exception.MethodNotImplementedException
Expand All @@ -33,6 +36,7 @@ class SessionInteractor(
private val sessionRepository: SessionRepository,
sessionModel: SessionModel,
isFlowTakenOver: Boolean,
private val analyticsManager: AnalyticsManager?,
) {

@VisibleForTesting
Expand Down Expand Up @@ -76,6 +80,14 @@ class SessionInteractor(
}
},
onFailure = {
paymentComponentState.data.paymentMethod?.type?.let { paymentMethodType ->
val event = GenericEvents.error(
component = paymentMethodType,
event = ErrorEvent.API_PAYMENTS,
)
analyticsManager?.trackEvent(event)
}

return SessionCallResult.Payments.Error(throwable = it)
},
)
Expand Down Expand Up @@ -260,7 +272,8 @@ class SessionInteractor(
return if (!callWasHandled) {
if (isFlowTakenOver) {
throw MethodNotImplementedException(
"Sessions flow was already taken over in a previous call, $merchantMethodName should be implemented"
"Sessions flow was already taken over in a previous call, " +
"$merchantMethodName should be implemented",
)
} else {
internalCall()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import com.adyen.checkout.components.core.PaymentComponentData
import com.adyen.checkout.components.core.PaymentMethodsApiResponse
import com.adyen.checkout.components.core.action.Action
import com.adyen.checkout.components.core.action.RedirectAction
import com.adyen.checkout.components.core.internal.analytics.ErrorEvent
import com.adyen.checkout.components.core.internal.analytics.GenericEvents
import com.adyen.checkout.components.core.internal.analytics.TestAnalyticsManager
import com.adyen.checkout.components.core.internal.util.StatusResponseUtils
import com.adyen.checkout.core.exception.CheckoutException
import com.adyen.checkout.sessions.core.SessionModel
Expand All @@ -35,7 +38,6 @@ import com.adyen.checkout.sessions.core.internal.data.model.SessionOrderResponse
import com.adyen.checkout.sessions.core.internal.data.model.SessionPaymentsResponse
import com.adyen.checkout.test.LoggingExtension
import com.adyen.checkout.test.TestDispatcherExtension
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
Expand All @@ -51,16 +53,17 @@ import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.whenever

@OptIn(ExperimentalCoroutinesApi::class)
@ExtendWith(MockitoExtension::class, TestDispatcherExtension::class, LoggingExtension::class)
internal class SessionInteractorTest(
@Mock private val sessionRepository: SessionRepository,
) {

private lateinit var sessionInteractor: SessionInteractor
private lateinit var analyticsManager: TestAnalyticsManager

@BeforeEach
fun before() {
analyticsManager = TestAnalyticsManager()
sessionInteractor = createSessionInteractor()
}

Expand Down Expand Up @@ -715,6 +718,34 @@ internal class SessionInteractorTest(
}
}

@Nested
inner class AnalyticsTest {

@Test
fun `when payment calls returns an error then error event is tracked`() = runTest {
val exception = Exception("failed for testing")
val paymentMethodType = "scheme"
val componentState = TestComponentState(
data = PaymentComponentData(
TestPaymentMethod(type = paymentMethodType),
TEST_ORDER_REQUEST,
TEST_AMOUNT,
),
isInputValid = true,
isReady = true,
)
whenever(sessionRepository.submitPayment(any(), any())) doReturn Result.failure(exception)

sessionInteractor.onPaymentsCallRequested(componentState, { false }, "")

val expectedEvent = GenericEvents.error(
component = paymentMethodType,
event = ErrorEvent.API_PAYMENTS,
)
analyticsManager.assertLastEventEquals(expectedEvent)
}
}

private fun createSessionInteractor(
sessionModel: SessionModel = TEST_SESSION_MODEL,
isFlowTakenOver: Boolean = false
Expand All @@ -723,6 +754,7 @@ internal class SessionInteractorTest(
sessionRepository = sessionRepository,
sessionModel = sessionModel,
isFlowTakenOver = isFlowTakenOver,
analyticsManager = analyticsManager,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ constructor(
),
sessionModel = sessionSavedStateHandleContainer.getSessionModel(),
isFlowTakenOver = sessionSavedStateHandleContainer.isFlowTakenOver ?: false,
analyticsManager = analyticsManager,
)

return SessionComponentEventHandler(
Expand Down
Loading

0 comments on commit e91f5fe

Please sign in to comment.