From 9c5ed956c5e1c8b2595466ac3fd78de658502b37 Mon Sep 17 00:00:00 2001 From: Anmol Agrawal Date: Thu, 15 May 2025 12:49:39 +0530 Subject: [PATCH] NTP-63992 | Anmol A | Fraud Risk Experience (#16168) Co-authored-by: vedant aggarwal Co-authored-by: Aditya Narayan Malik Co-authored-by: Sidharth Bamba Co-authored-by: Shaurya Rehan --- .../nativepayment/NaviPaymentAnalytics.kt | 42 +++++++++++++++++++ .../components/bsheets/NPSErrorBottomSheet.kt | 1 - .../reducer/CardDetailScreenContract.kt | 2 + .../reducer/NetBankingScreenContract.kt | 2 + .../screens/CardDetailsScreen.kt | 3 ++ .../nativepayment/screens/NetBankingScreen.kt | 3 ++ .../payment/nativepayment/utils/ErrorUtils.kt | 7 +++- .../utils/NaviPaymentErrorConfig.kt | 2 + .../viewmodel/CardDetailViewModel.kt | 27 +++++++++++- .../viewmodel/NetBankingViewModel.kt | 23 ++++++++++ .../java/com/navi/payment/utils/Constants.kt | 3 ++ 11 files changed, 111 insertions(+), 4 deletions(-) diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/NaviPaymentAnalytics.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/NaviPaymentAnalytics.kt index 71d7ad7a32..3a5bfee7fc 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/NaviPaymentAnalytics.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/NaviPaymentAnalytics.kt @@ -639,6 +639,27 @@ class NaviPaymentAnalytics private constructor() { eventName = "NaviPMT_NetBankingScreen_EmptyBanksList" ) } + + fun onFraudOnboardingTriggered(baseAnalyticsParams: MutableMap) { + NaviTrackEvent.trackEventOnClickStream( + eventName = "NaviPMT_NetBankingScreen_FraudOnboardingTriggered", + eventValues = baseAnalyticsParams, + ) + } + + fun onFraudOnboardingCancelled(baseAnalyticsParams: MutableMap) { + NaviTrackEvent.trackEventOnClickStream( + eventName = "NaviPMT_NetBankingScreen_FraudOnboardingCancelled", + eventValues = baseAnalyticsParams, + ) + } + + fun onFraudOnboardingCompleted(baseAnalyticsParams: MutableMap) { + NaviTrackEvent.trackEventOnClickStream( + eventName = "NaviPMT_NetBankingScreen_FraudOnboardingCompleted", + eventValues = baseAnalyticsParams, + ) + } } inner class CardScreen { @@ -745,6 +766,27 @@ class NaviPaymentAnalytics private constructor() { eventName = "NaviPMT_CardScreen_CardDetailsChangedAfterScanning" ) } + + fun onFraudOnboardingTriggered(baseAnalyticsParams: MutableMap) { + NaviTrackEvent.trackEventOnClickStream( + eventName = "NaviPMT_CardScreen_FraudOnboardingTriggered", + eventValues = baseAnalyticsParams, + ) + } + + fun onFraudOnboardingCancelled(baseAnalyticsParams: MutableMap) { + NaviTrackEvent.trackEventOnClickStream( + eventName = "NaviPMT_CardScreen_FraudOnboardingCancelled", + eventValues = baseAnalyticsParams, + ) + } + + fun onFraudOnboardingCompleted(baseAnalyticsParams: MutableMap) { + NaviTrackEvent.trackEventOnClickStream( + eventName = "NaviPMT_CardScreen_FraudOnboardingCompleted", + eventValues = baseAnalyticsParams, + ) + } } inner class SdkIntegrationScreen { diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/components/bsheets/NPSErrorBottomSheet.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/components/bsheets/NPSErrorBottomSheet.kt index 40d0890940..cfa884389d 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/components/bsheets/NPSErrorBottomSheet.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/components/bsheets/NPSErrorBottomSheet.kt @@ -58,7 +58,6 @@ fun NPSErrorBottomSheet( } } -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun NPSErrorBottomSheetContent( naviPaymentErrorConfig: NaviPaymentErrorConfig, diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/presentation/reducer/CardDetailScreenContract.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/presentation/reducer/CardDetailScreenContract.kt index 2f9d0e7cb1..015c4d731d 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/presentation/reducer/CardDetailScreenContract.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/presentation/reducer/CardDetailScreenContract.kt @@ -75,6 +75,8 @@ sealed interface CardDetailScreenEvent { data class OnPaymentInstrumentHeadingVisibilityChanged(val isHeadingVisible: Boolean = true) : CardDetailScreenEvent + + data object StartOnboarding : CardDetailScreenEvent } sealed interface CardDetailScreenEffect { diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/presentation/reducer/NetBankingScreenContract.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/presentation/reducer/NetBankingScreenContract.kt index 25c8d433e1..3fbbbcb592 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/presentation/reducer/NetBankingScreenContract.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/presentation/reducer/NetBankingScreenContract.kt @@ -45,6 +45,8 @@ sealed interface NetBankingScreenEvent : UiEvent { data object OnFeedBackSubmit : NetBankingScreenEvent data class OnBackPress(val isKeyboardVisible: Boolean) : NetBankingScreenEvent + + data object StartOnboarding : NetBankingScreenEvent } sealed interface NetBankingScreenEffect : UiEvent { diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/screens/CardDetailsScreen.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/screens/CardDetailsScreen.kt index 175874e860..fe704270af 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/screens/CardDetailsScreen.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/screens/CardDetailsScreen.kt @@ -748,6 +748,9 @@ private fun ObserveBottomSheetEvents( is NaviPaymentBottomSheetButtonAction.Dismiss -> { onEvent(CardDetailScreenEvent.OnBottomSheetDismiss) } + is NaviPaymentBottomSheetButtonAction.StartOnboarding -> { + onEvent(CardDetailScreenEvent.StartOnboarding) + } else -> {} } } diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/screens/NetBankingScreen.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/screens/NetBankingScreen.kt index e111755545..2aef502762 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/screens/NetBankingScreen.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/screens/NetBankingScreen.kt @@ -328,6 +328,9 @@ private fun ObserveBottomSheetEvents( is NaviPaymentBottomSheetButtonAction.SubmitFeedBack -> { onEvent(NetBankingScreenEvent.OnFeedBackSubmit) } + is NaviPaymentBottomSheetButtonAction.StartOnboarding -> { + onEvent(NetBankingScreenEvent.StartOnboarding) + } else -> {} } } diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/utils/ErrorUtils.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/utils/ErrorUtils.kt index 2d5c58666d..85f961426d 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/utils/ErrorUtils.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/utils/ErrorUtils.kt @@ -21,6 +21,7 @@ import com.navi.pay.common.viewmodel.NaviPayBaseVM.Companion.ERROR_DEFAULT_TAG import com.navi.payment.R import com.navi.payment.nativepayment.viewmodel.NaviPaymentBaseVM.Companion.UNKNOWN_ERROR_CODE import com.navi.payment.paymentscreen.model.FeedbackConfig +import com.navi.payment.utils.Constants.START_ONBOARDING fun RepoResult.toGenericErrorResponse(): GenericErrorResponse { val backendError = this.errors?.first() @@ -67,7 +68,11 @@ fun List.toNaviPaymentErrorButtonConfig(): List NaviPaymentBottomSheetButtonAction.StartOnboarding + else -> NaviPaymentBottomSheetButtonAction.Dismiss + }, ) } } diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/utils/NaviPaymentErrorConfig.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/utils/NaviPaymentErrorConfig.kt index e39016f26c..04e015da44 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/utils/NaviPaymentErrorConfig.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/utils/NaviPaymentErrorConfig.kt @@ -78,6 +78,8 @@ sealed class NaviPaymentBottomSheetButtonAction { data class ReportIssue(val feedbackConfig: FeedbackConfig) : NaviPaymentBottomSheetButtonAction() + + data object StartOnboarding : NaviPaymentBottomSheetButtonAction() } data class NaviPaymentBottomSheetCtaClickEvent( diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/viewmodel/CardDetailViewModel.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/viewmodel/CardDetailViewModel.kt index 9fd62c9443..820d26af31 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/viewmodel/CardDetailViewModel.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/viewmodel/CardDetailViewModel.kt @@ -23,6 +23,8 @@ import com.navi.common.model.RequestConfig import com.navi.common.network.models.RepoResult import com.navi.common.network.models.isSuccessWithData import com.navi.naviwidgets.models.FooterButtonState +import com.navi.pay.management.common.utils.NaviPayPspManager +import com.navi.pay.utils.ALL_ENABLED_ACCOUNTS import com.navi.payment.R import com.navi.payment.juspay.JusPayCardConstants.ARG_ACTION import com.navi.payment.juspay.JusPayCardConstants.ARG_CARD_BIN @@ -134,6 +136,7 @@ constructor( private val resourceProvider: ResourceProvider, private val transactionStatusUseCase: TransactionStatusUseCase, private val savedStateHandle: SavedStateHandle, + private val naviPayPspManager: NaviPayPspManager, ) : NaviPaymentBaseVM(screenName = NaviPaymentAnalyticScreenName.CARD_SCREEN.screenName), CardDetailScreenContract { @@ -346,9 +349,9 @@ constructor( is CardDetailScreenEvent.OnScanCardResult -> handleOnScanCardResult(event.scanResult) is CardDetailScreenEvent.OnScanCardClick -> handleOnScanCardClick(event.isKeyboardVisible) - is CardDetailScreenEvent.OnPaymentInstrumentHeadingVisibilityChanged -> toggleTopBarHeadingVisibility() + is CardDetailScreenEvent.StartOnboarding -> handleStartOnboarding() } } @@ -482,7 +485,7 @@ constructor( } is JuspaySdkResult.Invalid -> {} } - _state.update { it.copy(footerButtonState = FooterButtonState.ENABLED) } + stopFooterLoading() } private fun handlePayNowClicked() { @@ -550,6 +553,7 @@ constructor( } } else { isInteractionAllowed.set(true) + stopFooterLoading() handleError(response = response, errorReason = PMSErrorReason.PayNowError) } } @@ -1097,6 +1101,25 @@ constructor( ) } } + + private fun handleStartOnboarding() { + viewModelScope.safeLaunch(Dispatchers.IO) { + naviPayPspManager.handleAccountAdditionFlow( + screenName = screenName, + enabledAccountTypes = ALL_ENABLED_ACCOUNTS, + onOnboardingTriggered = { + naviPaymentAnalytics.onFraudOnboardingTriggered(baseAnalyticsParams) + }, + onPspEvaluated = { pspEvaluationResult -> + if (pspEvaluationResult.onboardingDataEntity == null) { + naviPaymentAnalytics.onFraudOnboardingCancelled(baseAnalyticsParams) + } else { + naviPaymentAnalytics.onFraudOnboardingCompleted(baseAnalyticsParams) + } + }, + ) + } + } } enum class ValidationKeys(val key: String) { diff --git a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/viewmodel/NetBankingViewModel.kt b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/viewmodel/NetBankingViewModel.kt index 2fb46d553a..a7c9d854fc 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/nativepayment/viewmodel/NetBankingViewModel.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/nativepayment/viewmodel/NetBankingViewModel.kt @@ -18,6 +18,8 @@ import com.navi.base.utils.orZero import com.navi.common.network.models.RepoResult import com.navi.common.network.models.isSuccessWithData import com.navi.common.utils.Constants.DEFAULT +import com.navi.pay.management.common.utils.NaviPayPspManager +import com.navi.pay.utils.ALL_ENABLED_ACCOUNTS import com.navi.payment.juspay.JusPayUtil import com.navi.payment.juspay.JuspaySdkResult import com.navi.payment.model.common.SignalPaymentData @@ -69,6 +71,7 @@ constructor( private val paymentRepository: PaymentRepository, private val netBankingUseCase: NetBankingUseCase, private val transactionStatusUseCase: TransactionStatusUseCase, + private val naviPayPspManager: NaviPayPspManager, @PaymentsSdkRetrofit private val deserializer: Gson, ) : NaviPaymentBaseVM(screenName = NaviPaymentAnalyticScreenName.NET_BANKING_SCREEN.screenName), @@ -218,6 +221,7 @@ constructor( viewModelScope.safeLaunch(Dispatchers.IO) { handleFeedbackSubmit() } } is NetBankingScreenEvent.OnBackPress -> handleOnBackPress(event) + is NetBankingScreenEvent.StartOnboarding -> handleStartOnboarding() } } @@ -377,4 +381,23 @@ constructor( ) } } + + private fun handleStartOnboarding() { + viewModelScope.safeLaunch(Dispatchers.IO) { + naviPayPspManager.handleAccountAdditionFlow( + screenName = screenName, + enabledAccountTypes = ALL_ENABLED_ACCOUNTS, + onOnboardingTriggered = { + netBankingAnalytics.onFraudOnboardingTriggered(baseAnalyticsParams) + }, + onPspEvaluated = { pspEvaluationResult -> + if (pspEvaluationResult.onboardingDataEntity == null) { + netBankingAnalytics.onFraudOnboardingCancelled(baseAnalyticsParams) + } else { + netBankingAnalytics.onFraudOnboardingCompleted(baseAnalyticsParams) + } + }, + ) + } + } } diff --git a/android/navi-payment/src/main/java/com/navi/payment/utils/Constants.kt b/android/navi-payment/src/main/java/com/navi/payment/utils/Constants.kt index a2f9f3ccda..f08eabe419 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/utils/Constants.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/utils/Constants.kt @@ -192,6 +192,9 @@ object Constants { const val PSP_MANAGER_RESPONSE = "PSP_MANAGER_RESPONSE" + // bottomsheet actions + const val START_ONBOARDING = "START_ONBOARDING" + enum class OneClickCheckoutExperiment(val experimentName: String) { OTHER_METHODS_CTA("other_methods_cta"), CHEVRON_UP("chevron_up"),