NTP-63992 | Anmol A | Fraud Risk Experience (#16168)

Co-authored-by: vedant aggarwal <vedant.aggarwal@navi.com>
Co-authored-by: Aditya Narayan Malik <aditya.narayan@navi.com>
Co-authored-by: Sidharth Bamba <sidharth.bamba@navi.com>
Co-authored-by: Shaurya Rehan <shaurya.rehan@navi.com>
This commit is contained in:
Anmol Agrawal
2025-05-15 12:49:39 +05:30
committed by GitHub
parent feac0b54b5
commit 9c5ed956c5
11 changed files with 111 additions and 4 deletions

View File

@@ -639,6 +639,27 @@ class NaviPaymentAnalytics private constructor() {
eventName = "NaviPMT_NetBankingScreen_EmptyBanksList"
)
}
fun onFraudOnboardingTriggered(baseAnalyticsParams: MutableMap<String, String>) {
NaviTrackEvent.trackEventOnClickStream(
eventName = "NaviPMT_NetBankingScreen_FraudOnboardingTriggered",
eventValues = baseAnalyticsParams,
)
}
fun onFraudOnboardingCancelled(baseAnalyticsParams: MutableMap<String, String>) {
NaviTrackEvent.trackEventOnClickStream(
eventName = "NaviPMT_NetBankingScreen_FraudOnboardingCancelled",
eventValues = baseAnalyticsParams,
)
}
fun onFraudOnboardingCompleted(baseAnalyticsParams: MutableMap<String, String>) {
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<String, String>) {
NaviTrackEvent.trackEventOnClickStream(
eventName = "NaviPMT_CardScreen_FraudOnboardingTriggered",
eventValues = baseAnalyticsParams,
)
}
fun onFraudOnboardingCancelled(baseAnalyticsParams: MutableMap<String, String>) {
NaviTrackEvent.trackEventOnClickStream(
eventName = "NaviPMT_CardScreen_FraudOnboardingCancelled",
eventValues = baseAnalyticsParams,
)
}
fun onFraudOnboardingCompleted(baseAnalyticsParams: MutableMap<String, String>) {
NaviTrackEvent.trackEventOnClickStream(
eventName = "NaviPMT_CardScreen_FraudOnboardingCompleted",
eventValues = baseAnalyticsParams,
)
}
}
inner class SdkIntegrationScreen {

View File

@@ -58,7 +58,6 @@ fun NPSErrorBottomSheet(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun NPSErrorBottomSheetContent(
naviPaymentErrorConfig: NaviPaymentErrorConfig,

View File

@@ -75,6 +75,8 @@ sealed interface CardDetailScreenEvent {
data class OnPaymentInstrumentHeadingVisibilityChanged(val isHeadingVisible: Boolean = true) :
CardDetailScreenEvent
data object StartOnboarding : CardDetailScreenEvent
}
sealed interface CardDetailScreenEffect {

View File

@@ -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 {

View File

@@ -748,6 +748,9 @@ private fun ObserveBottomSheetEvents(
is NaviPaymentBottomSheetButtonAction.Dismiss -> {
onEvent(CardDetailScreenEvent.OnBottomSheetDismiss)
}
is NaviPaymentBottomSheetButtonAction.StartOnboarding -> {
onEvent(CardDetailScreenEvent.StartOnboarding)
}
else -> {}
}
}

View File

@@ -328,6 +328,9 @@ private fun ObserveBottomSheetEvents(
is NaviPaymentBottomSheetButtonAction.SubmitFeedBack -> {
onEvent(NetBankingScreenEvent.OnFeedBackSubmit)
}
is NaviPaymentBottomSheetButtonAction.StartOnboarding -> {
onEvent(NetBankingScreenEvent.StartOnboarding)
}
else -> {}
}
}

View File

@@ -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 <T> RepoResult<T>.toGenericErrorResponse(): GenericErrorResponse {
val backendError = this.errors?.first()
@@ -67,7 +68,11 @@ fun List<Action>.toNaviPaymentErrorButtonConfig(): List<NaviPaymentErrorButtonCo
type =
if (index == 0) NaviPaymentButtonTheme.Primary
else NaviPaymentButtonTheme.Secondary,
action = NaviPaymentBottomSheetButtonAction.Dismiss,
action =
when (action.cta?.url) {
START_ONBOARDING -> NaviPaymentBottomSheetButtonAction.StartOnboarding
else -> NaviPaymentBottomSheetButtonAction.Dismiss
},
)
}
}

View File

@@ -78,6 +78,8 @@ sealed class NaviPaymentBottomSheetButtonAction {
data class ReportIssue(val feedbackConfig: FeedbackConfig) :
NaviPaymentBottomSheetButtonAction()
data object StartOnboarding : NaviPaymentBottomSheetButtonAction()
}
data class NaviPaymentBottomSheetCtaClickEvent(

View File

@@ -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) {

View File

@@ -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)
}
},
)
}
}
}

View File

@@ -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"),