NTP-61439 | Anmol A | Navi Upi Payment Processor (#16068)
This commit is contained in:
@@ -18,6 +18,7 @@ import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_PMT_
|
||||
import com.navi.common.network.models.ErrorMessage
|
||||
import com.navi.common.network.models.GenericErrorResponse
|
||||
import com.navi.pay.common.model.view.CheckBalanceAnalyticsEventData
|
||||
import com.navi.pay.common.model.view.NaviPayErrorConfig
|
||||
import com.navi.pay.management.common.utils.PspEvaluationResult
|
||||
import com.navi.payment.nativepayment.dataprovider.PinAction
|
||||
import com.navi.payment.nativepayment.db.model.TransactionStatusRequestEntity
|
||||
@@ -28,6 +29,7 @@ import com.navi.payment.nativepayment.presentation.reducer.ImageSource
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentErrorConfig
|
||||
import com.navi.payment.nativepayment.viewmodel.ScanCardResult
|
||||
import com.navi.payment.paymentscreen.model.ErrorReason
|
||||
import com.navi.payment.paymentscreen.model.InternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.NaviUpiTransactionInfo
|
||||
import com.navi.payment.utils.putIfNotNullAndNotEmpty
|
||||
import com.navi.payment.utils.usecases.CardValidator
|
||||
@@ -1916,7 +1918,7 @@ class NaviPaymentAnalytics private constructor() {
|
||||
}
|
||||
}
|
||||
|
||||
inner class PspManager() {
|
||||
inner class PspManager {
|
||||
// PSP Manager Events
|
||||
fun onAccountAdditionWithPspManager(enabledAccountTypes: String, screenName: String) {
|
||||
val eventAttributes = buildMap { put("enabledAccountTypes", enabledAccountTypes) }
|
||||
@@ -1973,12 +1975,6 @@ class NaviPaymentAnalytics private constructor() {
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onNaviPayOnboardingEntityNotInitialised(screenName: String) {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_NaviPayOnboardingEntityNotInitialised"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
inner class WebPaymentScreen {
|
||||
@@ -2460,6 +2456,139 @@ class NaviPaymentAnalytics private constructor() {
|
||||
}
|
||||
}
|
||||
|
||||
inner class NaviUpiPaymentProcessor {
|
||||
fun onUpiLitePayment(
|
||||
screenName: String,
|
||||
isDiscountApplied: String,
|
||||
baseAttributes: Map<String, String>,
|
||||
) {
|
||||
val eventAttributes = buildMap {
|
||||
put("is_discount_applied", isDiscountApplied)
|
||||
putAll(baseAttributes)
|
||||
}
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_UpiLitePayment",
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onNonUpiLitePayment(
|
||||
screenName: String,
|
||||
isDiscountApplied: String,
|
||||
baseAttributes: Map<String, String>,
|
||||
accountId: String,
|
||||
) {
|
||||
val eventAttributes = buildMap {
|
||||
put("is_discount_applied", isDiscountApplied)
|
||||
put("account_id", accountId)
|
||||
putAll(baseAttributes)
|
||||
}
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_NonUpiLitePayment",
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onPinPageOpened(
|
||||
screenName: String,
|
||||
naviPayUpiUriKey: String,
|
||||
transactionReferenceId: String,
|
||||
baseAttributes: Map<String, String>,
|
||||
) {
|
||||
val eventAttributes = buildMap {
|
||||
put("navi_pay_upi_uri_key", naviPayUpiUriKey)
|
||||
put("transaction_reference_id", transactionReferenceId)
|
||||
putAll(baseAttributes)
|
||||
}
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_PinPageOpened",
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onPinPageCancelled(
|
||||
screenName: String,
|
||||
naviPayUpiUriKey: String,
|
||||
transactionReferenceId: String,
|
||||
baseAttributes: Map<String, String>,
|
||||
) {
|
||||
val eventAttributes = buildMap {
|
||||
put("navi_pay_upi_uri_key", naviPayUpiUriKey)
|
||||
put("transaction_reference_id", transactionReferenceId)
|
||||
putAll(baseAttributes)
|
||||
}
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_PinPageCancelled",
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onPinPageError(
|
||||
screenName: String,
|
||||
naviPayUpiUriKey: String,
|
||||
transactionReferenceId: String,
|
||||
baseAttributes: Map<String, String>,
|
||||
errorCode: NaviPayErrorConfig,
|
||||
) {
|
||||
val eventAttributes = buildMap {
|
||||
put("navi_pay_upi_uri_key", naviPayUpiUriKey)
|
||||
put("transaction_reference_id", transactionReferenceId)
|
||||
put("navi_pay_error_config", errorCode.toString())
|
||||
putAll(baseAttributes)
|
||||
}
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_PinPageError",
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onPinPageSuccess(
|
||||
screenName: String,
|
||||
naviPayUpiUriKey: String,
|
||||
transactionReferenceId: String,
|
||||
baseAttributes: Map<String, String>,
|
||||
) {
|
||||
val eventAttributes = buildMap {
|
||||
put("navi_pay_upi_uri_key", naviPayUpiUriKey)
|
||||
put("transaction_reference_id", transactionReferenceId)
|
||||
putAll(baseAttributes)
|
||||
}
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_PinPageSuccess",
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onEmptyPaymentToken(screenName: String, baseAttributes: Map<String, String>) {
|
||||
val eventAttributes = buildMap { putAll(baseAttributes) }
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_EmptyPaymentToken",
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onPayNowChecksFailed(
|
||||
screenName: String,
|
||||
transactionReferenceId: String,
|
||||
paymentOrderReferenceId: String,
|
||||
intentUri: String,
|
||||
internalPayNowResponse: InternalPayNowResponse?,
|
||||
genericErrorResponse: GenericErrorResponse,
|
||||
) {
|
||||
val eventAttributes = buildMap {
|
||||
put("intentUri", intentUri)
|
||||
put("transaction_Reference_id", transactionReferenceId)
|
||||
put("payment_Order_ReferenceId", paymentOrderReferenceId)
|
||||
put("internalPayNowResponse", internalPayNowResponse.toString())
|
||||
put("genericErrorResponse", genericErrorResponse.toString())
|
||||
}
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPMT_${screenName}_PayNowChecksFailed",
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addScreenName(
|
||||
baseAttributes: Map<String, String>,
|
||||
screenName: String,
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.navi.pay.onboarding.binding.model.view.NaviPayCustomerOnboardingEntit
|
||||
sealed class PMSSendMoneyStatus {
|
||||
data class Success(
|
||||
val upiRequestId: String,
|
||||
val credBlock: String? = null,
|
||||
val credBlock: String,
|
||||
val onboardingDataEntity: NaviPayCustomerOnboardingEntity,
|
||||
) : PMSSendMoneyStatus()
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.presentation.reducer
|
||||
|
||||
import com.ramcosta.composedestinations.spec.Direction
|
||||
|
||||
sealed interface MPSScreenEffect {
|
||||
data class Navigation(val direction: Direction) : MPSScreenEffect
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.presentation.reducer
|
||||
|
||||
import com.navi.payment.nativepayment.utils.PaymentCancelSource
|
||||
import com.ramcosta.composedestinations.spec.Direction
|
||||
|
||||
sealed interface OneClickCheckoutScreenEffect {
|
||||
data class SetResultAndFinish(
|
||||
val cancelSource: PaymentCancelSource,
|
||||
val shouldPromptAmountEdit: Boolean,
|
||||
) : OneClickCheckoutScreenEffect
|
||||
|
||||
data class Navigation(val direction: Direction) : OneClickCheckoutScreenEffect
|
||||
}
|
||||
@@ -34,18 +34,13 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.google.gson.Gson
|
||||
import com.navi.analytics.utils.AlfredFacade
|
||||
import com.navi.base.utils.isNotNull
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.isNull
|
||||
import com.navi.base.utils.orElse
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_PMT_API_CONNECT_TIMEOUT
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_PMT_RETRY_POLICY_ENABLED
|
||||
import com.navi.common.model.RequestConfig
|
||||
import com.navi.common.utils.TemporaryStorageHelper
|
||||
import com.navi.naviwidgets.R
|
||||
import com.navi.pay.common.arc.ui.ArcNudgeBottomSheetContent
|
||||
@@ -66,20 +61,17 @@ import com.navi.payment.nativepayment.components.MPSNonOnboardedView
|
||||
import com.navi.payment.nativepayment.components.MPSOnboardedView
|
||||
import com.navi.payment.nativepayment.dataprovider.PinAction
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.PMSSendMoneyStatus
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatusRequest
|
||||
import com.navi.payment.nativepayment.presentation.reducer.MPSScreenEffect
|
||||
import com.navi.payment.nativepayment.screens.destinations.NPSScreenRootDestination
|
||||
import com.navi.payment.nativepayment.screens.destinations.TransactionPollingScreenDestination
|
||||
import com.navi.payment.nativepayment.utils.MPSScreenUtils
|
||||
import com.navi.payment.nativepayment.utils.PaymentCancelSource
|
||||
import com.navi.payment.nativepayment.utils.handleResultAndFinish
|
||||
import com.navi.payment.nativepayment.viewmodel.MPSViewModel
|
||||
import com.navi.payment.nativepayment.viewmodel.NaviPaymentViewModel
|
||||
import com.navi.payment.paymentscreen.model.NaviPayProcessPayload
|
||||
import com.navi.payment.paymentscreen.model.NaviUpiTransactionInfo
|
||||
import com.navi.payment.utils.Constants.MINI_PAYMENT_SCREEN
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Destination
|
||||
@@ -117,7 +109,6 @@ fun MPSScreen(
|
||||
val showDiscountedAmount by mpsViewModel.showDiscountedAmount.collectAsStateWithLifecycle()
|
||||
val checkBalanceStateMap by mpsViewModel.checkBalanceStateMap.collectAsStateWithLifecycle()
|
||||
val checkBalanceAccountId by mpsViewModel.checkBalanceAccountId.collectAsStateWithLifecycle()
|
||||
val sendMoneyStatus by mpsViewModel.pmsSendMoneyStatus.collectAsStateWithLifecycle()
|
||||
|
||||
val rewardsInfoV2 by mpsViewModel.rewardsInfoV2.collectAsStateWithLifecycle()
|
||||
val isDiscountPreApplied by mpsViewModel.isDiscountPreApplied.collectAsStateWithLifecycle()
|
||||
@@ -145,52 +136,7 @@ fun MPSScreen(
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = sendMoneyStatus) {
|
||||
if (sendMoneyStatus is PMSSendMoneyStatus.Success) {
|
||||
val pmsSendMoneyStatus = sendMoneyStatus as PMSSendMoneyStatus.Success
|
||||
val payNowResponse = mpsViewModel.payNowResponse
|
||||
val payload = (payNowResponse?.providerPayload) as? NaviPayProcessPayload
|
||||
if (
|
||||
mpsViewModel.paymentSdkInitParams?.token.isNotNullAndNotEmpty() &&
|
||||
payNowResponse?.transactionReferenceId.isNotNullAndNotEmpty()
|
||||
) {
|
||||
navigator.navigate(
|
||||
TransactionPollingScreenDestination(
|
||||
token = mpsViewModel.paymentSdkInitParams?.token.orEmpty(),
|
||||
paymentAmount = paymentAmount,
|
||||
redeemedCoinsValue =
|
||||
if (isDiscountApplied)
|
||||
if (rewardsInfoV2.isNull())
|
||||
coinBurnDetails?.redeemableCoinsValue?.value.orZero()
|
||||
else rewardsInfoV2?.burnDetails?.coinsValue?.value.orZero()
|
||||
else 0.0,
|
||||
source = mpsViewModel.paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
tstoreOrderReferenceId = payload?.tstoreOrderReferenceId.orEmpty(),
|
||||
sourceDestination = NaviPaymentScreenType.MINI_PAYMENT_SCREEN.name,
|
||||
pollingConfiguration =
|
||||
payNowResponse?.pollingConfiguration ?: RequestConfig(),
|
||||
request =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId = payNowResponse?.transactionReferenceId,
|
||||
screenType = NaviPaymentScreenType.MINI_PAYMENT_SCREEN.name,
|
||||
),
|
||||
naviUpiTransactionInfo =
|
||||
NaviUpiTransactionInfo(
|
||||
naviPayUpiUriKey = payload?.naviPayUpiUriKey,
|
||||
upiRequestId = pmsSendMoneyStatus.upiRequestId,
|
||||
selectedBankAccountId = selectedBankAccount?.accountId.orEmpty(),
|
||||
credBlock = pmsSendMoneyStatus.credBlock.orEmpty(),
|
||||
metaData = Gson().toJson(payload?.metadata),
|
||||
txnTimeStamp = mpsViewModel.txnTimeStamp,
|
||||
isArcProtected = selectedBankAccount?.isArcProtected.orFalse(),
|
||||
onboardingDataEntity = pmsSendMoneyStatus.onboardingDataEntity,
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
mpsViewModel.onNaviPayCallBack()
|
||||
}
|
||||
EffectsHandler(mpsScreenEffect = mpsViewModel.effect, navigator = navigator)
|
||||
|
||||
LaunchedEffect(key1 = Unit) {
|
||||
naviPaymentAnalytics.onMPSLanded(baseAttributes = mpsViewModel.getAnalyticsParams())
|
||||
@@ -598,6 +544,17 @@ fun MPSScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EffectsHandler(mpsScreenEffect: SharedFlow<MPSScreenEffect>, navigator: DestinationsNavigator) {
|
||||
LaunchedEffect(Unit) {
|
||||
mpsScreenEffect.collectLatest { effect ->
|
||||
when (effect) {
|
||||
is MPSScreenEffect.Navigation -> navigator.navigate(effect.direction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HandleLifecycleEventsForAlfred(naviPaymentActivity: NaviPaymentActivity) {
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
|
||||
@@ -26,11 +26,9 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.google.gson.Gson
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.model.RequestConfig
|
||||
import com.navi.common.upi.CANCEL
|
||||
import com.navi.common.upi.NAVI_PAY_RESPONSE
|
||||
import com.navi.common.utils.stringToJsonObject
|
||||
import com.navi.pay.common.theme.color.NaviPayColor
|
||||
@@ -43,14 +41,13 @@ import com.navi.payment.nativepayment.activity.NaviPaymentActivity
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.OneClickScreenBottomSheetUiState
|
||||
import com.navi.payment.nativepayment.model.PMSSendMoneyStatus
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatus
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatusRequest
|
||||
import com.navi.payment.nativepayment.presentation.reducer.OneClickCheckoutScreenEffect
|
||||
import com.navi.payment.nativepayment.screens.destinations.NPSScreenRootDestination
|
||||
import com.navi.payment.nativepayment.screens.destinations.TransactionPollingScreenDestination
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentBottomSheetButtonAction
|
||||
import com.navi.payment.nativepayment.utils.PaymentCancelSource
|
||||
import com.navi.payment.nativepayment.utils.handleResultAndFinish
|
||||
import com.navi.payment.nativepayment.utils.toNaviPaymentErrorConfig
|
||||
import com.navi.payment.nativepayment.viewmodel.OneClickCheckoutViewModel
|
||||
import com.navi.payment.paymentscreen.model.NaviPayProcessPayload
|
||||
import com.navi.payment.paymentscreen.model.NaviUpiTransactionInfo
|
||||
@@ -58,6 +55,7 @@ import com.navi.payment.paymentscreen.model.PayNowResponse
|
||||
import com.navi.payment.utils.validateUpiProcessPayload
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -72,8 +70,6 @@ fun OneClickCheckoutScreen(
|
||||
NaviPaymentAnalytics.INSTANCE.SendMoneyErrorBottomSheet(),
|
||||
) {
|
||||
|
||||
val sendMoneyStatus by
|
||||
oneClickCheckoutViewModel.pmsSendMoneyStatus.collectAsStateWithLifecycle()
|
||||
val bottomSheetStateHolder by
|
||||
oneClickCheckoutViewModel.bottomSheetStateHolder.collectAsStateWithLifecycle()
|
||||
val checkBalanceStateMap by
|
||||
@@ -86,6 +82,12 @@ fun OneClickCheckoutScreen(
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
EffectsHandler(
|
||||
screenEffect = oneClickCheckoutViewModel.effect,
|
||||
activity = naviPaymentActivity,
|
||||
navigator = navigator,
|
||||
)
|
||||
|
||||
val finishCallback:
|
||||
(cancelSource: PaymentCancelSource, shouldPromptAmountEdit: Boolean) -> Unit =
|
||||
{ cancelSource, shouldPromptAmountEdit ->
|
||||
@@ -102,7 +104,7 @@ fun OneClickCheckoutScreen(
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
systemUiController.setStatusBarColor(Color.White)
|
||||
oneClickCheckoutViewModel.startPayment(bundle = naviPaymentActivity.intent.extras)
|
||||
oneClickCheckoutViewModel.startPaymentProcess(bundle = naviPaymentActivity.intent.extras)
|
||||
}
|
||||
|
||||
BackHandler {
|
||||
@@ -132,50 +134,6 @@ fun OneClickCheckoutScreen(
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = sendMoneyStatus) {
|
||||
when (val pmsSendMoneyStatus = sendMoneyStatus) {
|
||||
is PMSSendMoneyStatus.Success -> {
|
||||
val payNowResponse = oneClickCheckoutViewModel.payNowResponse
|
||||
val payload = (payNowResponse?.providerPayload) as? NaviPayProcessPayload
|
||||
if (
|
||||
oneClickCheckoutViewModel.paymentSdkInitParams?.token.isNotNullAndNotEmpty() &&
|
||||
payNowResponse?.transactionReferenceId.isNotNullAndNotEmpty()
|
||||
) {
|
||||
oneClickCheckoutViewModel.updateTransactionStatusToPending(
|
||||
transactionReferenceId = payNowResponse?.transactionReferenceId
|
||||
)
|
||||
navigateToTransactionPollingScreen(
|
||||
navigator = navigator,
|
||||
oneClickCheckoutViewModel = oneClickCheckoutViewModel,
|
||||
payload = payload,
|
||||
payNowResponse = payNowResponse,
|
||||
pmsSendMoneyStatus = pmsSendMoneyStatus,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is PMSSendMoneyStatus.Error -> { // do this in VM instead
|
||||
var transactionStatus = TransactionStatus.ERROR.name
|
||||
if (pmsSendMoneyStatus.errorConfig.code == CANCEL) {
|
||||
transactionStatus = TransactionStatus.USER_CANCELLED_TRANSACTION.name
|
||||
oneClickCheckoutViewModel.handleBackPress(
|
||||
cancelSource = PaymentCancelSource.SYSTEM_BACK_CLICKED,
|
||||
finishCallback = finishCallback,
|
||||
)
|
||||
} else {
|
||||
oneClickCheckoutViewModel.notifyError(
|
||||
errorConfig = pmsSendMoneyStatus.errorConfig.toNaviPaymentErrorConfig()
|
||||
)
|
||||
}
|
||||
oneClickCheckoutViewModel.notifyNaviUpiExitWithError(
|
||||
status = transactionStatus,
|
||||
error = pmsSendMoneyStatus.errorConfig,
|
||||
)
|
||||
}
|
||||
null -> {}
|
||||
}
|
||||
oneClickCheckoutViewModel.onNaviPayCallBack()
|
||||
}
|
||||
Column { Surface(modifier = Modifier.fillMaxSize(), color = Color.Transparent) {} }
|
||||
ObserveBottomSheetEvents(activity = naviPaymentActivity, finishCallback = finishCallback)
|
||||
if (bottomSheetStateHolder.showBottomSheet) {
|
||||
@@ -343,3 +301,31 @@ private fun navigateToTransactionPollingScreen(
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EffectsHandler(
|
||||
screenEffect: SharedFlow<OneClickCheckoutScreenEffect>,
|
||||
activity: NaviPaymentActivity,
|
||||
navigator: DestinationsNavigator,
|
||||
) {
|
||||
LaunchedEffect(Unit) {
|
||||
screenEffect.collectLatest { effect ->
|
||||
when (effect) {
|
||||
is OneClickCheckoutScreenEffect.SetResultAndFinish -> {
|
||||
handleResultAndFinish(
|
||||
activity = activity,
|
||||
resultCode = 0,
|
||||
screenName = NaviPaymentScreenType.ONE_CLICK_CHECKOUT_SCREEN.name,
|
||||
cancelSource = effect.cancelSource,
|
||||
slideDirection = AnimatedContentTransitionScope.SlideDirection.Down,
|
||||
shouldPromptAmountEdit = effect.shouldPromptAmountEdit,
|
||||
)
|
||||
}
|
||||
|
||||
is OneClickCheckoutScreenEffect.Navigation -> {
|
||||
navigator.navigate(effect.direction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.navi.base.utils.FAILURE
|
||||
import com.navi.base.utils.SUCCESS
|
||||
import com.navi.base.utils.isNotNull
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.common.network.models.GenericErrorResponse
|
||||
import com.navi.common.uitron.model.action.UpiIntent
|
||||
import com.navi.common.upi.CANCEL
|
||||
@@ -255,22 +254,7 @@ fun WebPaymentMainScreen(
|
||||
val onPayButtonClick: () -> Unit = {
|
||||
try {
|
||||
finishBackgroundTask(activity)
|
||||
|
||||
if (selectedBankAccount?.isMPinSet.orFalse().not()) {
|
||||
naviPaymentAnalytics.onSetUpiPinBtnClick(
|
||||
webPaymentAction = webPaymentAction,
|
||||
webPaymentData = webPaymentData.toJsonObject(),
|
||||
baseAttributes = webPaymentViewModel.getAnalyticsParams(),
|
||||
)
|
||||
webPaymentViewModel.updateLastTriggeredActionBeforeOnboarding(webPaymentAction)
|
||||
webPaymentViewModel.handleMPinSetup(activity, upiResultLauncher)
|
||||
} else {
|
||||
naviPaymentAnalytics.onPayNowClicked(webPaymentViewModel.getAnalyticsParams())
|
||||
webPaymentViewModel.startPayAmount(
|
||||
selectedBankAccount?.accountId.orEmpty(),
|
||||
selectedBankAccount?.accountType.orEmpty(),
|
||||
)
|
||||
}
|
||||
webPaymentViewModel.onPayButtonClick(activity, upiResultLauncher)
|
||||
} catch (exception: Exception) {
|
||||
exception.log()
|
||||
}
|
||||
@@ -301,17 +285,7 @@ fun WebPaymentMainScreen(
|
||||
}
|
||||
}
|
||||
|
||||
val onBackClick: () -> Unit = {
|
||||
naviPaymentAnalytics.onBackPressed(webPaymentViewModel.getAnalyticsParams())
|
||||
webPaymentViewModel.finishWithResult {
|
||||
handleResultAndFinish(
|
||||
activity = activity,
|
||||
webPaymentAction = webPaymentAction,
|
||||
webPaymentData = webPaymentData,
|
||||
status = TransactionStatus.USER_CANCELLED_TRANSACTION.name,
|
||||
)
|
||||
}
|
||||
}
|
||||
val onBackClick: () -> Unit = { webPaymentViewModel.handleBackClick() }
|
||||
|
||||
BackHandler { onBackClick.invoke() }
|
||||
|
||||
@@ -324,7 +298,7 @@ fun WebPaymentMainScreen(
|
||||
bottomSheetStateHolder.showBottomSheet &&
|
||||
webPaymentViewModel.isDismissAllowed
|
||||
) {
|
||||
onBackClick.invoke()
|
||||
webPaymentViewModel.handleBackClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,7 +379,7 @@ fun WebPaymentMainScreen(
|
||||
NaviPayModalBottomSheetLayout(
|
||||
sheetState = bottomSheetState,
|
||||
sheetContent = {
|
||||
when (bottomSheetStateHolder.bottomSheetUIState) {
|
||||
when (val bottomSheetUIState = bottomSheetStateHolder.bottomSheetUIState) {
|
||||
is WebPaymentScreenState.Loading -> {
|
||||
MPSLoadingShimmer()
|
||||
}
|
||||
@@ -427,19 +401,10 @@ fun WebPaymentMainScreen(
|
||||
)
|
||||
}
|
||||
is WebPaymentScreenState.Error -> {
|
||||
webPaymentViewModel.finishWithResult {
|
||||
handleResultAndFinish(
|
||||
activity = activity,
|
||||
webPaymentAction = webPaymentAction,
|
||||
webPaymentData = webPaymentData,
|
||||
status = FAILURE,
|
||||
error =
|
||||
(bottomSheetStateHolder.bottomSheetUIState
|
||||
as? WebPaymentScreenState.Error)
|
||||
?.errorData
|
||||
?.error,
|
||||
)
|
||||
}
|
||||
webPaymentViewModel.finishWithResult(
|
||||
status = FAILURE,
|
||||
error = bottomSheetUIState.errorData?.error,
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.usecase
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.navi.base.utils.EMPTY
|
||||
import com.navi.base.utils.ResourceProvider
|
||||
import com.navi.common.checkmate.core.CheckMateManager
|
||||
import com.navi.common.checkmate.model.MetricInfo
|
||||
import com.navi.common.network.models.GenericErrorResponse
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.common.upi.CANCEL
|
||||
import com.navi.common.utils.safeLaunch
|
||||
import com.navi.common.utils.toJsonObject
|
||||
import com.navi.pay.common.model.view.NaviPayErrorConfig
|
||||
import com.navi.pay.common.model.view.NaviPayFlowType
|
||||
import com.navi.pay.management.common.utils.NaviPayPspManager
|
||||
import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
|
||||
import com.navi.pay.onboarding.binding.model.view.NaviPayCustomerOnboardingEntity
|
||||
import com.navi.payment.R
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalytics
|
||||
import com.navi.payment.nativepayment.common.usecase.TransactionStatusUseCase
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.PAYMENT_ORDER_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.TRANSACTION_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.db.model.TransactionStatusRequestEntity
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.PMSSendMoneyStatus
|
||||
import com.navi.payment.nativepayment.model.UpiLinkedAccountPaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatus
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatusRequest
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.utils.toGenericError
|
||||
import com.navi.payment.nativepayment.utils.toGenericErrorResponse
|
||||
import com.navi.payment.paymentscreen.model.InternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.PayNowResponse
|
||||
import com.navi.payment.turbocheckout.model.PayAmountRequest
|
||||
import com.navi.payment.utils.getPMSMetricInfo
|
||||
import com.navi.payment.utils.isUpiLiteAccount
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.joda.time.DateTime
|
||||
|
||||
/**
|
||||
* NaviUpiPaymentProcessor
|
||||
*
|
||||
* A centralized, injectable processor that manages the complete UPI payment lifecycle (for both
|
||||
* Lite and Non-Lite accounts) within the Navi Payments SDK. This class abstracts away the
|
||||
* complexities of onboarding, payment initiation, analytics, and error management, providing a
|
||||
* single, unified interface for all UPI payment flows.
|
||||
*
|
||||
* ## Purpose & Architectural Role
|
||||
* - Serves as the canonical entry point for all UPI payment operations in the payments module.
|
||||
* - Eliminates code duplication and branching logic that previously existed across multiple
|
||||
* ViewModels (e.g., NPSViewModel, MPSViewModel).
|
||||
* - Ensures a consistent, maintainable, and extensible payment flow for all UPI transactions,
|
||||
* regardless of account type.
|
||||
*
|
||||
* ## Usage
|
||||
* ViewModels and other payment orchestration components should delegate payment initiation to this
|
||||
* processor via the [makePayment] function, providing all necessary parameters and callbacks for
|
||||
* onboarding, payment, and error handling. This guarantees that any changes to payment flow,
|
||||
* analytics, or error handling are managed in a single location.
|
||||
*
|
||||
* ## Benefits to the Payments System
|
||||
* - **Maintainability:** Updates to payment flow, analytics, or error handling are made in one
|
||||
* place and instantly propagate.
|
||||
* - **Consistency:** All UPI payment flows (Lite/Non-Lite) follow the same process, reducing the
|
||||
* risk of bugs and divergent behavior.
|
||||
* - **Extensibility:** New features, account types, or analytics hooks can be added centrally
|
||||
* without modifying multiple ViewModels.
|
||||
* - **Code Quality:** Reduces surface area for errors, simplifies onboarding for new developers,
|
||||
* and enforces best practices across the payments module.
|
||||
*/
|
||||
class NaviUpiPaymentProcessor
|
||||
@Inject
|
||||
constructor(
|
||||
private val naviPayPspManager: NaviPayPspManager,
|
||||
private val pmsSendMoneyUseCase: PmsSendMoneyUseCase,
|
||||
private val paymentDataProvider: PaymentDataProvider,
|
||||
private val paymentRepository: PaymentRepository,
|
||||
private val transactionStatusUseCase: TransactionStatusUseCase,
|
||||
private val resourceProvider: ResourceProvider,
|
||||
) {
|
||||
// arguments
|
||||
private lateinit var paymentToken: String
|
||||
private lateinit var account: LinkedAccountEntity
|
||||
private lateinit var naviPaymentScreen: NaviPaymentScreenType
|
||||
|
||||
// analytics
|
||||
private lateinit var analyticScreenName: String
|
||||
private lateinit var baseAttributes: Map<String, String>
|
||||
|
||||
private val pspManagerAnalytics: NaviPaymentAnalytics.PspManager =
|
||||
NaviPaymentAnalytics.INSTANCE.PspManager()
|
||||
private val paymentProcessorAnalytics: NaviPaymentAnalytics.NaviUpiPaymentProcessor =
|
||||
NaviPaymentAnalytics.INSTANCE.NaviUpiPaymentProcessor()
|
||||
|
||||
/**
|
||||
* Initiates a UPI payment (Lite or Non-Lite) for the provided account, centralizing all payment
|
||||
* logic.
|
||||
*
|
||||
* This function is designed to be the single entry point for all UPI payment flows, eliminating
|
||||
* code duplication across multiple ViewModels (such as NPSViewModel, MPSViewModel, etc). It
|
||||
* encapsulates the entire payment lifecycle: onboarding, payment initiation, PIN handling,
|
||||
* analytics, and error management, via a unified interface.
|
||||
*
|
||||
* Usage:
|
||||
* - ViewModels should delegate payment initiation to this function, passing all required
|
||||
* parameters and callbacks.
|
||||
* - This ensures that any updates to payment flow, analytics, or error handling are managed in
|
||||
* one place.
|
||||
*
|
||||
* @param account The UPI-linked account to make the payment from. Must have MPIN set.
|
||||
* @param isDiscountApplied Whether a discount (e.g., Navi Coins) is being applied in this
|
||||
* payment.
|
||||
* @param discountInfo List of applied discount info (if any).
|
||||
* @param analyticScreenName Screen name for analytics and event tracking.
|
||||
* @param naviPaymentScreen Enum representing which payment screen is invoking the flow (e.g.,
|
||||
* FULL_PAYMENT_SCREEN).
|
||||
* @param paymentToken Token received from the payment backend for this transaction.
|
||||
* @param baseAttributes Analytics attributes for tracking and reporting.
|
||||
* @param onInitialChecksFailure Callback for initial validation failure.
|
||||
* @param onOnboardingTriggered Callback when onboarding is triggered for the account.
|
||||
* @param onOnboardingCancelled Callback when onboarding is cancelled by the user.
|
||||
* @param onOnboardingCompleted Callback when onboarding is completed successfully.
|
||||
* @param onBeforePayNowApiCall Callback before making the PayNow API call (e.g., show loader).
|
||||
* @param onPayNowSuccess Callback on successful PayNow API response.
|
||||
* @param onPayNowFailure Callback on failed PayNow API response.
|
||||
* @param onBeforeOpeningPinPage Callback before navigating to the PIN page.
|
||||
* @param onPinPageBack Callback when the PIN page is dismissed/backed out.
|
||||
* @param onPinPageError Callback on error during PIN entry/validation.
|
||||
* @param onPinPageSuccess Callback on successful PIN entry and payment completion.
|
||||
*
|
||||
* Example usage in a ViewModel:
|
||||
* ```kotlin
|
||||
* naviUpiPaymentProcessor.makePayment(
|
||||
* account = selectedBankAccount,
|
||||
* isDiscountApplied = npsScreenState.naviCoinState.isDiscountApplied,
|
||||
* discountInfo = createDiscountInfo(),
|
||||
* analyticScreenName = screenName,
|
||||
* naviPaymentScreen = NaviPaymentScreenType.FULL_PAYMENT_SCREEN,
|
||||
* paymentToken = paymentSdkInitParams?.token.orEmpty(),
|
||||
* baseAttributes = baseAnalyticsParams,
|
||||
* ... // pass all required callbacks
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* This approach ensures all UPI payment flows are consistent, maintainable, and easily
|
||||
* extensible.
|
||||
*/
|
||||
suspend fun makePayment(
|
||||
account: LinkedAccountEntity,
|
||||
isDiscountApplied: Boolean,
|
||||
discountInfo: List<PayAmountRequest.DiscountInfo>?,
|
||||
analyticScreenName: String,
|
||||
naviPaymentScreen: NaviPaymentScreenType,
|
||||
paymentToken: String,
|
||||
baseAttributes: Map<String, String>,
|
||||
onInitialChecksFailure: (GenericErrorResponse) -> Unit,
|
||||
onOnboardingTriggered: () -> Unit,
|
||||
onOnboardingCancelled: () -> Unit,
|
||||
onOnboardingCompleted: () -> Unit,
|
||||
onBeforePayNowApiCall: () -> Unit,
|
||||
onPayNowSuccess: (PayNowResponse) -> Unit,
|
||||
onPayNowFailure: (GenericErrorResponse) -> Unit,
|
||||
onBeforeOpeningPinPage: () -> Unit,
|
||||
onPinPageBack: () -> Unit,
|
||||
onPinPageError: (GenericErrorResponse) -> Unit,
|
||||
onPinPageSuccess: suspend (UpiNavigationResponse) -> Unit,
|
||||
) {
|
||||
if (initialChecksFailed(account, paymentToken, analyticScreenName, onInitialChecksFailure))
|
||||
return
|
||||
initialise(analyticScreenName, naviPaymentScreen, baseAttributes, paymentToken, account)
|
||||
when {
|
||||
account.isUpiLiteAccount() ->
|
||||
processUpiLitePayment(
|
||||
isDiscountApplied = isDiscountApplied,
|
||||
discountInfo = discountInfo,
|
||||
onInitialChecksFailure = onInitialChecksFailure,
|
||||
onOnboardingTriggered = onOnboardingTriggered,
|
||||
onOnboardingCancelled = onOnboardingCancelled,
|
||||
onOnboardingCompleted = onOnboardingCompleted,
|
||||
onBeforePayNowApiCall = onBeforePayNowApiCall,
|
||||
onPayNowFailure = onPayNowFailure,
|
||||
onPayNowSuccess = onPayNowSuccess,
|
||||
onBeforeOpeningPinPage = onBeforeOpeningPinPage,
|
||||
onPinPageBack = onPinPageBack,
|
||||
onPinPageError = onPinPageError,
|
||||
onPinPageSuccess = onPinPageSuccess,
|
||||
)
|
||||
|
||||
else ->
|
||||
processNonUpiLitePayment(
|
||||
isDiscountApplied = isDiscountApplied,
|
||||
discountInfo = discountInfo,
|
||||
onOnboardingTriggered = onOnboardingTriggered,
|
||||
onOnboardingCancelled = onOnboardingCancelled,
|
||||
onOnboardingCompleted = onOnboardingCompleted,
|
||||
onBeforePayNowApiCall = onBeforePayNowApiCall,
|
||||
onPayNowFailure = onPayNowFailure,
|
||||
onPayNowSuccess = onPayNowSuccess,
|
||||
onBeforeOpeningPinPage = onBeforeOpeningPinPage,
|
||||
onPinPageBack = onPinPageBack,
|
||||
onPinPageError = onPinPageError,
|
||||
onPinPageSuccess = onPinPageSuccess,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initialChecksFailed(
|
||||
account: LinkedAccountEntity,
|
||||
paymentToken: String,
|
||||
analyticScreenName: String,
|
||||
onInitialChecksFailure: (GenericErrorResponse) -> Unit,
|
||||
): Boolean {
|
||||
if (account.isMPinSet.not()) return true
|
||||
if (paymentToken.isEmpty()) {
|
||||
CheckMateManager.logAppErrorEvent(
|
||||
metricInfo = MetricInfo.PMSMetric<Any>(screen = analyticScreenName),
|
||||
errorCode = resourceProvider.getString(R.string.empty_payment_token),
|
||||
errorTitle = resourceProvider.getString(R.string.something_went_wrong),
|
||||
errorDes = resourceProvider.getString(R.string.technical_issue),
|
||||
)
|
||||
onInitialChecksFailure(
|
||||
GenericErrorResponse(
|
||||
title = resourceProvider.getString(R.string.something_went_wrong),
|
||||
message = resourceProvider.getString(R.string.technical_issue),
|
||||
code = resourceProvider.getString(R.string.empty_payment_token),
|
||||
logMessage = resourceProvider.getString(R.string.empty_payment_token),
|
||||
)
|
||||
)
|
||||
paymentProcessorAnalytics.onEmptyPaymentToken(
|
||||
screenName = analyticScreenName,
|
||||
baseAttributes = baseAttributes,
|
||||
)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun initialise(
|
||||
analyticScreenName: String,
|
||||
naviPaymentScreen: NaviPaymentScreenType,
|
||||
baseAttributes: Map<String, String>,
|
||||
paymentToken: String,
|
||||
account: LinkedAccountEntity,
|
||||
) {
|
||||
this.analyticScreenName = analyticScreenName
|
||||
this.naviPaymentScreen = naviPaymentScreen
|
||||
this.baseAttributes = baseAttributes
|
||||
this.paymentToken = paymentToken
|
||||
this.account = account
|
||||
}
|
||||
|
||||
private suspend fun processUpiLitePayment(
|
||||
isDiscountApplied: Boolean,
|
||||
discountInfo: List<PayAmountRequest.DiscountInfo>?,
|
||||
onInitialChecksFailure: (GenericErrorResponse) -> Unit,
|
||||
onOnboardingTriggered: () -> Unit,
|
||||
onOnboardingCancelled: () -> Unit,
|
||||
onOnboardingCompleted: () -> Unit,
|
||||
onBeforePayNowApiCall: () -> Unit,
|
||||
onPayNowFailure: (GenericErrorResponse) -> Unit,
|
||||
onPayNowSuccess: (PayNowResponse) -> Unit,
|
||||
onBeforeOpeningPinPage: () -> Unit,
|
||||
onPinPageBack: () -> Unit,
|
||||
onPinPageError: (GenericErrorResponse) -> Unit,
|
||||
onPinPageSuccess: suspend (UpiNavigationResponse) -> Unit,
|
||||
) {
|
||||
if (account.activeLiteAccountPsp == null) {
|
||||
CheckMateManager.logAppErrorEvent(
|
||||
metricInfo = MetricInfo.PMSMetric<Any>(screen = analyticScreenName),
|
||||
errorCode = resourceProvider.getString(R.string.no_active_lite_account_psp),
|
||||
errorTitle = resourceProvider.getString(R.string.something_went_wrong),
|
||||
errorDes = resourceProvider.getString(R.string.technical_issue),
|
||||
)
|
||||
onInitialChecksFailure(getUpiLiteChecksFailureErrorConfig())
|
||||
return
|
||||
}
|
||||
val vpaEntityForLiteAccount =
|
||||
account.getVpaEntityByPsp(account.activeLiteAccountPsp ?: return)
|
||||
paymentProcessorAnalytics.onUpiLitePayment(
|
||||
screenName = analyticScreenName,
|
||||
isDiscountApplied = isDiscountApplied.toString(),
|
||||
baseAttributes = baseAttributes,
|
||||
)
|
||||
pspManagerAnalytics.onSendMoneyWithPspManager(
|
||||
accountId = account.accountId,
|
||||
isPaymentFromLiteAccount = true,
|
||||
screenName = analyticScreenName,
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForVpa(
|
||||
vpaEntity = vpaEntityForLiteAccount,
|
||||
screenName = analyticScreenName,
|
||||
onOnboardingTriggered = { onOnboardingTriggered() },
|
||||
naviPayFlowType = NaviPayFlowType.UPI_LITE,
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, analyticScreenName)
|
||||
if (pspEvaluationResult.isOnboardingTriggered) {
|
||||
if (pspEvaluationResult.onboardingDataEntity == null) {
|
||||
onOnboardingCancelled()
|
||||
return@evaluateAndOnboardPspForVpa
|
||||
} else {
|
||||
onOnboardingCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
callPayNowApi(
|
||||
discountInfo = discountInfo,
|
||||
onboardingDataEntity = onboardingEntity,
|
||||
onBeforePayNowApiCall = onBeforePayNowApiCall,
|
||||
onPayNowSuccess = onPayNowSuccess,
|
||||
onPayNowFailure = onPayNowFailure,
|
||||
onBeforeOpeningPinPage = onBeforeOpeningPinPage,
|
||||
onPinPageBack = onPinPageBack,
|
||||
onPinPageError = onPinPageError,
|
||||
onPinPageSuccess = onPinPageSuccess,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun processNonUpiLitePayment(
|
||||
isDiscountApplied: Boolean,
|
||||
discountInfo: List<PayAmountRequest.DiscountInfo>?,
|
||||
onOnboardingTriggered: () -> Unit,
|
||||
onOnboardingCancelled: () -> Unit,
|
||||
onOnboardingCompleted: () -> Unit,
|
||||
onBeforePayNowApiCall: () -> Unit,
|
||||
onPayNowFailure: (GenericErrorResponse) -> Unit,
|
||||
onPayNowSuccess: (PayNowResponse) -> Unit,
|
||||
onBeforeOpeningPinPage: () -> Unit,
|
||||
onPinPageBack: () -> Unit,
|
||||
onPinPageError: (GenericErrorResponse) -> Unit,
|
||||
onPinPageSuccess: suspend (UpiNavigationResponse) -> Unit,
|
||||
) {
|
||||
paymentProcessorAnalytics.onNonUpiLitePayment(
|
||||
screenName = analyticScreenName,
|
||||
isDiscountApplied = isDiscountApplied.toString(),
|
||||
accountId = account.accountId,
|
||||
baseAttributes = baseAttributes,
|
||||
)
|
||||
pspManagerAnalytics.onSendMoneyWithPspManager(
|
||||
accountId = account.accountId,
|
||||
isPaymentFromLiteAccount = false,
|
||||
screenName = analyticScreenName,
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForFlow(
|
||||
naviPayFlowType = NaviPayFlowType.getSendMoneyFlowForAccountType(account.accountType),
|
||||
vpaEntityList = account.vpaEntityList,
|
||||
screenName = analyticScreenName,
|
||||
onOnboardingTriggered = { onOnboardingTriggered() },
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, analyticScreenName)
|
||||
if (pspEvaluationResult.isOnboardingTriggered) {
|
||||
if (pspEvaluationResult.onboardingDataEntity == null) {
|
||||
onOnboardingCancelled()
|
||||
return@evaluateAndOnboardPspForFlow
|
||||
} else {
|
||||
onOnboardingCompleted()
|
||||
}
|
||||
}
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
callPayNowApi(
|
||||
discountInfo = discountInfo,
|
||||
onboardingDataEntity = onboardingEntity,
|
||||
onBeforePayNowApiCall = onBeforePayNowApiCall,
|
||||
onPayNowSuccess = onPayNowSuccess,
|
||||
onPayNowFailure = onPayNowFailure,
|
||||
onBeforeOpeningPinPage = onBeforeOpeningPinPage,
|
||||
onPinPageBack = onPinPageBack,
|
||||
onPinPageError = onPinPageError,
|
||||
onPinPageSuccess = onPinPageSuccess,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun callPayNowApi(
|
||||
discountInfo: List<PayAmountRequest.DiscountInfo>?,
|
||||
onboardingDataEntity: NaviPayCustomerOnboardingEntity,
|
||||
onBeforePayNowApiCall: () -> Unit,
|
||||
onPayNowSuccess: (PayNowResponse) -> Unit,
|
||||
onPayNowFailure: (GenericErrorResponse) -> Unit,
|
||||
onBeforeOpeningPinPage: () -> Unit,
|
||||
onPinPageBack: () -> Unit,
|
||||
onPinPageError: (GenericErrorResponse) -> Unit,
|
||||
onPinPageSuccess: suspend (UpiNavigationResponse) -> Unit,
|
||||
) {
|
||||
onBeforePayNowApiCall()
|
||||
val payNowResponse =
|
||||
paymentRepository.postPayNow(
|
||||
token = paymentToken,
|
||||
data =
|
||||
PayAmountRequest(
|
||||
methodName = UpiLinkedAccountPaymentInstrument.PAYMENT_INSTRUMENT_TYPE,
|
||||
selectedMethodDetails =
|
||||
PayAmountRequest.SelectedMethodDetails(
|
||||
payerBankAccountId = account.accountId,
|
||||
accountType = account.accountType,
|
||||
),
|
||||
discountInfo = discountInfo,
|
||||
),
|
||||
metricInfo = getPMSMetricInfo(screenName = analyticScreenName),
|
||||
)
|
||||
val internalPayNowResponse = payNowResponse.data as? InternalPayNowResponse
|
||||
val intentUri = internalPayNowResponse?.providerPayload?.naviPayUpiUriKey.orEmpty()
|
||||
val transactionReferenceId = internalPayNowResponse?.transactionReferenceId.orEmpty()
|
||||
val paymentOrderReferenceId = internalPayNowResponse?.paymentOrderReferenceId.orEmpty()
|
||||
if (
|
||||
payNowResponse.isSuccessWithData() &&
|
||||
internalPayNowResponse != null &&
|
||||
intentUri.isNotEmpty() &&
|
||||
transactionReferenceId.isNotEmpty() &&
|
||||
paymentOrderReferenceId.isNotEmpty()
|
||||
) {
|
||||
updateTransactionInfoInDataProvider(transactionReferenceId, paymentOrderReferenceId)
|
||||
insertTransactionStatusRequest(transactionReferenceId)
|
||||
onPayNowSuccess(internalPayNowResponse)
|
||||
startNaviUpiPayment(
|
||||
payNowResponse = internalPayNowResponse,
|
||||
intentUri = intentUri,
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
paymentOrderReferenceId = paymentOrderReferenceId,
|
||||
onboardingDataEntity = onboardingDataEntity,
|
||||
onBeforeOpeningPinPage = onBeforeOpeningPinPage,
|
||||
onPinPageBack = onPinPageBack,
|
||||
onPinPageError = onPinPageError,
|
||||
onPinPageSuccess = onPinPageSuccess,
|
||||
)
|
||||
} else {
|
||||
val genericErrorResponse = payNowResponse.toGenericErrorResponse()
|
||||
paymentProcessorAnalytics.onPayNowChecksFailed(
|
||||
analyticScreenName,
|
||||
transactionReferenceId,
|
||||
paymentOrderReferenceId,
|
||||
intentUri,
|
||||
internalPayNowResponse,
|
||||
genericErrorResponse,
|
||||
)
|
||||
onPayNowFailure(genericErrorResponse)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun startNaviUpiPayment(
|
||||
payNowResponse: InternalPayNowResponse,
|
||||
intentUri: String,
|
||||
transactionReferenceId: String,
|
||||
paymentOrderReferenceId: String,
|
||||
onboardingDataEntity: NaviPayCustomerOnboardingEntity,
|
||||
onBeforeOpeningPinPage: () -> Unit,
|
||||
onPinPageBack: () -> Unit,
|
||||
onPinPageError: (GenericErrorResponse) -> Unit,
|
||||
onPinPageSuccess: suspend (UpiNavigationResponse) -> Unit,
|
||||
) {
|
||||
onBeforeOpeningPinPage()
|
||||
val metaData = Gson().toJson(payNowResponse.providerPayload?.metadata)
|
||||
paymentProcessorAnalytics.onPinPageOpened(
|
||||
screenName = analyticScreenName,
|
||||
naviPayUpiUriKey = intentUri,
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
baseAttributes = baseAttributes,
|
||||
)
|
||||
val transactionTimeStamp = DateTime.now().toString()
|
||||
val pmsSendMoneyStatus =
|
||||
pmsSendMoneyUseCase.performChecksAndGenerateCredBlock(
|
||||
naviPayUpiUriKey = intentUri,
|
||||
screenName = naviPaymentScreen.name,
|
||||
linkedAccountEntity = account,
|
||||
baseAnalyticsParam = baseAttributes,
|
||||
txnTimeStamp = transactionTimeStamp,
|
||||
onboardingDataEntity = onboardingDataEntity,
|
||||
)
|
||||
|
||||
when (pmsSendMoneyStatus) {
|
||||
is PMSSendMoneyStatus.Error -> {
|
||||
val naviPayErrorConfig = pmsSendMoneyStatus.errorConfig
|
||||
var transactionStatus = TransactionStatus.ERROR.name
|
||||
if (naviPayErrorConfig.code == CANCEL) {
|
||||
paymentProcessorAnalytics.onPinPageCancelled(
|
||||
screenName = analyticScreenName,
|
||||
naviPayUpiUriKey = intentUri,
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
baseAttributes = baseAttributes,
|
||||
)
|
||||
onPinPageBack()
|
||||
transactionStatus = TransactionStatus.USER_CANCELLED_TRANSACTION.name
|
||||
} else {
|
||||
paymentProcessorAnalytics.onPinPageError(
|
||||
screenName = analyticScreenName,
|
||||
naviPayUpiUriKey = intentUri,
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
errorCode = naviPayErrorConfig,
|
||||
baseAttributes = baseAttributes,
|
||||
)
|
||||
onPinPageError(naviPayErrorConfig.toGenericError())
|
||||
}
|
||||
notifyNaviUpiExitWithError(
|
||||
status = transactionStatus,
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
error = naviPayErrorConfig,
|
||||
)
|
||||
}
|
||||
is PMSSendMoneyStatus.Success -> {
|
||||
paymentProcessorAnalytics.onPinPageSuccess(
|
||||
screenName = analyticScreenName,
|
||||
naviPayUpiUriKey = intentUri,
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
baseAttributes = baseAttributes,
|
||||
)
|
||||
updateTransactionStatusToPending(transactionReferenceId)
|
||||
val navigationResponse =
|
||||
UpiNavigationResponse(
|
||||
paymentToken = paymentToken,
|
||||
transactionTimestamp = transactionTimeStamp,
|
||||
pmsSendMoneyStatus = pmsSendMoneyStatus,
|
||||
internalPayNowResponse = payNowResponse,
|
||||
metaData = metaData,
|
||||
intentUri = intentUri,
|
||||
tstoreOrderReferenceId =
|
||||
payNowResponse.providerPayload?.tstoreOrderReferenceId.orEmpty(),
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
paymentOrderReferenceId = paymentOrderReferenceId,
|
||||
)
|
||||
onPinPageSuccess(navigationResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyNaviUpiExitWithError(
|
||||
status: String,
|
||||
transactionReferenceId: String,
|
||||
error: NaviPayErrorConfig?,
|
||||
) {
|
||||
CoroutineScope(Dispatchers.IO).safeLaunch {
|
||||
transactionStatusUseCase.updateAndPostTransactionStatus(
|
||||
token = paymentToken,
|
||||
transactionStatusRequest =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
event = error.toJsonObject().toString(),
|
||||
screenType = naviPaymentScreen.name,
|
||||
status = status,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTransactionInfoInDataProvider(
|
||||
transactionReferenceId: String,
|
||||
paymentOrderReferenceId: String,
|
||||
) {
|
||||
paymentDataProvider.add(TRANSACTION_REFERENCE_ID, transactionReferenceId)
|
||||
paymentDataProvider.add(PAYMENT_ORDER_REFERENCE_ID, paymentOrderReferenceId)
|
||||
}
|
||||
|
||||
private fun insertTransactionStatusRequest(transactionReferenceId: String) {
|
||||
CoroutineScope(Dispatchers.IO).safeLaunch {
|
||||
transactionStatusUseCase.insertTransactionStatusRequest(
|
||||
TransactionStatusRequestEntity(
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
token = paymentToken,
|
||||
status = TransactionStatus.INITIATED.name,
|
||||
event = EMPTY,
|
||||
screenType = naviPaymentScreen.name,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTransactionStatusToPending(transactionReferenceId: String) {
|
||||
CoroutineScope(Dispatchers.IO).safeLaunch {
|
||||
transactionStatusUseCase.updateTransactionStatusRequest(
|
||||
transactionStatusRequest =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
status = TransactionStatus.PENDING.name,
|
||||
event = EMPTY,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUpiLiteChecksFailureErrorConfig(): GenericErrorResponse {
|
||||
return GenericErrorResponse(
|
||||
title = resourceProvider.getString(R.string.something_went_wrong),
|
||||
message = resourceProvider.getString(R.string.technical_issue),
|
||||
code = resourceProvider.getString(R.string.no_active_lite_account_psp),
|
||||
logMessage = resourceProvider.getString(R.string.no_active_lite_account_psp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class UpiNavigationResponse(
|
||||
val paymentToken: String,
|
||||
val transactionTimestamp: String,
|
||||
val pmsSendMoneyStatus: PMSSendMoneyStatus.Success,
|
||||
val internalPayNowResponse: InternalPayNowResponse,
|
||||
val intentUri: String,
|
||||
val metaData: String,
|
||||
val tstoreOrderReferenceId: String,
|
||||
val transactionReferenceId: String,
|
||||
val paymentOrderReferenceId: String,
|
||||
)
|
||||
@@ -21,10 +21,10 @@ import com.navi.base.utils.orZero
|
||||
import com.navi.common.checkmate.core.CheckMateManager
|
||||
import com.navi.common.checkmate.model.MetricInfo
|
||||
import com.navi.common.model.ModuleNameV2
|
||||
import com.navi.common.model.RequestConfig
|
||||
import com.navi.common.network.models.GenericErrorResponse
|
||||
import com.navi.common.network.models.RepoResult
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.common.upi.CANCEL
|
||||
import com.navi.common.upi.NAVI_PAY_RESPONSE
|
||||
import com.navi.common.upi.NaviPayAction
|
||||
import com.navi.common.upi.TYPE
|
||||
@@ -32,9 +32,7 @@ import com.navi.common.upi.UpiDataType
|
||||
import com.navi.common.usecase.LitmusExperimentsUseCase
|
||||
import com.navi.common.utils.CommonUtils.getDisplayableAmount
|
||||
import com.navi.common.utils.stringToJsonObject
|
||||
import com.navi.common.utils.toJsonObject
|
||||
import com.navi.pay.common.model.view.CheckBalanceState
|
||||
import com.navi.pay.common.model.view.NaviPayErrorConfig
|
||||
import com.navi.pay.common.model.view.NaviPayFlowType
|
||||
import com.navi.pay.common.setup.NaviPayManager
|
||||
import com.navi.pay.common.usecase.AccountListCheckBalanceUseCase
|
||||
@@ -60,32 +58,30 @@ import com.navi.payment.nativepayment.NaviPaymentAnalytics
|
||||
import com.navi.payment.nativepayment.activity.NaviPaymentActivity
|
||||
import com.navi.payment.nativepayment.common.usecase.TransactionStatusUseCase
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.PAYMENT_ORDER_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.TRANSACTION_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.UPI_LITE_MAX_PAYABLE_AMOUNT_PER_TRANSACTION
|
||||
import com.navi.payment.nativepayment.dataprovider.PinAction
|
||||
import com.navi.payment.nativepayment.dataprovider.getMpinResetAction
|
||||
import com.navi.payment.nativepayment.dataprovider.getMpinSetAction
|
||||
import com.navi.payment.nativepayment.db.model.TransactionStatusRequestEntity
|
||||
import com.navi.payment.nativepayment.model.BasePaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.BasePaymentMethodResponse
|
||||
import com.navi.payment.nativepayment.model.CoinDetails
|
||||
import com.navi.payment.nativepayment.model.CoinRewards
|
||||
import com.navi.payment.nativepayment.model.LoaderConfig
|
||||
import com.navi.payment.nativepayment.model.MPSBottomSheetStateHolder
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.OnboardingDetails
|
||||
import com.navi.payment.nativepayment.model.PMSLinkedAccountEntity
|
||||
import com.navi.payment.nativepayment.model.PMSSendMoneyStatus
|
||||
import com.navi.payment.nativepayment.model.PaymentsMainCtaState
|
||||
import com.navi.payment.nativepayment.model.RewardsInfoV2
|
||||
import com.navi.payment.nativepayment.model.S2sPaymentMethodResponse
|
||||
import com.navi.payment.nativepayment.model.UpiLinkedAccountPaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatus
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatusRequest
|
||||
import com.navi.payment.nativepayment.presentation.reducer.MPSScreenEffect
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.screens.destinations.TransactionPollingScreenDestination
|
||||
import com.navi.payment.nativepayment.usecase.NaviUpiPaymentProcessor
|
||||
import com.navi.payment.nativepayment.usecase.PmsLinkedAccountUseCase
|
||||
import com.navi.payment.nativepayment.usecase.PmsSendMoneyUseCase
|
||||
import com.navi.payment.nativepayment.usecase.UpiNavigationResponse
|
||||
import com.navi.payment.nativepayment.utils.MPSScreenUtils
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentErrorConfig
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentEventHandler
|
||||
@@ -99,11 +95,11 @@ import com.navi.payment.nativepayment.utils.getLastSelectedAccountBeforeAccounts
|
||||
import com.navi.payment.nativepayment.utils.getPayloadBasedOnType
|
||||
import com.navi.payment.nativepayment.utils.mapToLinkedAccountEntity
|
||||
import com.navi.payment.nativepayment.utils.rankUpiAccountsByEligibility
|
||||
import com.navi.payment.nativepayment.utils.toGenericError
|
||||
import com.navi.payment.nativepayment.utils.toGenericErrorResponse
|
||||
import com.navi.payment.nativepayment.utils.toPaymentNaviPaymentErrorConfig
|
||||
import com.navi.payment.network.util.PaymentsSdkRetrofit
|
||||
import com.navi.payment.paymentscreen.model.InternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.NaviPayProcessPayload
|
||||
import com.navi.payment.paymentscreen.model.NaviUpiTransactionInfo
|
||||
import com.navi.payment.paymentscreen.model.PMSErrorReason
|
||||
import com.navi.payment.paymentscreen.model.PayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.PaymentErrorData
|
||||
@@ -121,7 +117,6 @@ import com.navi.payment.utils.getArcNudgeBottomSheetSubtitle
|
||||
import com.navi.payment.utils.getArcNudgeBottomSheetTitle
|
||||
import com.navi.payment.utils.getInstalledUpiApps
|
||||
import com.navi.payment.utils.getPMSMetricInfo
|
||||
import com.navi.payment.utils.isUpiLiteAccount
|
||||
import com.navi.payment.utils.requireTpvSupport
|
||||
import com.navi.payment.utils.roundTo
|
||||
import com.navi.payment.utils.validateUpiProcessPayload
|
||||
@@ -131,13 +126,15 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.joda.time.DateTime
|
||||
|
||||
@HiltViewModel
|
||||
class MPSViewModel
|
||||
@@ -155,8 +152,8 @@ constructor(
|
||||
private val transactionStatusUseCase: TransactionStatusUseCase,
|
||||
private val accountListCheckBalanceUseCase: AccountListCheckBalanceUseCase,
|
||||
private val arcNudgeUseCase: ArcNudgeUseCase,
|
||||
private val pmsSendMoneyUseCase: PmsSendMoneyUseCase,
|
||||
private val naviPayPspManager: NaviPayPspManager,
|
||||
private val naviUpiPaymentProcessor: NaviUpiPaymentProcessor,
|
||||
@PaymentsSdkRetrofit private val deserializer: Gson,
|
||||
) :
|
||||
NaviPaymentBaseVM(
|
||||
@@ -230,11 +227,9 @@ constructor(
|
||||
var paymentSdkInitParams: PaymentSdkInitParams? = null
|
||||
var addAccountType: List<String>? = null
|
||||
|
||||
private val _pmsSendMoneyStatus = MutableStateFlow<PMSSendMoneyStatus?>(null)
|
||||
val pmsSendMoneyStatus = _pmsSendMoneyStatus.asStateFlow()
|
||||
|
||||
var loaderConfig: LoaderConfig? = null
|
||||
var txnTimeStamp: String = EMPTY
|
||||
private val _effect = MutableSharedFlow<MPSScreenEffect>()
|
||||
val effect: SharedFlow<MPSScreenEffect>
|
||||
get() = _effect.asSharedFlow()
|
||||
|
||||
private val _bottomSheetStateHolder =
|
||||
MutableStateFlow(
|
||||
@@ -328,7 +323,6 @@ constructor(
|
||||
methodDetails.paymentOrderRefId.orEmpty(),
|
||||
)
|
||||
updatePaymentAmount(methodDetails.amount?.value.orZero())
|
||||
updateLottieConfig(methodDetails.loaderConfig)
|
||||
if (paymentSdkInitParams?.rewardsInfo?.isEnabled.orFalse()) {
|
||||
getRewardInfoV2()
|
||||
} else {
|
||||
@@ -343,10 +337,6 @@ constructor(
|
||||
_paymentAmount.update { amount }
|
||||
}
|
||||
|
||||
private fun updateLottieConfig(loaderConfig: LoaderConfig?) {
|
||||
this.loaderConfig = loaderConfig
|
||||
}
|
||||
|
||||
private suspend fun processAvailablePaymentMethods(
|
||||
availablePaymentMethods: List<BasePaymentInstrument>
|
||||
) {
|
||||
@@ -532,102 +522,6 @@ constructor(
|
||||
_mainCtaState.update { mainCtaState }
|
||||
}
|
||||
|
||||
private fun startPayAmount(onboardingDataEntity: NaviPayCustomerOnboardingEntity) =
|
||||
viewModelScope.launch {
|
||||
if (showPayNowLoader.value) return@launch
|
||||
_showPayNowLoader.update { true }
|
||||
val response = fetchPayNowResponse()
|
||||
if (response.isSuccessWithData()) {
|
||||
paymentDataProvider.add(
|
||||
TRANSACTION_REFERENCE_ID,
|
||||
response.data?.transactionReferenceId.orEmpty(),
|
||||
)
|
||||
paymentDataProvider.add(
|
||||
PAYMENT_ORDER_REFERENCE_ID,
|
||||
response.data?.paymentOrderReferenceId.orEmpty(),
|
||||
)
|
||||
response.data?.transactionReferenceId?.let { transactionReferenceId ->
|
||||
insertTransactionStatusRequest(
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
token = paymentSdkInitParams?.token.orEmpty(),
|
||||
screenType = NaviPaymentScreenType.MINI_PAYMENT_SCREEN.name,
|
||||
event = EMPTY,
|
||||
status = TransactionStatus.INITIATED.name,
|
||||
)
|
||||
}
|
||||
payNowResponse = response.data
|
||||
(response.data as? InternalPayNowResponse)?.let {
|
||||
startNaviUpiPayment(payNowResponse = it, onboardingDataEntity)
|
||||
}
|
||||
} else {
|
||||
val errorResponse = response.toGenericErrorResponse()
|
||||
updateBottomSheetUIState(
|
||||
showBottomSheet = true,
|
||||
bottomSheetUIState =
|
||||
MPSScreenUtils.MPSScreenType.Error(
|
||||
errorData =
|
||||
PaymentErrorData(
|
||||
error = errorResponse,
|
||||
errorReason = PMSErrorReason.PayNowError,
|
||||
)
|
||||
),
|
||||
bottomSheetStateChange = true,
|
||||
)
|
||||
}
|
||||
_showPayNowLoader.update { false }
|
||||
}
|
||||
|
||||
private suspend fun fetchPayNowResponse() =
|
||||
paymentRepository.postPayNow(
|
||||
token = paymentSdkInitParams?.token,
|
||||
data =
|
||||
PayAmountRequest(
|
||||
methodName = UpiLinkedAccountPaymentInstrument.PAYMENT_INSTRUMENT_TYPE,
|
||||
selectedMethodDetails =
|
||||
PayAmountRequest.SelectedMethodDetails(
|
||||
payerBankAccountId = selectedBankAccount.value?.accountId,
|
||||
accountType = selectedBankAccount.value?.accountType,
|
||||
),
|
||||
discountInfo =
|
||||
if (isDiscountApplied.value) {
|
||||
listOf(
|
||||
PayAmountRequest.DiscountInfo(
|
||||
type = PayAmountRequest.DiscountType.COIN.name,
|
||||
amount =
|
||||
if (rewardsInfoV2.value.isNull())
|
||||
coinBurnDetails.value?.redeemableCoinsValue
|
||||
else rewardsInfoV2.value?.burnDetails?.coinsValue,
|
||||
discountMetadata =
|
||||
PayAmountRequest.DiscountMetadata(
|
||||
coinsUsed =
|
||||
if (rewardsInfoV2.value.isNull())
|
||||
coinBurnDetails.value?.redeemableCoins
|
||||
else {
|
||||
val coins =
|
||||
rewardsInfoV2.value?.burnDetails?.coins
|
||||
val coinValue =
|
||||
coins
|
||||
?.replace(",", "")
|
||||
?.toIntOrNull()
|
||||
.orZero()
|
||||
coinValue
|
||||
}
|
||||
),
|
||||
)
|
||||
)
|
||||
} else null,
|
||||
),
|
||||
metricInfo =
|
||||
getPMSMetricInfo(
|
||||
screenName = NaviPaymentAnalyticScreenName.MINI_PAYMENT_SCREEN.screenName
|
||||
),
|
||||
)
|
||||
|
||||
fun onNaviPayCallBack() {
|
||||
payNowResponse = null
|
||||
_pmsSendMoneyStatus.update { null }
|
||||
}
|
||||
|
||||
private suspend fun updateSDKInitParams() {
|
||||
paymentSdkInitParams = paymentDataProvider.getSdkInitParams()
|
||||
paymentDataProvider.updateAnalyticsParams(
|
||||
@@ -829,44 +723,6 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyNaviUpiExitWithError(status: String, error: NaviPayErrorConfig?) {
|
||||
coroutineScope.safeLaunch(Dispatchers.IO) {
|
||||
paymentSdkInitParams?.token?.let {
|
||||
transactionStatusUseCase.updateAndPostTransactionStatus(
|
||||
token = it,
|
||||
transactionStatusRequest =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId =
|
||||
paymentDataProvider.get(TRANSACTION_REFERENCE_ID).toString(),
|
||||
event = error.toJsonObject().toString(),
|
||||
screenType = NaviPaymentScreenType.MINI_PAYMENT_SCREEN.name,
|
||||
status = status,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun insertTransactionStatusRequest(
|
||||
transactionReferenceId: String,
|
||||
token: String,
|
||||
event: String,
|
||||
screenType: String,
|
||||
status: String,
|
||||
) {
|
||||
coroutineScope.safeLaunch(Dispatchers.IO) {
|
||||
transactionStatusUseCase.insertTransactionStatusRequest(
|
||||
TransactionStatusRequestEntity(
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
token = token,
|
||||
status = status,
|
||||
event = event,
|
||||
screenType = screenType,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateFeedbackOptions(option: String) {
|
||||
if (feedBackOptions.value.contains(option)) {
|
||||
_feedBackOptions.update { it.minus(option) }
|
||||
@@ -902,10 +758,6 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun isUserOnboardedForAnyPsp(): Boolean {
|
||||
return naviPayManager.isUserOnboardedForAnyPsp()
|
||||
}
|
||||
|
||||
fun onDiscountClicked(isDiscountApplied: Boolean) {
|
||||
viewModelScope.launch(Dispatchers.Default) {
|
||||
_isDiscountApplied.update { isDiscountApplied }
|
||||
@@ -991,12 +843,16 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun updateCheckBalanceAccountId(accountId: String) {
|
||||
private fun updateCheckBalanceAccountId(accountId: String) {
|
||||
_checkBalanceAccountId.update { accountId }
|
||||
}
|
||||
|
||||
fun updateShowPayNowLoader(show: Boolean) {
|
||||
_showPayNowLoader.update { show }
|
||||
private fun showPayNowLoader() {
|
||||
_showPayNowLoader.update { true }
|
||||
}
|
||||
|
||||
private fun stopPayNowLoader() {
|
||||
_showPayNowLoader.update { false }
|
||||
}
|
||||
|
||||
fun onArcNudgeClicked() {
|
||||
@@ -1056,69 +912,6 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun startNaviUpiPayment(
|
||||
payNowResponse: InternalPayNowResponse,
|
||||
onboardingDataEntity: NaviPayCustomerOnboardingEntity,
|
||||
) {
|
||||
val payLoad = payNowResponse.providerPayload
|
||||
naviPaymentAnalytics.onRedirectionToPinPage(
|
||||
naviPayUpiUriKey = payLoad?.naviPayUpiUriKey.orEmpty(),
|
||||
transactionReferenceId = payNowResponse.transactionReferenceId.orEmpty(),
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
)
|
||||
txnTimeStamp = DateTime.now().toString()
|
||||
val pmsSendMoneyStatus =
|
||||
pmsSendMoneyUseCase.performChecksAndGenerateCredBlock(
|
||||
naviPayUpiUriKey = payLoad?.naviPayUpiUriKey.orEmpty(),
|
||||
linkedAccountEntity = selectedBankAccount.value,
|
||||
screenName = NaviPaymentScreenType.MINI_PAYMENT_SCREEN.name,
|
||||
baseAnalyticsParam = getAnalyticsParams(),
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
onboardingDataEntity = onboardingDataEntity,
|
||||
)
|
||||
when (pmsSendMoneyStatus) {
|
||||
is PMSSendMoneyStatus.Error -> {
|
||||
var transactionStatus = TransactionStatus.ERROR.name
|
||||
val errorConfig = pmsSendMoneyStatus.errorConfig
|
||||
if (errorConfig.code == CANCEL) {
|
||||
transactionStatus = TransactionStatus.USER_CANCELLED_TRANSACTION.name
|
||||
updateShowPayNowLoader(false)
|
||||
updateBottomSheetUIState(true)
|
||||
} else {
|
||||
updateBottomSheetUIState(
|
||||
showBottomSheet = true,
|
||||
bottomSheetUIState =
|
||||
MPSScreenUtils.MPSScreenType.Error(
|
||||
PaymentErrorData(
|
||||
error = errorConfig.toGenericError(),
|
||||
errorReason = PMSErrorReason.UPIError,
|
||||
)
|
||||
),
|
||||
bottomSheetStateChange = true,
|
||||
)
|
||||
}
|
||||
notifyNaviUpiExitWithError(
|
||||
status = transactionStatus,
|
||||
error = pmsSendMoneyStatus.errorConfig,
|
||||
)
|
||||
}
|
||||
is PMSSendMoneyStatus.Success -> {
|
||||
bottomSheetPreSendMoneyState = bottomSheetStateHolder.value
|
||||
transactionStatusUseCase.updateTransactionStatusRequest(
|
||||
transactionStatusRequest =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId =
|
||||
payNowResponse.transactionReferenceId.orEmpty(),
|
||||
event = EMPTY,
|
||||
screenType = NaviPaymentScreenType.MINI_PAYMENT_SCREEN.name,
|
||||
status = TransactionStatus.PENDING.name,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
_pmsSendMoneyStatus.update { pmsSendMoneyStatus }
|
||||
}
|
||||
|
||||
private fun getRewardInfoV2() {
|
||||
naviPaymentAnalytics.onOfferExperienceBannerShown(
|
||||
rewardsInfoV2 = paymentSdkInitParams?.rewardsInfo,
|
||||
@@ -1179,15 +972,54 @@ constructor(
|
||||
upiResultLauncher: ManagedActivityResultLauncher<Intent, ActivityResult>,
|
||||
) {
|
||||
val selectedBankAccountValue = selectedBankAccount.value ?: return
|
||||
if (showPayNowLoader.value) return
|
||||
when {
|
||||
selectedBankAccountValue.isUpiLiteAccount() ->
|
||||
processUpiLitePayment(selectedBankAccountValue)
|
||||
selectedBankAccountValue.isMPinSet.not() ->
|
||||
handleMPinSetup(selectedBankAccountValue, naviPaymentActivity, upiResultLauncher)
|
||||
else -> processNonUpiLitePayment(selectedBankAccountValue)
|
||||
else -> makePayment(selectedBankAccountValue)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun makePayment(selectedBankAccountValue: LinkedAccountEntity) {
|
||||
showPayNowLoader()
|
||||
naviUpiPaymentProcessor.makePayment(
|
||||
account = selectedBankAccountValue,
|
||||
isDiscountApplied = isDiscountApplied.value,
|
||||
discountInfo = createDiscountInfo(),
|
||||
analyticScreenName = NaviPaymentAnalyticScreenName.MINI_PAYMENT_SCREEN.screenName,
|
||||
naviPaymentScreen = NaviPaymentScreenType.MINI_PAYMENT_SCREEN,
|
||||
paymentToken = paymentSdkInitParams?.token.orEmpty(),
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
onInitialChecksFailure = { showErrorState(PaymentErrorData(error = it)) },
|
||||
onOnboardingTriggered = { updateBottomSheetUIState(showBottomSheet = false) },
|
||||
onOnboardingCancelled = {
|
||||
stopPayNowLoader()
|
||||
updateBottomSheetUIState(showBottomSheet = true)
|
||||
},
|
||||
onOnboardingCompleted = { updateBottomSheetUIState(showBottomSheet = true) },
|
||||
onBeforePayNowApiCall = {},
|
||||
onPayNowSuccess = { payNowResponse = it },
|
||||
onPayNowFailure = {
|
||||
stopPayNowLoader()
|
||||
showErrorState(
|
||||
PaymentErrorData(error = it, errorReason = PMSErrorReason.PayNowError)
|
||||
)
|
||||
},
|
||||
onBeforeOpeningPinPage = {},
|
||||
onPinPageBack = {
|
||||
stopPayNowLoader()
|
||||
updateBottomSheetUIState(true)
|
||||
},
|
||||
onPinPageError = {
|
||||
stopPayNowLoader()
|
||||
showErrorState(
|
||||
PaymentErrorData(error = it, errorReason = PMSErrorReason.PayNowError)
|
||||
)
|
||||
},
|
||||
onPinPageSuccess = { onPinPageSuccess(selectedBankAccountValue, it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun handleMPinSetup(
|
||||
selectedBankAccountValue: LinkedAccountEntity,
|
||||
naviPaymentActivity: NaviPaymentActivity,
|
||||
@@ -1250,72 +1082,6 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processNonUpiLitePayment(selectedBankAccountValue: LinkedAccountEntity) {
|
||||
naviPaymentAnalytics.onNonUpiLitePayment(
|
||||
isDiscountApplied = isDiscountApplied.value.toString(),
|
||||
accountId = selectedBankAccountValue.accountId,
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
)
|
||||
pspManagerAnalytics.onSendMoneyWithPspManager(
|
||||
accountId = selectedBankAccountValue.accountId,
|
||||
isPaymentFromLiteAccount = false,
|
||||
screenName = screenName,
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForFlow(
|
||||
naviPayFlowType =
|
||||
NaviPayFlowType.getSendMoneyFlowForAccountType(
|
||||
selectedBankAccountValue.accountType
|
||||
),
|
||||
vpaEntityList = selectedBankAccountValue.vpaEntityList,
|
||||
screenName = screenName,
|
||||
onOnboardingTriggered = { updateBottomSheetUIState(showBottomSheet = false) },
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, screenName = screenName)
|
||||
if (pspEvaluationResult.isOnboardingTriggered) {
|
||||
updateBottomSheetUIState(showBottomSheet = true)
|
||||
}
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
onPspEvaluatedForPayment(onboardingEntity = onboardingEntity)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun processUpiLitePayment(selectedBankAccountValue: LinkedAccountEntity) {
|
||||
if (selectedBankAccountValue.activeLiteAccountPsp == null) {
|
||||
showErrorState(PaymentErrorData())
|
||||
CheckMateManager.logAppErrorEvent(
|
||||
metricInfo = MetricInfo.PMSMetric<Any>(screen = screenName),
|
||||
errorCode = resourceProvider.getString(R.string.no_active_lite_account_psp),
|
||||
errorTitle = resourceProvider.getString(R.string.something_went_wrong),
|
||||
errorDes = resourceProvider.getString(R.string.technical_issue),
|
||||
)
|
||||
return
|
||||
}
|
||||
val vpaEntityForLiteAccount =
|
||||
selectedBankAccountValue.getVpaEntityByPsp(
|
||||
selectedBankAccountValue.activeLiteAccountPsp ?: return
|
||||
)
|
||||
naviPaymentAnalytics.onUpiLitePayment(
|
||||
isDiscountApplied = isDiscountApplied.value.toString(),
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForVpa(
|
||||
vpaEntity = vpaEntityForLiteAccount,
|
||||
screenName = screenName,
|
||||
onOnboardingTriggered = { updateBottomSheetUIState(showBottomSheet = false) },
|
||||
naviPayFlowType = NaviPayFlowType.UPI_LITE,
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
if (pspEvaluationResult.isOnboardingTriggered) {
|
||||
updateBottomSheetUIState(showBottomSheet = true)
|
||||
}
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
onPspEvaluatedForPayment(onboardingEntity = onboardingEntity)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun handleAccountAdditionFlow(addAccountButtonClicked: Boolean = false) {
|
||||
viewModelScope.launch {
|
||||
val enabledAccountTypes = getEnabledAccountTypes()
|
||||
@@ -1437,10 +1203,6 @@ constructor(
|
||||
|
||||
private fun isCheckBalanceInProgress(): Boolean = checkBalanceAccountId.value.isNotEmpty()
|
||||
|
||||
private fun onPspEvaluatedForPayment(onboardingEntity: NaviPayCustomerOnboardingEntity) {
|
||||
startPayAmount(onboardingEntity)
|
||||
}
|
||||
|
||||
private suspend fun onPspEvaluatedForCheckBalance(
|
||||
accountId: String,
|
||||
linkedAccount: LinkedAccountEntity,
|
||||
@@ -1579,4 +1341,77 @@ constructor(
|
||||
bottomSheetStateChange = true,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun onPinPageSuccess(
|
||||
account: LinkedAccountEntity,
|
||||
upiNavigationResponse: UpiNavigationResponse,
|
||||
) {
|
||||
bottomSheetPreSendMoneyState = bottomSheetStateHolder.value
|
||||
val payload = (payNowResponse?.providerPayload) as? NaviPayProcessPayload
|
||||
_effect.emit(
|
||||
MPSScreenEffect.Navigation(
|
||||
direction =
|
||||
TransactionPollingScreenDestination(
|
||||
token = upiNavigationResponse.paymentToken,
|
||||
paymentAmount = paymentAmount.value,
|
||||
redeemedCoinsValue =
|
||||
if (isDiscountApplied.value)
|
||||
if (rewardsInfoV2.isNull())
|
||||
coinBurnDetails.value?.redeemableCoinsValue?.value.orZero()
|
||||
else rewardsInfoV2.value?.burnDetails?.coinsValue?.value.orZero()
|
||||
else 0.0,
|
||||
source = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
tstoreOrderReferenceId = upiNavigationResponse.tstoreOrderReferenceId,
|
||||
sourceDestination = NaviPaymentScreenType.MINI_PAYMENT_SCREEN.name,
|
||||
pollingConfiguration =
|
||||
payNowResponse?.pollingConfiguration ?: RequestConfig(),
|
||||
request =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId =
|
||||
upiNavigationResponse.transactionReferenceId,
|
||||
screenType = NaviPaymentScreenType.MINI_PAYMENT_SCREEN.name,
|
||||
),
|
||||
naviUpiTransactionInfo =
|
||||
NaviUpiTransactionInfo(
|
||||
naviPayUpiUriKey = upiNavigationResponse.intentUri,
|
||||
upiRequestId =
|
||||
upiNavigationResponse.pmsSendMoneyStatus.upiRequestId,
|
||||
selectedBankAccountId = account.accountId,
|
||||
credBlock = upiNavigationResponse.pmsSendMoneyStatus.credBlock,
|
||||
metaData = Gson().toJson(payload?.metadata),
|
||||
txnTimeStamp = upiNavigationResponse.transactionTimestamp,
|
||||
isArcProtected = account.isArcProtected.orFalse(),
|
||||
onboardingDataEntity =
|
||||
upiNavigationResponse.pmsSendMoneyStatus.onboardingDataEntity,
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
payNowResponse = null
|
||||
}
|
||||
|
||||
private fun createDiscountInfo(): List<PayAmountRequest.DiscountInfo>? {
|
||||
return if (isDiscountApplied.value) {
|
||||
listOf(
|
||||
PayAmountRequest.DiscountInfo(
|
||||
type = PayAmountRequest.DiscountType.COIN.name,
|
||||
amount =
|
||||
if (rewardsInfoV2.value.isNull())
|
||||
coinBurnDetails.value?.redeemableCoinsValue
|
||||
else rewardsInfoV2.value?.burnDetails?.coinsValue,
|
||||
discountMetadata =
|
||||
PayAmountRequest.DiscountMetadata(
|
||||
coinsUsed =
|
||||
if (rewardsInfoV2.value.isNull())
|
||||
coinBurnDetails.value?.redeemableCoins
|
||||
else {
|
||||
val coins = rewardsInfoV2.value?.burnDetails?.coins
|
||||
val coinValue = coins?.replace(",", "")?.toIntOrNull().orZero()
|
||||
coinValue
|
||||
}
|
||||
),
|
||||
)
|
||||
)
|
||||
} else null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ import com.navi.base.utils.orElse
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orTrue
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.network.models.GenericErrorResponse
|
||||
import com.navi.common.network.models.RepoResult
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.common.upi.CANCEL
|
||||
import com.navi.common.upi.NAVI_PAY_RESPONSE
|
||||
import com.navi.common.upi.NaviPayAction
|
||||
import com.navi.common.upi.TYPE
|
||||
@@ -34,7 +34,6 @@ import com.navi.common.usecase.LitmusExperimentsUseCase
|
||||
import com.navi.common.utils.CommonUtils.getDisplayableAmount
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.common.utils.stringToJsonObject
|
||||
import com.navi.common.utils.toJsonObject
|
||||
import com.navi.pay.common.model.view.NaviPayFlowType
|
||||
import com.navi.pay.common.setup.NaviPayManager
|
||||
import com.navi.pay.common.usecase.AccountListCheckBalanceUseCase
|
||||
@@ -44,7 +43,6 @@ import com.navi.pay.common.usecase.NaviPayConfigUseCase
|
||||
import com.navi.pay.management.common.sendmoney.model.view.BankAccountsState
|
||||
import com.navi.pay.management.common.utils.NaviPayPspManager
|
||||
import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
|
||||
import com.navi.pay.onboarding.binding.model.view.NaviPayCustomerOnboardingEntity
|
||||
import com.navi.pay.utils.ALL_ENABLED_ACCOUNTS
|
||||
import com.navi.pay.utils.LITE_MAX_SEND_MONEY
|
||||
import com.navi.pay.utils.NAVI_PAY_PURPLE_CTA_LOADER_LOTTIE
|
||||
@@ -73,7 +71,6 @@ import com.navi.payment.nativepayment.model.FomoBottomSheetCtaAction
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.NetBankingPaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.NetBankingPaymentInstumentDetails
|
||||
import com.navi.payment.nativepayment.model.PMSSendMoneyStatus
|
||||
import com.navi.payment.nativepayment.model.PaymentsMainCtaState
|
||||
import com.navi.payment.nativepayment.model.RewardsInfoV2
|
||||
import com.navi.payment.nativepayment.model.S2sPaymentMethodResponse
|
||||
@@ -96,9 +93,10 @@ import com.navi.payment.nativepayment.presentation.reducer.NaviUpiPaymentState
|
||||
import com.navi.payment.nativepayment.presentation.reducer.NetbankingDetails
|
||||
import com.navi.payment.nativepayment.presentation.reducer.UpiCollectOptionState
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.usecase.NaviUpiPaymentProcessor
|
||||
import com.navi.payment.nativepayment.usecase.NetBankingUseCase
|
||||
import com.navi.payment.nativepayment.usecase.PmsLinkedAccountUseCase
|
||||
import com.navi.payment.nativepayment.usecase.PmsSendMoneyUseCase
|
||||
import com.navi.payment.nativepayment.usecase.UpiNavigationResponse
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentEventHandler
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentRewardsEventBus
|
||||
import com.navi.payment.nativepayment.utils.PaymentRewardsEvent
|
||||
@@ -109,13 +107,11 @@ import com.navi.payment.nativepayment.utils.getLastSelectedAccountBeforeAccounts
|
||||
import com.navi.payment.nativepayment.utils.getPayloadBasedOnType
|
||||
import com.navi.payment.nativepayment.utils.mapToLinkedAccountEntity
|
||||
import com.navi.payment.nativepayment.utils.rankUpiAccountsByEligibility
|
||||
import com.navi.payment.nativepayment.utils.toGenericError
|
||||
import com.navi.payment.nativepayment.utils.toGenericErrorResponse
|
||||
import com.navi.payment.nativepayment.utils.toPaymentNaviPaymentErrorConfig
|
||||
import com.navi.payment.network.util.PaymentsSdkRetrofit
|
||||
import com.navi.payment.paymentscreen.model.ExternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.IntentUriPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.InternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.NaviUpiTransactionInfo
|
||||
import com.navi.payment.paymentscreen.model.PMSErrorReason
|
||||
import com.navi.payment.paymentscreen.model.PayNowResponse
|
||||
@@ -125,7 +121,6 @@ import com.navi.payment.turbocheckout.model.PayNowRequest
|
||||
import com.navi.payment.turbocheckout.model.SelectedMethodDetails
|
||||
import com.navi.payment.turbocheckout.model.UpiCollectPayNowRequest
|
||||
import com.navi.payment.turbocheckout.model.UpiIntentPayNowRequest
|
||||
import com.navi.payment.turbocheckout.model.UpiPayNowRequest
|
||||
import com.navi.payment.utils.Constants
|
||||
import com.navi.payment.utils.Constants.COIN_DISCOUNT_APPLY_DELAY
|
||||
import com.navi.payment.utils.Constants.SCREEN_TRANSITION_DURATION_IN_MILLIS
|
||||
@@ -153,7 +148,6 @@ import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.joda.time.DateTime
|
||||
import org.json.JSONObject
|
||||
|
||||
@HiltViewModel
|
||||
@@ -170,12 +164,12 @@ constructor(
|
||||
private val naviPayManager: NaviPayManager,
|
||||
@PaymentsSdkRetrofit private val deserializer: Gson,
|
||||
private val paymentEventHandler: NaviPaymentEventHandler,
|
||||
private val pmsSendMoneyUseCase: PmsSendMoneyUseCase,
|
||||
private val arcNudgeUseCase: ArcNudgeUseCase,
|
||||
private val naviPaymentRewardsEventBus: NaviPaymentRewardsEventBus,
|
||||
private val netBankingUseCase: NetBankingUseCase,
|
||||
private val accountListCheckBalanceUseCase: AccountListCheckBalanceUseCase,
|
||||
private val naviPayPspManager: NaviPayPspManager,
|
||||
private val naviUpiPaymentProcessor: NaviUpiPaymentProcessor,
|
||||
) :
|
||||
NPSBaseViewModel(
|
||||
paymentRepository = paymentRepository,
|
||||
@@ -1020,10 +1014,7 @@ constructor(
|
||||
submitPayNowRequest(payNowRequest)
|
||||
}
|
||||
|
||||
private fun handlePayNowResponse(
|
||||
response: RepoResult<PayNowResponse>,
|
||||
onboardingEntity: NaviPayCustomerOnboardingEntity? = null,
|
||||
) {
|
||||
private fun handlePayNowResponse(response: RepoResult<PayNowResponse>) {
|
||||
viewModelScope.launch {
|
||||
if (response.isSuccessWithData()) {
|
||||
paymentDataProvider.add(
|
||||
@@ -1040,7 +1031,6 @@ constructor(
|
||||
transactionReferenceId = it,
|
||||
token = paymentSdkInitParams?.token.orEmpty(),
|
||||
screenType = NaviPaymentScreenType.FULL_PAYMENT_SCREEN.name,
|
||||
event = EMPTY,
|
||||
status = TransactionStatus.INITIATED.name,
|
||||
)
|
||||
}
|
||||
@@ -1060,9 +1050,6 @@ constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
is InternalPayNowResponse -> {
|
||||
startNaviUpiPayment(responseData, onboardingEntity)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
showLoader(false)
|
||||
@@ -1282,7 +1269,6 @@ constructor(
|
||||
private fun insertTransactionStatusRequest(
|
||||
transactionReferenceId: String,
|
||||
token: String,
|
||||
event: String,
|
||||
screenType: String,
|
||||
status: String,
|
||||
) {
|
||||
@@ -1292,7 +1278,7 @@ constructor(
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
token = token,
|
||||
status = status,
|
||||
event = event,
|
||||
event = EMPTY,
|
||||
screenType = screenType,
|
||||
)
|
||||
)
|
||||
@@ -1445,79 +1431,6 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun startNaviUpiPayment(
|
||||
payNowResponse: InternalPayNowResponse,
|
||||
onboardingEntity: NaviPayCustomerOnboardingEntity? = null,
|
||||
) {
|
||||
updateBottomSheetUIState(false)
|
||||
if (onboardingEntity == null) {
|
||||
pspManagerAnalytics.onNaviPayOnboardingEntityNotInitialised(screenName)
|
||||
return
|
||||
}
|
||||
|
||||
val payload = (payNowResponse.providerPayload)
|
||||
val txnTimeStamp = DateTime.now().toString()
|
||||
val pmsSendMoneyStatus =
|
||||
pmsSendMoneyUseCase.performChecksAndGenerateCredBlock(
|
||||
naviPayUpiUriKey = payload?.naviPayUpiUriKey.orEmpty(),
|
||||
screenName = NaviPaymentScreenType.FULL_PAYMENT_SCREEN.name,
|
||||
linkedAccountEntity = npsScreenState.naviUpiPaymentState.selectedBankAccount,
|
||||
baseAnalyticsParam = baseAnalyticsParams,
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
onboardingDataEntity = onboardingEntity,
|
||||
)
|
||||
when (pmsSendMoneyStatus) {
|
||||
is PMSSendMoneyStatus.Error -> {
|
||||
val errorConfig = (pmsSendMoneyStatus as? PMSSendMoneyStatus.Error)?.errorConfig
|
||||
var transactionStatus = TransactionStatus.ERROR.name
|
||||
if (errorConfig?.code == CANCEL) {
|
||||
transactionStatus = TransactionStatus.USER_CANCELLED_TRANSACTION.name
|
||||
} else {
|
||||
handleError(
|
||||
genericErrorResponse = errorConfig?.toGenericError(),
|
||||
errorReason = PMSErrorReason.UPIError,
|
||||
)
|
||||
}
|
||||
notifySdkExitWithError(transactionStatus, errorConfig.toJsonObject().toString())
|
||||
}
|
||||
is PMSSendMoneyStatus.Success -> {
|
||||
if (
|
||||
paymentSdkInitParams?.token.isNotNullAndNotEmpty() &&
|
||||
payNowResponse.transactionReferenceId.isNotNullAndNotEmpty()
|
||||
) {
|
||||
updateTransactionStatusToPending(payNowResponse.transactionReferenceId)
|
||||
_effect.emit(
|
||||
NPSBaseContract.Effect.NavigateToLoaderScreen(
|
||||
token = paymentSdkInitParams?.token.orEmpty(),
|
||||
paymentAmount = npsScreenState.npsBaseState.paymentAmount,
|
||||
source = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
tstoreOrderReferenceId = payload?.tstoreOrderReferenceId.orEmpty(),
|
||||
payNowResponse = payNowResponse,
|
||||
naviUpiTransactionInfo =
|
||||
NaviUpiTransactionInfo(
|
||||
selectedBankAccountId =
|
||||
npsScreenState.naviUpiPaymentState.selectedBankAccount
|
||||
?.accountId
|
||||
.orEmpty(),
|
||||
credBlock = pmsSendMoneyStatus.credBlock.orEmpty(),
|
||||
upiRequestId = pmsSendMoneyStatus.upiRequestId,
|
||||
naviPayUpiUriKey = payload?.naviPayUpiUriKey,
|
||||
metaData = Gson().toJson(payload?.metadata),
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
isArcProtected =
|
||||
npsScreenState.naviUpiPaymentState.selectedBankAccount
|
||||
?.isArcProtected
|
||||
.orFalse(),
|
||||
onboardingDataEntity = onboardingEntity,
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
showLoader(false)
|
||||
}
|
||||
|
||||
private fun handleArcNudgeClicked() {
|
||||
viewModelScope.safeLaunch {
|
||||
naviPaymentAnalytics.onArcNudgeClicked()
|
||||
@@ -1629,18 +1542,6 @@ constructor(
|
||||
npsScreenState.naviUpiPaymentState.showOnboardingCard
|
||||
}
|
||||
|
||||
private fun createUpiRequest(selectedBankAccount: LinkedAccountEntity): UpiPayNowRequest {
|
||||
return UpiPayNowRequest(
|
||||
methodName = UpiLinkedAccountPaymentInstrument.PAYMENT_INSTRUMENT_TYPE,
|
||||
selectedMethodDetails =
|
||||
SelectedMethodDetails(
|
||||
payerBankAccountId = selectedBankAccount.accountId,
|
||||
accountType = selectedBankAccount.accountType,
|
||||
),
|
||||
discountInfo = createDiscountInfo(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createDiscountInfo(): List<PayAmountRequest.DiscountInfo>? {
|
||||
val discountState = npsScreenState.naviCoinState
|
||||
|
||||
@@ -1701,43 +1602,41 @@ constructor(
|
||||
selectedBankAccount: LinkedAccountEntity
|
||||
) {
|
||||
when {
|
||||
isPaymentFromLiteAccount() -> handleLiteAccountPayment(selectedBankAccount)
|
||||
selectedBankAccount.isMPinSet.not() -> handleMPinSetup(selectedBankAccount)
|
||||
else -> handleNonLiteAccountPayment(selectedBankAccount)
|
||||
else -> makePayment(selectedBankAccount)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleNonLiteAccountPayment(selectedBankAccount: LinkedAccountEntity) {
|
||||
pspManagerAnalytics.onSendMoneyWithPspManager(
|
||||
accountId = selectedBankAccount.accountId,
|
||||
isPaymentFromLiteAccount = false,
|
||||
screenName = screenName,
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForFlow(
|
||||
naviPayFlowType =
|
||||
NaviPayFlowType.getSendMoneyFlowForAccountType(selectedBankAccount.accountType),
|
||||
vpaEntityList = selectedBankAccount.vpaEntityList,
|
||||
screenName = screenName,
|
||||
onOnboardingTriggered = {},
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, screenName)
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
if (pspEvaluationResult.isOnboardingTriggered) {
|
||||
showRedirectingToMakePaymentBottomSheet()
|
||||
}
|
||||
onPspEvaluatedForSendMoney(onboardingEntity, selectedBankAccount)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun onPspEvaluatedForSendMoney(
|
||||
onboardingEntity: NaviPayCustomerOnboardingEntity,
|
||||
selectedBankAccount: LinkedAccountEntity,
|
||||
) {
|
||||
private suspend fun makePayment(account: LinkedAccountEntity) {
|
||||
showLoader(true)
|
||||
val upiPayNowRequest = createUpiRequest(selectedBankAccount)
|
||||
submitPayNowRequest(upiPayNowRequest, onboardingEntity)
|
||||
naviUpiPaymentProcessor.makePayment(
|
||||
account = account,
|
||||
isDiscountApplied = npsScreenState.naviCoinState.isDiscountApplied,
|
||||
discountInfo = createDiscountInfo(),
|
||||
analyticScreenName = screenName,
|
||||
naviPaymentScreen = NaviPaymentScreenType.FULL_PAYMENT_SCREEN,
|
||||
paymentToken = paymentSdkInitParams?.token.orEmpty(),
|
||||
baseAttributes = baseAnalyticsParams,
|
||||
onInitialChecksFailure = {
|
||||
handleError(
|
||||
genericErrorResponse = it,
|
||||
errorReason = PMSErrorReason.NoActiveLiteAccountPSP,
|
||||
)
|
||||
},
|
||||
onOnboardingTriggered = {},
|
||||
onOnboardingCancelled = { showLoader(false) },
|
||||
onOnboardingCompleted = { showRedirectingToMakePaymentBottomSheet() },
|
||||
onBeforePayNowApiCall = {},
|
||||
onPayNowSuccess = { payNowResponse = it },
|
||||
onPayNowFailure = onPayNowFailure(),
|
||||
onBeforeOpeningPinPage = { updateBottomSheetUIState(false) },
|
||||
onPinPageBack = { showLoader(false) },
|
||||
onPinPageError = {
|
||||
showLoader(false)
|
||||
handleError(genericErrorResponse = it, errorReason = PMSErrorReason.UPIError)
|
||||
},
|
||||
onPinPageSuccess = navigateToTransactionPollingScreen(account),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun handleAccountAdditionFlow(hasClickedAddAccount: Boolean = false) {
|
||||
@@ -1814,41 +1713,6 @@ constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun handleLiteAccountPayment(selectedBankAccount: LinkedAccountEntity) {
|
||||
if (selectedBankAccount.activeLiteAccountPsp == null) {
|
||||
notifyError()
|
||||
return
|
||||
}
|
||||
val vpaEntityForLiteAccount =
|
||||
selectedBankAccount.getVpaEntityByPsp(
|
||||
selectedBankAccount.activeLiteAccountPsp ?: return
|
||||
)
|
||||
pspManagerAnalytics.onSendMoneyWithPspManager(
|
||||
accountId = selectedBankAccount.accountId,
|
||||
isPaymentFromLiteAccount = true,
|
||||
screenName,
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForVpa(
|
||||
vpaEntity = vpaEntityForLiteAccount,
|
||||
screenName = screenName,
|
||||
onOnboardingTriggered = {},
|
||||
naviPayFlowType = NaviPayFlowType.UPI_LITE,
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, screenName)
|
||||
if (pspEvaluationResult.isOnboardingTriggered) {
|
||||
return@evaluateAndOnboardPspForVpa // don't make upi lite payment automatically
|
||||
// after onboarding
|
||||
}
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
onPspEvaluatedForSendMoney(
|
||||
onboardingEntity = onboardingEntity,
|
||||
selectedBankAccount = selectedBankAccount,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun isPaymentFromLiteAccount(): Boolean {
|
||||
return npsScreenState.naviUpiPaymentState.selectedBankAccount
|
||||
?.accountId
|
||||
@@ -1893,10 +1757,7 @@ constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun submitPayNowRequest(
|
||||
payNowRequest: PayNowRequest,
|
||||
onboardingEntity: NaviPayCustomerOnboardingEntity? = null,
|
||||
) {
|
||||
private suspend fun submitPayNowRequest(payNowRequest: PayNowRequest) {
|
||||
val payNowResponse =
|
||||
paymentRepository.postPayNow(
|
||||
token = paymentSdkInitParams?.token,
|
||||
@@ -1906,7 +1767,7 @@ constructor(
|
||||
screenName = NaviPaymentAnalyticScreenName.FULL_PAYMENT_SCREEN.screenName
|
||||
),
|
||||
)
|
||||
handlePayNowResponse(payNowResponse, onboardingEntity)
|
||||
handlePayNowResponse(payNowResponse)
|
||||
}
|
||||
|
||||
private fun isUpiCollectSelected() =
|
||||
@@ -1946,4 +1807,42 @@ constructor(
|
||||
?.contains(UpiLinkedAccountPaymentInstrument.PAYMENT_INSTRUMENT_TYPE)
|
||||
.orFalse()
|
||||
}
|
||||
|
||||
private fun onPayNowFailure(): (GenericErrorResponse) -> Unit = {
|
||||
showLoader(false)
|
||||
_state.update {
|
||||
npsScreenState.copy(
|
||||
netBankingDetails = npsScreenState.netBankingDetails.copy(selectedBank = null)
|
||||
)
|
||||
}
|
||||
updateBottomSheetUIState(false)
|
||||
handleError(it, errorReason = PMSErrorReason.PayNowError)
|
||||
}
|
||||
|
||||
private fun navigateToTransactionPollingScreen(
|
||||
account: LinkedAccountEntity
|
||||
): suspend (UpiNavigationResponse) -> Unit = { upiNavigationResponse ->
|
||||
val payload = upiNavigationResponse.internalPayNowResponse.providerPayload
|
||||
_effect.emit(
|
||||
NPSBaseContract.Effect.NavigateToLoaderScreen(
|
||||
token = upiNavigationResponse.paymentToken,
|
||||
paymentAmount = npsScreenState.npsBaseState.paymentAmount,
|
||||
source = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
tstoreOrderReferenceId = upiNavigationResponse.tstoreOrderReferenceId,
|
||||
payNowResponse = payNowResponse,
|
||||
naviUpiTransactionInfo =
|
||||
NaviUpiTransactionInfo(
|
||||
selectedBankAccountId = account.accountId,
|
||||
credBlock = upiNavigationResponse.pmsSendMoneyStatus.credBlock,
|
||||
upiRequestId = upiNavigationResponse.pmsSendMoneyStatus.upiRequestId,
|
||||
naviPayUpiUriKey = upiNavigationResponse.intentUri,
|
||||
metaData = Gson().toJson(payload?.metadata),
|
||||
txnTimeStamp = upiNavigationResponse.transactionTimestamp,
|
||||
isArcProtected = account.isArcProtected,
|
||||
onboardingDataEntity =
|
||||
upiNavigationResponse.pmsSendMoneyStatus.onboardingDataEntity,
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,9 @@ import com.navi.base.utils.EMPTY
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.common.model.RequestConfig
|
||||
import com.navi.common.usecase.LitmusExperimentsUseCase
|
||||
import com.navi.common.utils.TemporaryStorageHelper
|
||||
import com.navi.common.utils.toJsonObject
|
||||
import com.navi.pay.common.model.view.CheckBalanceState
|
||||
import com.navi.pay.common.model.view.NaviPayErrorConfig
|
||||
import com.navi.pay.common.model.view.NaviPayFlowType
|
||||
import com.navi.pay.common.model.view.PspType
|
||||
import com.navi.pay.common.setup.NaviPayManager
|
||||
@@ -33,36 +30,29 @@ import com.navi.pay.common.usecase.NaviPayConfigUseCase
|
||||
import com.navi.pay.management.common.sendmoney.util.PaymentRetryErrorBucket
|
||||
import com.navi.pay.management.common.utils.NaviPayPspManager
|
||||
import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
|
||||
import com.navi.pay.onboarding.binding.model.view.NaviPayCustomerOnboardingEntity
|
||||
import com.navi.pay.utils.isAccountIdOfTypeUpiLite
|
||||
import com.navi.payment.model.common.PaymentSdkInitParams
|
||||
import com.navi.payment.model.common.SignalPaymentData
|
||||
import com.navi.payment.model.paymentmethod.Amount
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalyticScreenName
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalytics
|
||||
import com.navi.payment.nativepayment.common.usecase.TransactionStatusUseCase
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.PAYMENT_ORDER_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.TRANSACTION_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.PinAction
|
||||
import com.navi.payment.nativepayment.dataprovider.getMpinResetAction
|
||||
import com.navi.payment.nativepayment.db.model.TransactionStatusRequestEntity
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.OneClickScreenBottomSheetStateHolder
|
||||
import com.navi.payment.nativepayment.model.OneClickScreenBottomSheetUiState
|
||||
import com.navi.payment.nativepayment.model.PMSSendMoneyStatus
|
||||
import com.navi.payment.nativepayment.model.S2sPaymentMethodResponse
|
||||
import com.navi.payment.nativepayment.model.UpiLinkedAccountPaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatus
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatusRequest
|
||||
import com.navi.payment.nativepayment.presentation.reducer.OneClickCheckoutScreenEffect
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.usecase.PmsSendMoneyUseCase
|
||||
import com.navi.payment.nativepayment.screens.destinations.TransactionPollingScreenDestination
|
||||
import com.navi.payment.nativepayment.usecase.NaviUpiPaymentProcessor
|
||||
import com.navi.payment.nativepayment.usecase.UpiNavigationResponse
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentEventHandler
|
||||
import com.navi.payment.nativepayment.utils.PaymentCancelSource
|
||||
import com.navi.payment.nativepayment.utils.toGenericErrorResponse
|
||||
import com.navi.payment.nativepayment.utils.toPaymentNaviPaymentErrorConfig
|
||||
import com.navi.payment.paymentscreen.model.InternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.NaviPayProcessPayload
|
||||
import com.navi.payment.paymentscreen.model.NaviUpiTransactionInfo
|
||||
import com.navi.payment.paymentscreen.model.PMSErrorReason
|
||||
import com.navi.payment.paymentscreen.model.PayNowResponse
|
||||
import com.navi.payment.turbocheckout.model.PayAmountRequest
|
||||
@@ -77,13 +67,15 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.joda.time.DateTime
|
||||
import org.json.JSONObject
|
||||
|
||||
@HiltViewModel
|
||||
@@ -96,12 +88,11 @@ constructor(
|
||||
private val paymentDataProvider: PaymentDataProvider,
|
||||
private val paymentRepository: PaymentRepository,
|
||||
private val paymentEventHandler: NaviPaymentEventHandler,
|
||||
private val transactionStatusUseCase: TransactionStatusUseCase,
|
||||
private val pmsSendMoneyUseCase: PmsSendMoneyUseCase,
|
||||
private val arcNudgeUseCase: ArcNudgeUseCase,
|
||||
private val naviPayManager: NaviPayManager,
|
||||
private val naviPayPspManager: NaviPayPspManager,
|
||||
private val accountListCheckBalanceUseCase: AccountListCheckBalanceUseCase,
|
||||
private val naviUpiPaymentProcessor: NaviUpiPaymentProcessor,
|
||||
) :
|
||||
NaviPaymentBaseVM(
|
||||
screenName = NaviPaymentAnalyticScreenName.ONE_CLICK_CHECKOUT_SCREEN.screenName,
|
||||
@@ -119,9 +110,6 @@ constructor(
|
||||
var paymentSdkInitParams: PaymentSdkInitParams? = null
|
||||
var isAmountReadOnly: Boolean = true
|
||||
|
||||
private val _pmsSendMoneyStatus = MutableStateFlow<PMSSendMoneyStatus?>(null)
|
||||
val pmsSendMoneyStatus = _pmsSendMoneyStatus.asStateFlow()
|
||||
|
||||
private val _bottomSheetStateHolder =
|
||||
MutableStateFlow(
|
||||
OneClickScreenBottomSheetStateHolder(
|
||||
@@ -145,6 +133,10 @@ constructor(
|
||||
private val pspManagerAnalytics = NaviPaymentAnalytics.INSTANCE.PspManager()
|
||||
private val sendMoneyErrorAnalytics = NaviPaymentAnalytics.INSTANCE.SendMoneyErrorBottomSheet()
|
||||
|
||||
private val _effect = MutableSharedFlow<OneClickCheckoutScreenEffect>()
|
||||
val effect: SharedFlow<OneClickCheckoutScreenEffect>
|
||||
get() = _effect.asSharedFlow()
|
||||
|
||||
init {
|
||||
viewModelScope.safeLaunch(Dispatchers.IO) { sendMoneyErrorListener() }
|
||||
}
|
||||
@@ -199,7 +191,7 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun startPayment(bundle: Bundle? = Bundle()) {
|
||||
fun startPaymentProcess(bundle: Bundle? = Bundle()) {
|
||||
viewModelScope.safeLaunch(Dispatchers.IO) {
|
||||
if (selectedAccountId.isNotNullAndNotEmpty()) return@safeLaunch
|
||||
bundle?.let {
|
||||
@@ -221,185 +213,68 @@ constructor(
|
||||
paymentDataProvider.paymentMethodResponse.collectLatest { it ->
|
||||
(it as? S2sPaymentMethodResponse)?.let {
|
||||
amount = it.methodDetails?.amount?.value.orZero()
|
||||
callPayNowApiAndStartPayment()
|
||||
getSelectedAccountAndStartPayment()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun callPayNowApiAndStartPayment() {
|
||||
private suspend fun getSelectedAccountAndStartPayment() {
|
||||
val accounts = linkedAccountUseCase.execute(includeAllDetails = true).first()
|
||||
linkedAccountEntity = accounts.firstOrNull { it.accountId == selectedAccountId }
|
||||
linkedAccountEntity?.let {
|
||||
if (paymentSdkInitParams?.isArcProtected.orFalse()) {
|
||||
arcNudgeUseCase.updateAccountArcStatusForLinkedAccount(it)
|
||||
}
|
||||
accountListCheckBalanceUseCase.updateCheckBalanceStateForLinkedAccount(
|
||||
linkedAccountEntity = it,
|
||||
isAccountEligible = it.eligibilityState.isAccountEligible,
|
||||
)
|
||||
_checkBalanceStateMap.update { accountListCheckBalanceUseCase.checkBalanceStateMap }
|
||||
}
|
||||
val response = fetchPayNowResponse()
|
||||
if (response.isSuccessWithData()) {
|
||||
paymentDataProvider.add(
|
||||
TRANSACTION_REFERENCE_ID,
|
||||
response.data?.transactionReferenceId.orEmpty(),
|
||||
)
|
||||
paymentDataProvider.add(
|
||||
PAYMENT_ORDER_REFERENCE_ID,
|
||||
response.data?.paymentOrderReferenceId.orEmpty(),
|
||||
)
|
||||
response.data?.transactionReferenceId?.let { transactionReferenceId ->
|
||||
insertTransactionStatusRequest(transactionReferenceId = transactionReferenceId)
|
||||
}
|
||||
payNowResponse = response.data
|
||||
(response.data as? InternalPayNowResponse)?.let {
|
||||
startNaviUpiPayment(payNowResponse = it)
|
||||
}
|
||||
} else {
|
||||
onBottomSheetCloseClicked()
|
||||
handleError(response = response, errorReason = PMSErrorReason.PayNowError)
|
||||
}
|
||||
linkedAccountEntity?.let { makePayment(it) }
|
||||
}
|
||||
|
||||
private suspend fun fetchPayNowResponse() =
|
||||
paymentRepository.postPayNow(
|
||||
token = paymentSdkInitParams?.token,
|
||||
data =
|
||||
PayAmountRequest(
|
||||
methodName = UpiLinkedAccountPaymentInstrument.PAYMENT_INSTRUMENT_TYPE,
|
||||
selectedMethodDetails =
|
||||
PayAmountRequest.SelectedMethodDetails(
|
||||
payerBankAccountId = linkedAccountEntity?.accountId,
|
||||
accountType = linkedAccountEntity?.accountType,
|
||||
),
|
||||
discountInfo =
|
||||
if (coinsValue > 0) {
|
||||
listOf(
|
||||
PayAmountRequest.DiscountInfo(
|
||||
type = PayAmountRequest.DiscountType.COIN.name,
|
||||
amount = coinsAmount,
|
||||
discountMetadata =
|
||||
PayAmountRequest.DiscountMetadata(coinsUsed = coinsValue),
|
||||
)
|
||||
)
|
||||
} else null,
|
||||
),
|
||||
metricInfo =
|
||||
getPMSMetricInfo(
|
||||
screenName = NaviPaymentAnalyticScreenName.ONE_CLICK_CHECKOUT_SCREEN.screenName
|
||||
),
|
||||
)
|
||||
|
||||
private suspend fun startNaviUpiPayment(payNowResponse: InternalPayNowResponse) {
|
||||
naviPaymentAnalytics.onNavigatingToPinPage(
|
||||
selectedBankAccountId = selectedAccountId,
|
||||
oneClickPayToPinTime =
|
||||
(System.currentTimeMillis() - TemporaryStorageHelper.payNowClickTime).toString(),
|
||||
baseAttributes = paymentDataProvider.getAnalyticsParams(),
|
||||
)
|
||||
val selectedBankAccount = linkedAccountEntity ?: return
|
||||
val payload = payNowResponse.providerPayload
|
||||
txnTimeStamp = DateTime.now().toString()
|
||||
when {
|
||||
isPaymentFromLiteAccount() -> handleLiteAccountPayment(selectedBankAccount, payload)
|
||||
else -> handleNonLiteAccountPayment(selectedBankAccount, payload)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleNonLiteAccountPayment(
|
||||
selectedBankAccount: LinkedAccountEntity,
|
||||
payload: NaviPayProcessPayload?,
|
||||
) {
|
||||
pspManagerAnalytics.onSendMoneyWithPspManager(
|
||||
accountId = selectedBankAccount.accountId,
|
||||
isPaymentFromLiteAccount = false,
|
||||
screenName = screenName,
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForFlow(
|
||||
naviPayFlowType =
|
||||
NaviPayFlowType.getSendMoneyFlowForAccountType(selectedBankAccount.accountType),
|
||||
vpaEntityList = selectedBankAccount.vpaEntityList,
|
||||
screenName = screenName,
|
||||
private suspend fun makePayment(account: LinkedAccountEntity) {
|
||||
naviUpiPaymentProcessor.makePayment(
|
||||
account = account,
|
||||
isDiscountApplied = coinsValue > 0,
|
||||
discountInfo = getDiscountInfo(),
|
||||
analyticScreenName = NaviPaymentAnalyticScreenName.ONE_CLICK_CHECKOUT_SCREEN.screenName,
|
||||
naviPaymentScreen = NaviPaymentScreenType.ONE_CLICK_CHECKOUT_SCREEN,
|
||||
paymentToken = paymentSdkInitParams?.token.orEmpty(),
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
onInitialChecksFailure = {
|
||||
handleError(
|
||||
genericErrorResponse = it,
|
||||
errorReason = PMSErrorReason.NoActiveLiteAccountPSP,
|
||||
)
|
||||
},
|
||||
onOnboardingTriggered = {},
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, screenName)
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
onPspEvaluatedForSendMoney(onboardingEntity, payload, selectedBankAccount)
|
||||
}
|
||||
onOnboardingCancelled = {},
|
||||
onOnboardingCompleted = {},
|
||||
onBeforePayNowApiCall = { onBeforePayNowApiCall(account) },
|
||||
onPayNowSuccess = { payNowResponse = it },
|
||||
onPayNowFailure = {
|
||||
onBottomSheetCloseClicked()
|
||||
handleError(it, errorReason = PMSErrorReason.PayNowError)
|
||||
},
|
||||
onBeforeOpeningPinPage = {},
|
||||
onPinPageBack = {
|
||||
postSdkExitSignal()
|
||||
finish()
|
||||
payNowResponse = null
|
||||
},
|
||||
onPinPageError = {
|
||||
handleError(it)
|
||||
payNowResponse = null // check if needed
|
||||
},
|
||||
onPinPageSuccess = {
|
||||
navigateToTransactionPollingScreen(it, account = account)
|
||||
payNowResponse = null
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun handleLiteAccountPayment(
|
||||
selectedBankAccount: LinkedAccountEntity,
|
||||
payload: NaviPayProcessPayload?,
|
||||
) {
|
||||
if (selectedBankAccount.activeLiteAccountPsp == null) {
|
||||
notifyError()
|
||||
return
|
||||
}
|
||||
val vpaEntityForLiteAccount =
|
||||
selectedBankAccount.getVpaEntityByPsp(
|
||||
selectedBankAccount.activeLiteAccountPsp ?: return
|
||||
)
|
||||
pspManagerAnalytics.onSendMoneyWithPspManager(
|
||||
accountId = selectedBankAccount.accountId,
|
||||
isPaymentFromLiteAccount = true,
|
||||
screenName,
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForVpa(
|
||||
vpaEntity = vpaEntityForLiteAccount,
|
||||
screenName = screenName,
|
||||
onOnboardingTriggered = {},
|
||||
naviPayFlowType = NaviPayFlowType.UPI_LITE,
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, screenName)
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
onPspEvaluatedForSendMoney(
|
||||
onboardingEntity = onboardingEntity,
|
||||
payload = payload,
|
||||
selectedBankAccount = selectedBankAccount,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun onPspEvaluatedForSendMoney(
|
||||
onboardingEntity: NaviPayCustomerOnboardingEntity,
|
||||
payload: NaviPayProcessPayload?,
|
||||
selectedBankAccount: LinkedAccountEntity,
|
||||
) {
|
||||
_pmsSendMoneyStatus.update {
|
||||
pmsSendMoneyUseCase.performChecksAndGenerateCredBlock(
|
||||
naviPayUpiUriKey = payload?.naviPayUpiUriKey.orEmpty(),
|
||||
linkedAccountEntity = selectedBankAccount,
|
||||
screenName = screenName,
|
||||
baseAnalyticsParam = paymentDataProvider.getAnalyticsParams(),
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
onboardingDataEntity = onboardingEntity,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isPaymentFromLiteAccount(): Boolean {
|
||||
return linkedAccountEntity?.accountId?.isAccountIdOfTypeUpiLite().orFalse()
|
||||
}
|
||||
|
||||
private fun insertTransactionStatusRequest(transactionReferenceId: String) {
|
||||
coroutineScope.safeLaunch(Dispatchers.IO) {
|
||||
transactionStatusUseCase.insertTransactionStatusRequest(
|
||||
TransactionStatusRequestEntity(
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
token = paymentSdkInitParams?.token,
|
||||
screenType = NaviPaymentScreenType.ONE_CLICK_CHECKOUT_SCREEN.name,
|
||||
event = EMPTY,
|
||||
status = TransactionStatus.INITIATED.name,
|
||||
private fun getDiscountInfo() =
|
||||
if (coinsValue > 0) {
|
||||
listOf(
|
||||
PayAmountRequest.DiscountInfo(
|
||||
type = PayAmountRequest.DiscountType.COIN.name,
|
||||
amount = coinsAmount,
|
||||
discountMetadata = PayAmountRequest.DiscountMetadata(coinsUsed = coinsValue),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else null
|
||||
|
||||
private suspend fun updateSDKInitParams() {
|
||||
paymentSdkInitParams = paymentDataProvider.getSdkInitParams()
|
||||
@@ -430,47 +305,11 @@ constructor(
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
)
|
||||
_isBottomSheetRetryCtaLoaderEnabled.update { true }
|
||||
callPayNowApiAndStartPayment()
|
||||
getSelectedAccountAndStartPayment()
|
||||
onBottomSheetCloseClicked()
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyNaviUpiExitWithError(status: String, error: NaviPayErrorConfig?) {
|
||||
coroutineScope.safeLaunch(Dispatchers.IO) {
|
||||
paymentSdkInitParams?.token?.let {
|
||||
transactionStatusUseCase.updateAndPostTransactionStatus(
|
||||
token = it,
|
||||
transactionStatusRequest =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId =
|
||||
paymentDataProvider.get(TRANSACTION_REFERENCE_ID).toString(),
|
||||
event = error.toJsonObject().toString(),
|
||||
screenType = NaviPaymentScreenType.ONE_CLICK_CHECKOUT_SCREEN.name,
|
||||
status = status,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTransactionStatusToPending(transactionReferenceId: String?) {
|
||||
coroutineScope.safeLaunch(Dispatchers.IO) {
|
||||
transactionStatusUseCase.updateTransactionStatusRequest(
|
||||
transactionStatusRequest =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId = transactionReferenceId,
|
||||
status = TransactionStatus.PENDING.name,
|
||||
event = EMPTY,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onNaviPayCallBack() {
|
||||
payNowResponse = null
|
||||
_pmsSendMoneyStatus.update { null }
|
||||
}
|
||||
|
||||
fun postSdkExitSignal() {
|
||||
coroutineScope.safeLaunch(Dispatchers.IO) {
|
||||
paymentSdkInitParams?.token?.let {
|
||||
@@ -601,4 +440,76 @@ constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun finish() {
|
||||
viewModelScope.safeLaunch {
|
||||
_effect.emit(
|
||||
OneClickCheckoutScreenEffect.SetResultAndFinish(
|
||||
cancelSource = PaymentCancelSource.SYSTEM_BACK_CLICKED,
|
||||
shouldPromptAmountEdit = false,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onBeforePayNowApiCall(account: LinkedAccountEntity) {
|
||||
viewModelScope.safeLaunch(Dispatchers.IO) {
|
||||
if (paymentSdkInitParams?.isArcProtected.orFalse()) {
|
||||
arcNudgeUseCase.updateAccountArcStatusForLinkedAccount(account)
|
||||
}
|
||||
accountListCheckBalanceUseCase.updateCheckBalanceStateForLinkedAccount(
|
||||
linkedAccountEntity = account,
|
||||
isAccountEligible = account.eligibilityState.isAccountEligible,
|
||||
)
|
||||
_checkBalanceStateMap.update { accountListCheckBalanceUseCase.checkBalanceStateMap }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun navigateToTransactionPollingScreen(
|
||||
upiNavigationResponse: UpiNavigationResponse,
|
||||
account: LinkedAccountEntity,
|
||||
) {
|
||||
if (
|
||||
upiNavigationResponse.paymentToken.isNotEmpty() &&
|
||||
upiNavigationResponse.transactionReferenceId.isNotEmpty()
|
||||
) {
|
||||
_effect.emit(
|
||||
OneClickCheckoutScreenEffect.Navigation(
|
||||
direction =
|
||||
TransactionPollingScreenDestination(
|
||||
token = upiNavigationResponse.paymentToken,
|
||||
paymentAmount = amount,
|
||||
redeemedCoinsValue = coinsAmount?.value.orZero(),
|
||||
source = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
tstoreOrderReferenceId = upiNavigationResponse.tstoreOrderReferenceId,
|
||||
sourceDestination =
|
||||
NaviPaymentScreenType.ONE_CLICK_CHECKOUT_SCREEN.name,
|
||||
pollingConfiguration =
|
||||
payNowResponse?.pollingConfiguration ?: RequestConfig(),
|
||||
request =
|
||||
TransactionStatusRequest(
|
||||
transactionReferenceId =
|
||||
upiNavigationResponse.transactionReferenceId,
|
||||
screenType =
|
||||
NaviPaymentScreenType.ONE_CLICK_CHECKOUT_SCREEN.name,
|
||||
),
|
||||
naviUpiTransactionInfo =
|
||||
NaviUpiTransactionInfo(
|
||||
naviPayUpiUriKey = upiNavigationResponse.intentUri,
|
||||
upiRequestId =
|
||||
upiNavigationResponse.pmsSendMoneyStatus.upiRequestId,
|
||||
selectedBankAccountId = account.accountId,
|
||||
credBlock = upiNavigationResponse.pmsSendMoneyStatus.credBlock,
|
||||
metaData = upiNavigationResponse.metaData,
|
||||
txnTimeStamp = upiNavigationResponse.transactionTimestamp,
|
||||
isArcProtected = account.isArcProtected.orFalse(),
|
||||
onboardingDataEntity =
|
||||
upiNavigationResponse.pmsSendMoneyStatus
|
||||
.onboardingDataEntity,
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,13 @@ import androidx.activity.result.ActivityResult
|
||||
import com.google.gson.Gson
|
||||
import com.navi.base.utils.EMPTY
|
||||
import com.navi.base.utils.ResourceProvider
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.network.models.RepoResult
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.common.uitron.model.action.UpiIntent
|
||||
import com.navi.common.upi.CANCEL
|
||||
import com.navi.common.usecase.LitmusExperimentsUseCase
|
||||
import com.navi.common.utils.CommonUtils.getDisplayableAmount
|
||||
import com.navi.common.utils.toJsonObject
|
||||
import com.navi.pay.common.model.view.NaviPayFlowType
|
||||
import com.navi.pay.common.setup.NaviPayManager
|
||||
import com.navi.pay.common.usecase.NaviPayConfigUseCase
|
||||
@@ -40,7 +37,6 @@ import com.navi.payment.nativepayment.dataprovider.getMpinSetAction
|
||||
import com.navi.payment.nativepayment.db.model.TransactionStatusRequestEntity
|
||||
import com.navi.payment.nativepayment.model.BasePaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.PMSSendMoneyStatus
|
||||
import com.navi.payment.nativepayment.model.PaymentsMainCtaState
|
||||
import com.navi.payment.nativepayment.model.S2sPaymentMethodResponse
|
||||
import com.navi.payment.nativepayment.model.UpiCollectPaymentInstrument
|
||||
@@ -53,15 +49,13 @@ import com.navi.payment.nativepayment.presentation.reducer.NPSBaseState
|
||||
import com.navi.payment.nativepayment.presentation.reducer.UpiCollectOptionState
|
||||
import com.navi.payment.nativepayment.presentation.reducer.UpiIntentScreenContract
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.usecase.NaviUpiPaymentProcessor
|
||||
import com.navi.payment.nativepayment.usecase.PmsLinkedAccountUseCase
|
||||
import com.navi.payment.nativepayment.usecase.PmsSendMoneyUseCase
|
||||
import com.navi.payment.nativepayment.usecase.UpiNavigationResponse
|
||||
import com.navi.payment.nativepayment.utils.mapToLinkedAccountEntity
|
||||
import com.navi.payment.nativepayment.utils.toGenericError
|
||||
import com.navi.payment.network.util.PaymentsSdkRetrofit
|
||||
import com.navi.payment.paymentscreen.model.ExternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.IntentUriPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.InternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.NaviPayProcessPayload
|
||||
import com.navi.payment.paymentscreen.model.NaviUpiTransactionInfo
|
||||
import com.navi.payment.paymentscreen.model.PMSErrorReason
|
||||
import com.navi.payment.paymentscreen.model.PayNowResponse
|
||||
@@ -69,7 +63,6 @@ import com.navi.payment.turbocheckout.model.PayNowRequest
|
||||
import com.navi.payment.turbocheckout.model.SelectedMethodDetails
|
||||
import com.navi.payment.turbocheckout.model.UpiCollectPayNowRequest
|
||||
import com.navi.payment.turbocheckout.model.UpiIntentPayNowRequest
|
||||
import com.navi.payment.turbocheckout.model.UpiPayNowRequest
|
||||
import com.navi.payment.utils.getPMSMetricInfo
|
||||
import com.navi.payment.utils.roundTo
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@@ -83,7 +76,6 @@ import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import org.joda.time.DateTime
|
||||
import org.json.JSONObject
|
||||
|
||||
@HiltViewModel
|
||||
@@ -94,13 +86,13 @@ constructor(
|
||||
@PaymentsSdkRetrofit private val deserializer: Gson,
|
||||
paymentDataProvider: PaymentDataProvider,
|
||||
pmsLinkedAccountUseCase: PmsLinkedAccountUseCase,
|
||||
transactionStatusUseCase: TransactionStatusUseCase,
|
||||
transactionStatusUseCase: TransactionStatusUseCase, // TODO Remove?
|
||||
paymentRepository: PaymentRepository,
|
||||
resourceProvider: ResourceProvider,
|
||||
litmusExperimentsUseCase: LitmusExperimentsUseCase,
|
||||
naviPayConfigUseCase: NaviPayConfigUseCase,
|
||||
private val pmsSendMoneyUseCase: PmsSendMoneyUseCase,
|
||||
private val naviPayPspManager: NaviPayPspManager,
|
||||
private val naviUpiPaymentProcessor: NaviUpiPaymentProcessor,
|
||||
) :
|
||||
NPSBaseViewModel(
|
||||
paymentRepository = paymentRepository,
|
||||
@@ -357,53 +349,50 @@ constructor(
|
||||
private suspend fun handleNaviUpiFlow(vpaAccount: LinkedAccountEntity) {
|
||||
when {
|
||||
vpaAccount.isMPinSet.not() -> handleMPinSetup(vpaAccount)
|
||||
else -> handleNaviUpiPayment(vpaAccount)
|
||||
else -> makePayment(vpaAccount)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleNaviUpiPayment(vpaAccount: LinkedAccountEntity) {
|
||||
pspManagerAnalytics.onSendMoneyWithPspManager(
|
||||
accountId = vpaAccount.accountId,
|
||||
isPaymentFromLiteAccount = false,
|
||||
screenName = screenName,
|
||||
)
|
||||
naviPayPspManager.evaluateAndOnboardPspForFlow(
|
||||
naviPayFlowType =
|
||||
NaviPayFlowType.getSendMoneyFlowForAccountType(vpaAccount.accountType),
|
||||
vpaEntityList = vpaAccount.vpaEntityList,
|
||||
screenName = screenName,
|
||||
onOnboardingTriggered = {},
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(
|
||||
pspEvaluationResult = pspEvaluationResult,
|
||||
screenName = screenName,
|
||||
private suspend fun makePayment(vpaAccount: LinkedAccountEntity) {
|
||||
showLoader(true)
|
||||
naviUpiPaymentProcessor.makePayment(
|
||||
account = vpaAccount,
|
||||
isDiscountApplied = false,
|
||||
discountInfo = null,
|
||||
analyticScreenName = screenName,
|
||||
naviPaymentScreen = NaviPaymentScreenType.UPI_INTENT,
|
||||
paymentToken = paymentSdkInitParams?.token.orEmpty(),
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
onInitialChecksFailure = {
|
||||
handleError(
|
||||
genericErrorResponse = it,
|
||||
errorReason = PMSErrorReason.NoActiveLiteAccountPSP,
|
||||
)
|
||||
},
|
||||
onOnboardingTriggered = {},
|
||||
onOnboardingCancelled = { showLoader(false) },
|
||||
onOnboardingCompleted = {},
|
||||
onBeforePayNowApiCall = {},
|
||||
onPayNowSuccess = { payNowResponse = it },
|
||||
onPayNowFailure = { error ->
|
||||
showLoader(false)
|
||||
handleError(genericErrorResponse = error, errorReason = PMSErrorReason.UPIError)
|
||||
},
|
||||
onBeforeOpeningPinPage = {},
|
||||
onPinPageBack = { showLoader(false) },
|
||||
onPinPageError = { error ->
|
||||
showLoader(false)
|
||||
handleError(genericErrorResponse = error, errorReason = PMSErrorReason.UPIError)
|
||||
},
|
||||
onPinPageSuccess = {
|
||||
navigateToTransactionPollingScreen(
|
||||
upiNavigationResponse = it,
|
||||
accountId = vpaAccount.accountId,
|
||||
)
|
||||
pspEvaluationResult.onboardingDataEntity?.let { onboardingEntity ->
|
||||
onPspEvaluatedForSendMoney(onboardingEntity, vpaAccount)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun onPspEvaluatedForSendMoney(
|
||||
onboardingEntity: NaviPayCustomerOnboardingEntity,
|
||||
vpaAccount: LinkedAccountEntity,
|
||||
) {
|
||||
|
||||
val upiPayNowRequest = createUpiPayNowRequest(vpaAccount)
|
||||
callPayNowApiAndHandleResponse(upiPayNowRequest, onboardingEntity)
|
||||
}
|
||||
|
||||
private fun createUpiPayNowRequest(vpaAccount: LinkedAccountEntity) =
|
||||
UpiPayNowRequest(
|
||||
methodName = UpiLinkedAccountPaymentInstrument.PAYMENT_INSTRUMENT_TYPE,
|
||||
selectedMethodDetails =
|
||||
SelectedMethodDetails(
|
||||
payerBankAccountId = vpaAccount.accountId,
|
||||
accountType = vpaAccount.accountType,
|
||||
),
|
||||
)
|
||||
|
||||
private fun createCollectPayNowRequest(vpa: String): UpiCollectPayNowRequest {
|
||||
return UpiCollectPayNowRequest(
|
||||
selectedMethodDetails = SelectedMethodDetails(customerVpa = vpa)
|
||||
@@ -460,12 +449,6 @@ constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
is InternalPayNowResponse -> {
|
||||
startNaviUpiPayment(
|
||||
payNowResponse = payNowResponseData,
|
||||
onboardingDataEntity = onboardingDataEntity,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
showLoader(false)
|
||||
@@ -526,92 +509,27 @@ constructor(
|
||||
return upiScreenState.connectedAccountVpaMap?.get(key = vpa)
|
||||
}
|
||||
|
||||
private suspend fun startNaviUpiPayment(
|
||||
payNowResponse: InternalPayNowResponse,
|
||||
onboardingDataEntity: NaviPayCustomerOnboardingEntity? = null,
|
||||
) {
|
||||
if (onboardingDataEntity == null) {
|
||||
pspManagerAnalytics.onNaviPayOnboardingEntityNotInitialised(screenName = screenName)
|
||||
return
|
||||
}
|
||||
val payload = payNowResponse.providerPayload
|
||||
val txnTimeStamp = DateTime.now().toString()
|
||||
val pmsSendMoneyStatus =
|
||||
pmsSendMoneyUseCase.performChecksAndGenerateCredBlock(
|
||||
naviPayUpiUriKey = payload?.naviPayUpiUriKey.orEmpty(),
|
||||
screenName = NaviPaymentScreenType.UPI_INTENT.name,
|
||||
linkedAccountEntity =
|
||||
getLinkedAccountEntityFromVpaIfAvailable(
|
||||
vpa =
|
||||
upiScreenState.npsBaseState.upiCollectOptionState.upiCollectVpa.text
|
||||
.trimEnd()
|
||||
),
|
||||
baseAnalyticsParam = baseAnalyticsParams,
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
onboardingDataEntity = onboardingDataEntity,
|
||||
)
|
||||
when (pmsSendMoneyStatus) {
|
||||
is PMSSendMoneyStatus.Error -> {
|
||||
val errorConfig = pmsSendMoneyStatus.errorConfig
|
||||
var transactionStatus = TransactionStatus.ERROR.name
|
||||
if (errorConfig.code == CANCEL) {
|
||||
transactionStatus = TransactionStatus.USER_CANCELLED_TRANSACTION.name
|
||||
} else {
|
||||
handleError(
|
||||
genericErrorResponse = errorConfig.toGenericError(),
|
||||
errorReason = PMSErrorReason.UPIError,
|
||||
)
|
||||
}
|
||||
notifySdkExitWithError(transactionStatus, errorConfig.toJsonObject().toString())
|
||||
}
|
||||
is PMSSendMoneyStatus.Success -> {
|
||||
if (
|
||||
paymentSdkInitParams?.token.isNotNullAndNotEmpty() &&
|
||||
payNowResponse.transactionReferenceId.isNotNullAndNotEmpty()
|
||||
) {
|
||||
updateTransactionStatusToPending(payNowResponse.transactionReferenceId)
|
||||
navigateToTransactionLoaderScreen(
|
||||
payload,
|
||||
payNowResponse,
|
||||
pmsSendMoneyStatus,
|
||||
txnTimeStamp,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
showLoader(false)
|
||||
}
|
||||
|
||||
private suspend fun navigateToTransactionLoaderScreen(
|
||||
payload: NaviPayProcessPayload?,
|
||||
payNowResponse: InternalPayNowResponse,
|
||||
pmsSendMoneyStatus: PMSSendMoneyStatus.Success,
|
||||
txnTimeStamp: String,
|
||||
private suspend fun navigateToTransactionPollingScreen(
|
||||
accountId: String,
|
||||
upiNavigationResponse: UpiNavigationResponse,
|
||||
) {
|
||||
_effect.emit(
|
||||
NPSBaseContract.Effect.NavigateToLoaderScreen(
|
||||
token = paymentSdkInitParams?.token.orEmpty(),
|
||||
token = upiNavigationResponse.paymentToken,
|
||||
paymentAmount = state.value.npsBaseState.paymentAmount,
|
||||
source = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
tstoreOrderReferenceId = payload?.tstoreOrderReferenceId.orEmpty(),
|
||||
payNowResponse = payNowResponse,
|
||||
tstoreOrderReferenceId = upiNavigationResponse.tstoreOrderReferenceId,
|
||||
payNowResponse = upiNavigationResponse.internalPayNowResponse,
|
||||
naviUpiTransactionInfo =
|
||||
NaviUpiTransactionInfo(
|
||||
selectedBankAccountId =
|
||||
getLinkedAccountEntityFromVpaIfAvailable(
|
||||
vpa =
|
||||
upiScreenState.npsBaseState.upiCollectOptionState
|
||||
.upiCollectVpa
|
||||
.text
|
||||
)
|
||||
?.accountId
|
||||
.orEmpty(),
|
||||
credBlock = pmsSendMoneyStatus.credBlock.orEmpty(),
|
||||
upiRequestId = pmsSendMoneyStatus.upiRequestId,
|
||||
naviPayUpiUriKey = payload?.naviPayUpiUriKey,
|
||||
metaData = Gson().toJson(payload?.metadata),
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
onboardingDataEntity = pmsSendMoneyStatus.onboardingDataEntity,
|
||||
selectedBankAccountId = accountId,
|
||||
credBlock = upiNavigationResponse.pmsSendMoneyStatus.credBlock,
|
||||
upiRequestId = upiNavigationResponse.pmsSendMoneyStatus.upiRequestId,
|
||||
naviPayUpiUriKey = upiNavigationResponse.intentUri,
|
||||
metaData = upiNavigationResponse.metaData,
|
||||
txnTimeStamp = upiNavigationResponse.transactionTimestamp,
|
||||
onboardingDataEntity =
|
||||
upiNavigationResponse.pmsSendMoneyStatus.onboardingDataEntity,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.navi.common.checkmate.model.MetricInfo
|
||||
import com.navi.common.network.models.GenericErrorResponse
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.common.uitron.model.action.UpiIntent
|
||||
import com.navi.common.upi.UPI_REQUEST_ID
|
||||
import com.navi.common.upi.UpiDataType
|
||||
import com.navi.common.utils.CommonUtils.getDisplayableAmount
|
||||
import com.navi.common.utils.toJsonObject
|
||||
@@ -51,7 +52,6 @@ import com.navi.payment.model.initiatesdk.PaymentPrefetchMethodRequest
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalyticScreenName
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalytics
|
||||
import com.navi.payment.nativepayment.activity.WebPaymentActivity
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.PAYMENT_ORDER_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.TRANSACTION_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.UPI_LITE_MAX_PAYABLE_AMOUNT_PER_TRANSACTION
|
||||
import com.navi.payment.nativepayment.dataprovider.WebPaymentDataProvider
|
||||
@@ -60,6 +60,7 @@ import com.navi.payment.nativepayment.dataprovider.WebPaymentDataProvider.Compan
|
||||
import com.navi.payment.nativepayment.dataprovider.getMpinSetAction
|
||||
import com.navi.payment.nativepayment.model.BasePaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.CoinRewards
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.PMSLinkedAccountEntity
|
||||
import com.navi.payment.nativepayment.model.PMSSendMoneyStatus
|
||||
import com.navi.payment.nativepayment.model.PaymentsMainCtaState
|
||||
@@ -71,24 +72,27 @@ import com.navi.payment.nativepayment.model.WebPaymentData
|
||||
import com.navi.payment.nativepayment.model.WebPaymentScreenEffect
|
||||
import com.navi.payment.nativepayment.model.WebPaymentScreenState
|
||||
import com.navi.payment.nativepayment.model.WebPaymentSource
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatus
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.usecase.NaviUpiPaymentProcessor
|
||||
import com.navi.payment.nativepayment.usecase.PmsSendMoneyUseCase
|
||||
import com.navi.payment.nativepayment.usecase.UpiNavigationResponse
|
||||
import com.navi.payment.nativepayment.utils.getEligibilityStateForUpiLiteAccount
|
||||
import com.navi.payment.nativepayment.utils.getFirstEligibleAccount
|
||||
import com.navi.payment.nativepayment.utils.getPayloadBasedOnType
|
||||
import com.navi.payment.nativepayment.utils.mapToLinkedAccountEntity
|
||||
import com.navi.payment.nativepayment.utils.rankUpiAccountsByEligibility
|
||||
import com.navi.payment.nativepayment.utils.toGenericError
|
||||
import com.navi.payment.nativepayment.utils.toGenericErrorResponse
|
||||
import com.navi.payment.nativepayment.utils.updateAccountEligibilityStatusForNonUpiLiteAccounts
|
||||
import com.navi.payment.network.util.PaymentsSdkRetrofit
|
||||
import com.navi.payment.paymentscreen.model.InternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.NaviUpiTransactionInfo
|
||||
import com.navi.payment.paymentscreen.model.PMSErrorReason
|
||||
import com.navi.payment.paymentscreen.model.PayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.PaymentErrorData
|
||||
import com.navi.payment.turbocheckout.model.PayAmountRequest
|
||||
import com.navi.payment.utils.Constants
|
||||
import com.navi.payment.utils.Constants.EMPTY_TOKEN_ERROR
|
||||
import com.navi.payment.utils.Constants.PAYMENT_ORDER_REFERNCE_ID
|
||||
import com.navi.payment.utils.Constants.PSP_MANAGER_RESPONSE
|
||||
import com.navi.payment.utils.getErrorData
|
||||
import com.navi.payment.utils.getPMSMetricInfo
|
||||
@@ -120,8 +124,9 @@ constructor(
|
||||
private val naviPayManager: NaviPayManager,
|
||||
private val linkedAccountsUseCase: LinkedAccountsUseCase,
|
||||
private val pmsSendMoneyUseCase: PmsSendMoneyUseCase,
|
||||
@PaymentsSdkRetrofit private val deserializer: Gson,
|
||||
private val naviUpiPaymentProcessor: NaviUpiPaymentProcessor,
|
||||
private val naviPayPspManager: NaviPayPspManager,
|
||||
@PaymentsSdkRetrofit private val deserializer: Gson,
|
||||
) : NaviPaymentBaseVM(screenName = NaviPaymentAnalyticScreenName.WEB_PAYMENT_SCREEN.screenName) {
|
||||
|
||||
private val webPaymentData = savedStateHandle.get<WebPaymentData>("webPaymentData")
|
||||
@@ -485,7 +490,7 @@ constructor(
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, screenName)
|
||||
if (pspEvaluationResult.isOnboardingTriggered) {
|
||||
if (webPayAction == WebPaymentAction.WEB_VIEW_SEND_MONEY) finishWithError()
|
||||
_showPayNowLoader.update { false }
|
||||
stopPayNowLoader()
|
||||
return@evaluateAndOnboardPspForVpa // don't make upi lite payment automatically
|
||||
// after onboarding for web view payments.
|
||||
}
|
||||
@@ -525,7 +530,7 @@ constructor(
|
||||
onPspEvaluated = { pspEvaluationResult ->
|
||||
pspManagerAnalytics.onPspManagerResult(pspEvaluationResult, screenName)
|
||||
if (pspEvaluationResult.onboardingDataEntity == null) {
|
||||
_showPayNowLoader.update { false }
|
||||
stopPayNowLoader()
|
||||
if (webPayAction == WebPaymentAction.WEB_VIEW_SEND_MONEY) finishWithError()
|
||||
return@evaluateAndOnboardPspForFlow
|
||||
}
|
||||
@@ -559,7 +564,7 @@ constructor(
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
onboardingDataEntity = onboardingEntity,
|
||||
)
|
||||
_showPayNowLoader.update { false }
|
||||
stopPayNowLoader()
|
||||
handlePinPageResult(
|
||||
sendMoneyStatus = sendMoneyStatus,
|
||||
naviPayUpiUriKey = naviPayUpiUriKey,
|
||||
@@ -590,7 +595,7 @@ constructor(
|
||||
NaviUpiTransactionInfo(
|
||||
naviPayUpiUriKey = naviPayUpiUriKey,
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
credBlock = sendMoneyStatus.credBlock!!,
|
||||
credBlock = sendMoneyStatus.credBlock,
|
||||
upiRequestId = sendMoneyStatus.upiRequestId,
|
||||
selectedBankAccountId = linkedAccountEntity.accountId,
|
||||
metaData = metaData,
|
||||
@@ -633,69 +638,11 @@ constructor(
|
||||
_paymentAmount.update { amount }
|
||||
}
|
||||
|
||||
fun startPayAmount(accountId: String, linkedAccountType: String) =
|
||||
viewModelScope.launch {
|
||||
if (showPayNowLoader.value) return@launch
|
||||
_showPayNowLoader.update { true }
|
||||
val response = fetchPayNowResponse(accountId, linkedAccountType)
|
||||
if (response.isSuccessWithData()) {
|
||||
paymentDataProvider.add(
|
||||
TRANSACTION_REFERENCE_ID,
|
||||
response.data?.transactionReferenceId.orEmpty(),
|
||||
)
|
||||
paymentDataProvider.add(
|
||||
PAYMENT_ORDER_REFERENCE_ID,
|
||||
response.data?.paymentOrderReferenceId.orEmpty(),
|
||||
)
|
||||
payNowResponse = response.data
|
||||
(response.data as? InternalPayNowResponse)?.let {
|
||||
val payLoad = it.providerPayload
|
||||
startNaviUpiPayment(
|
||||
naviPayUpiUriKey = payLoad?.naviPayUpiUriKey,
|
||||
tstoreOrderId = payLoad?.tstoreOrderReferenceId.orEmpty(),
|
||||
metaData = Gson().toJson(payLoad?.metadata),
|
||||
bankAccountId = selectedBankAccount.value?.accountId.orEmpty(),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
_showPayNowLoader.update { false }
|
||||
updateBottomSheetUIState(
|
||||
true,
|
||||
WebPaymentScreenState.Error(
|
||||
PaymentErrorData(error = response.toGenericErrorResponse())
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchPayNowResponse(accountId: String, linkedAccountType: String) =
|
||||
paymentRepository.postPayNow(
|
||||
token = token,
|
||||
PayAmountRequest(
|
||||
UpiLinkedAccountPaymentInstrument.PAYMENT_INSTRUMENT_TYPE,
|
||||
PayAmountRequest.SelectedMethodDetails(
|
||||
payerBankAccountId = accountId,
|
||||
accountType = linkedAccountType,
|
||||
),
|
||||
),
|
||||
getPMSMetricInfo(
|
||||
screenName = NaviPaymentAnalyticScreenName.WEB_PAYMENT_SCREEN.screenName
|
||||
),
|
||||
)
|
||||
|
||||
fun onBankAccountSelected(linkedAccountEntity: LinkedAccountEntity) {
|
||||
_selectedBankAccount.update { linkedAccountEntity }
|
||||
updateMainCtaState()
|
||||
}
|
||||
|
||||
fun finishWithResult(finishCallback: () -> Unit) {
|
||||
updateBottomSheetUIState(showBottomSheet = false)
|
||||
viewModelScope.launch(Dispatchers.Main) {
|
||||
delay(150)
|
||||
finishCallback.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun startAction(
|
||||
activity: Activity,
|
||||
launcher: ActivityResultLauncher<Intent>,
|
||||
@@ -822,7 +769,7 @@ constructor(
|
||||
WebPaymentScreenEffect.SetResultAndFinish(status = FAILURE)
|
||||
)
|
||||
} else {
|
||||
updateBottomSheetUIState(true)
|
||||
showBottomSheet()
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -830,23 +777,25 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun finishWithError() {
|
||||
_effect.emit(
|
||||
WebPaymentScreenEffect.SetResultAndFinish(
|
||||
status = FAILURE,
|
||||
error =
|
||||
GenericErrorResponse(
|
||||
title =
|
||||
AppServiceManager.application.resources.getString(
|
||||
CommonR.string.something_went_wrong
|
||||
),
|
||||
message =
|
||||
AppServiceManager.application.resources.getString(
|
||||
R.string.generic_error_description
|
||||
),
|
||||
),
|
||||
private fun finishWithError() {
|
||||
viewModelScope.safeLaunch {
|
||||
_effect.emit(
|
||||
WebPaymentScreenEffect.SetResultAndFinish(
|
||||
status = FAILURE,
|
||||
error =
|
||||
GenericErrorResponse(
|
||||
title =
|
||||
AppServiceManager.application.resources.getString(
|
||||
CommonR.string.something_went_wrong
|
||||
),
|
||||
message =
|
||||
AppServiceManager.application.resources.getString(
|
||||
R.string.generic_error_description
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleWebSendMoney() {
|
||||
@@ -865,4 +814,180 @@ constructor(
|
||||
linkedAccountsUseCase.execute(screenName = screenName, includeAllDetails = true).first()
|
||||
return accounts.any { it.accountType.contains("CREDIT").not() && it.isDisabled.not() }
|
||||
}
|
||||
|
||||
fun onPayButtonClick(
|
||||
activity: WebPaymentActivity,
|
||||
upiResultLauncher: ManagedActivityResultLauncher<Intent, ActivityResult>,
|
||||
) {
|
||||
val account = selectedBankAccount.value ?: return
|
||||
if (showPayNowLoader.value) return
|
||||
naviPaymentAnalytics.onPayNowClicked(baseAttributes = getAnalyticsParams())
|
||||
if (account.isMPinSet.not()) {
|
||||
naviPaymentAnalytics.onSetUpiPinBtnClick(
|
||||
webPaymentAction = webPayAction ?: WebPaymentAction.WEB_SEND_MONEY,
|
||||
webPaymentData = webPaymentData.toJsonObject(),
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
)
|
||||
updateLastTriggeredActionBeforeOnboarding(
|
||||
webPayAction ?: WebPaymentAction.WEB_SEND_MONEY
|
||||
)
|
||||
handleMPinSetup(activity, upiResultLauncher)
|
||||
} else {
|
||||
makePayment(account)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleBackClick() {
|
||||
naviPaymentAnalytics.onBackPressed(getAnalyticsParams())
|
||||
finishWithResult(status = TransactionStatus.USER_CANCELLED_TRANSACTION.name)
|
||||
}
|
||||
|
||||
fun finishWithResult(
|
||||
status: String,
|
||||
error: GenericErrorResponse? = null,
|
||||
additionalParams: Map<String, String> = emptyMap(),
|
||||
) {
|
||||
viewModelScope.safeLaunch(Dispatchers.IO) {
|
||||
hideBottomSheet()
|
||||
delay(150)
|
||||
_effect.emit(
|
||||
WebPaymentScreenEffect.SetResultAndFinish(
|
||||
status = status,
|
||||
error = error,
|
||||
additionalParams = additionalParams,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun makePayment(account: LinkedAccountEntity) {
|
||||
showPayNowLoader()
|
||||
viewModelScope.safeLaunch(Dispatchers.IO) {
|
||||
naviUpiPaymentProcessor.makePayment(
|
||||
account = account,
|
||||
isDiscountApplied = false,
|
||||
discountInfo = null,
|
||||
analyticScreenName = screenName,
|
||||
naviPaymentScreen =
|
||||
NaviPaymentScreenType
|
||||
.MINI_PAYMENT_SCREEN, // Enum not present for web in backend.
|
||||
paymentToken = token,
|
||||
baseAttributes = getAnalyticsParams(),
|
||||
onInitialChecksFailure = {
|
||||
showErrorBottomSheet(
|
||||
error = it,
|
||||
errorReason = PMSErrorReason.NoActiveLiteAccountPSP,
|
||||
)
|
||||
},
|
||||
onOnboardingTriggered = { hideBottomSheet() },
|
||||
onOnboardingCancelled = {
|
||||
showBottomSheet()
|
||||
stopPayNowLoader()
|
||||
},
|
||||
onOnboardingCompleted = { showBottomSheet() },
|
||||
onBeforePayNowApiCall = {},
|
||||
onPayNowSuccess = { payNowResponse = it },
|
||||
onPayNowFailure = {
|
||||
stopPayNowLoader()
|
||||
showErrorBottomSheet(it, PMSErrorReason.PayNowError)
|
||||
},
|
||||
onBeforeOpeningPinPage = { updateBottomSheetUIState(false) },
|
||||
onPinPageBack = {
|
||||
finishWithResult(
|
||||
status = TransactionStatus.USER_CANCELLED_TRANSACTION.name,
|
||||
error = null,
|
||||
additionalParams =
|
||||
mapOf(
|
||||
TRANSACTION_REFERENCE_ID to
|
||||
payNowResponse?.transactionReferenceId.orEmpty(),
|
||||
PAYMENT_ORDER_REFERNCE_ID to
|
||||
payNowResponse?.paymentOrderReferenceId.orEmpty(),
|
||||
),
|
||||
)
|
||||
},
|
||||
onPinPageError = {
|
||||
finishWithResult(
|
||||
status = FAILURE,
|
||||
error = null,
|
||||
additionalParams =
|
||||
mapOf(
|
||||
TRANSACTION_REFERENCE_ID to
|
||||
payNowResponse?.transactionReferenceId.orEmpty(),
|
||||
PAYMENT_ORDER_REFERNCE_ID to
|
||||
payNowResponse?.paymentOrderReferenceId.orEmpty(),
|
||||
),
|
||||
)
|
||||
},
|
||||
onPinPageSuccess = { upiNavigationResponse ->
|
||||
executeSendMoney(upiNavigationResponse, account)
|
||||
stopPayNowLoader()
|
||||
finishWithResult(
|
||||
status = SUCCESS,
|
||||
error = null,
|
||||
additionalParams =
|
||||
mapOf(
|
||||
TRANSACTION_REFERENCE_ID to
|
||||
payNowResponse?.transactionReferenceId.orEmpty(),
|
||||
PAYMENT_ORDER_REFERNCE_ID to
|
||||
payNowResponse?.paymentOrderReferenceId.orEmpty(),
|
||||
UPI_REQUEST_ID to
|
||||
upiNavigationResponse.pmsSendMoneyStatus.upiRequestId,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPayNowLoader() {
|
||||
_showPayNowLoader.update { true }
|
||||
}
|
||||
|
||||
private fun executeSendMoney(
|
||||
upiNavigationResponse: UpiNavigationResponse,
|
||||
account: LinkedAccountEntity,
|
||||
) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
pmsSendMoneyUseCase.performChecksAndExecuteSendMoney(
|
||||
onInitialChecksFailure = {
|
||||
showErrorBottomSheet(it.toGenericError(), PMSErrorReason.UPIError)
|
||||
},
|
||||
naviUpiTransactionInfo =
|
||||
NaviUpiTransactionInfo(
|
||||
naviPayUpiUriKey = upiNavigationResponse.intentUri,
|
||||
txnTimeStamp = upiNavigationResponse.transactionTimestamp,
|
||||
credBlock = upiNavigationResponse.pmsSendMoneyStatus.credBlock,
|
||||
upiRequestId = upiNavigationResponse.pmsSendMoneyStatus.upiRequestId,
|
||||
selectedBankAccountId = account.accountId,
|
||||
metaData = upiNavigationResponse.metaData,
|
||||
onboardingDataEntity =
|
||||
upiNavigationResponse.pmsSendMoneyStatus.onboardingDataEntity,
|
||||
),
|
||||
tstoreOrderId = upiNavigationResponse.tstoreOrderReferenceId,
|
||||
screenName = NaviPaymentAnalyticScreenName.WEB_PAYMENT_SCREEN.screenName,
|
||||
paymentAmount = paymentAmount.value.toString(),
|
||||
onPaymentSuccess = {},
|
||||
onPaymentFailure = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopPayNowLoader() {
|
||||
_showPayNowLoader.update { false }
|
||||
}
|
||||
|
||||
private fun showErrorBottomSheet(error: GenericErrorResponse?, errorReason: PMSErrorReason) {
|
||||
updateBottomSheetUIState(
|
||||
true,
|
||||
WebPaymentScreenState.Error(PaymentErrorData(error = error, errorReason = errorReason)),
|
||||
)
|
||||
}
|
||||
|
||||
private fun showBottomSheet() {
|
||||
updateBottomSheetUIState(true)
|
||||
}
|
||||
|
||||
private fun hideBottomSheet() {
|
||||
updateBottomSheetUIState(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,6 @@ sealed class PMSErrorReason : Parcelable, ErrorReason {
|
||||
data object Unknown : PMSErrorReason()
|
||||
|
||||
data object PaymentsServiceDown : PMSErrorReason()
|
||||
|
||||
data object NoActiveLiteAccountPSP : PMSErrorReason()
|
||||
}
|
||||
|
||||
@@ -163,4 +163,5 @@
|
||||
<string name="other_apps_platform_fee_value">₹2 to ₹5</string>
|
||||
<string name="platform_fee_value">₹0</string>
|
||||
<string name="applicable_on_all_bills_and_recharges">Applicable on all bills and recharges.</string>
|
||||
<string name="empty_payment_token">EMPTY_PAYMENT_TOKEN</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user