NTP-50498 | PS | Payments kill switch (#15664)
This commit is contained in:
@@ -174,6 +174,8 @@ object FirebaseRemoteConfigHelper {
|
||||
"NAVI_PMT_TRANSACTION_STORE_EXPIRY_TIME_MILLIS"
|
||||
const val NAVI_PMT_ONE_CLICK_CHECKOUT_API_TIMEOUT_MILLIS =
|
||||
"NAVI_PMT_ONE_CLICK_CHECKOUT_API_TIMEOUT_MILLIS"
|
||||
const val ENABLE_NAVI_PAYMENT_KILL_SWITCH_MECHANISM =
|
||||
"ENABLE_NAVI_PAYMENT_KILL_SWITCH_MECHANISM"
|
||||
|
||||
// BBPS
|
||||
const val NAVI_BBPS_REWARDS_NUDGE_CACHE_TTL_IN_MILLIS =
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.navi.payment.nativepayment.model.RewardsInfoV2
|
||||
import com.navi.payment.nativepayment.model.WebPaymentAction
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatusRequest
|
||||
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.utils.putIfNotNullAndNotEmpty
|
||||
@@ -180,6 +181,32 @@ class NaviPaymentAnalytics private constructor() {
|
||||
eventValues = eventAttributes,
|
||||
)
|
||||
}
|
||||
|
||||
fun onErrorOccurredInGetQuerySnapshot(exception: Exception) {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPmt_UptimePoller_ErrorOccurredInGetQuerySnapshot",
|
||||
mapOf(
|
||||
"exception" to exception.toString(),
|
||||
"exceptionMessage" to exception.message.toString(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun onErrorOccurredInProcessingQuerySnapshot(exception: Exception) {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPmt_UptimePoller_ErrorOccurredInProcessingQuerySnapshot",
|
||||
mapOf(
|
||||
"exception" to exception.toString(),
|
||||
"exceptionMessage" to exception.message.toString(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun onPaymentsUptimePollerSyncSuccess() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPmt_UptimePoller_PaymentsUptimePollerSyncSuccess"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
inner class NPSMainScreen {
|
||||
@@ -1503,6 +1530,16 @@ class NaviPaymentAnalytics private constructor() {
|
||||
)
|
||||
}
|
||||
|
||||
fun onBottomSheetCloseClicked(
|
||||
bottomSheetState: String,
|
||||
error: NaviPaymentErrorConfig? = null,
|
||||
) {
|
||||
NaviTrackEvent.trackEvent(
|
||||
"NaviPMT_OneClickCheckoutScreen_BottomSheetCloseClicked",
|
||||
mapOf("bottom_sheet_state" to bottomSheetState, "error" to error.toString()),
|
||||
)
|
||||
}
|
||||
|
||||
fun onRedirectingBottomSheetClosed(selectedBankAccountId: String) {
|
||||
NaviTrackEvent.trackEvent(
|
||||
"NaviPMT_OneClickCheckoutScreen_RedirectingBottomSheetClosed",
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.common.usecase
|
||||
|
||||
import com.google.firebase.firestore.QuerySnapshot
|
||||
import com.navi.base.utils.FirestoreDataProvider
|
||||
import com.navi.common.utils.NaviApiPoller
|
||||
import com.navi.pay.utils.parallelMap
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalytics
|
||||
import com.navi.payment.nativepayment.db.model.toPaymentsUptimeEntity
|
||||
import com.navi.payment.nativepayment.repository.PaymentsUptimeRepository
|
||||
import com.navi.payment.utils.Constants.FIRESTORE_PAYMENTS_UPTIME_COLLECTION_PATH
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
@Singleton
|
||||
class PaymentsUptimePollerUseCase
|
||||
@Inject
|
||||
constructor(
|
||||
private val firestoreDataProvider: FirestoreDataProvider,
|
||||
private val paymentsUptimeRepository: PaymentsUptimeRepository,
|
||||
) {
|
||||
private val PAYMENTS_UPTIME_POLLING_INTERVAL = 5.minutes
|
||||
private val paymentsUptimePoller by lazy {
|
||||
NaviApiPoller(repeatInterval = PAYMENTS_UPTIME_POLLING_INTERVAL)
|
||||
}
|
||||
private val naviPaymentAnalytics = NaviPaymentAnalytics.INSTANCE.CommonAnalytics()
|
||||
|
||||
suspend fun executePollerForPaymentsUptime() {
|
||||
paymentsUptimePoller.stopPolling()
|
||||
paymentsUptimePoller
|
||||
.startPolling {
|
||||
try {
|
||||
firestoreDataProvider.getQuerySnapShotForCollectionPath(
|
||||
collectionPath = FIRESTORE_PAYMENTS_UPTIME_COLLECTION_PATH
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
naviPaymentAnalytics.onErrorOccurredInGetQuerySnapshot(exception = exception)
|
||||
paymentsUptimePoller.stopPolling()
|
||||
}
|
||||
}
|
||||
.collect {
|
||||
try {
|
||||
val paymentsUptimeQuerySnapShot = it as? QuerySnapshot?
|
||||
processQuerySnapShotForPaymentsUptime(
|
||||
paymentsUptimeQuerySnapShot = paymentsUptimeQuerySnapShot
|
||||
)
|
||||
naviPaymentAnalytics.onPaymentsUptimePollerSyncSuccess()
|
||||
} catch (exception: Exception) {
|
||||
naviPaymentAnalytics.onErrorOccurredInProcessingQuerySnapshot(
|
||||
exception = exception
|
||||
)
|
||||
paymentsUptimePoller.stopPolling()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun processQuerySnapShotForPaymentsUptime(
|
||||
paymentsUptimeQuerySnapShot: QuerySnapshot?
|
||||
) {
|
||||
paymentsUptimeQuerySnapShot?.let { querySnapShot ->
|
||||
val paymentsUptimeEntityList =
|
||||
querySnapShot.documents.parallelMap { it.toPaymentsUptimeEntity() }
|
||||
|
||||
if (paymentsUptimeEntityList.isNotEmpty()) {
|
||||
paymentsUptimeRepository.deleteAllExistingDataAndInsertAll(
|
||||
uptimeEntityList = paymentsUptimeEntityList
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@ import com.navi.pay.R
|
||||
import com.navi.pay.common.arc.ui.ArcNudgeBottomSheetContent
|
||||
import com.navi.pay.common.model.view.CheckBalanceState
|
||||
import com.navi.pay.common.theme.color.NaviPayColor
|
||||
import com.navi.pay.common.ui.BottomSheetContentWithVerticalPrimarySecondaryButton
|
||||
import com.navi.pay.common.ui.ImageWithCircularBackground
|
||||
import com.navi.pay.common.ui.LoaderRoundedButton
|
||||
import com.navi.pay.common.ui.NaviPayModalBottomSheet
|
||||
@@ -260,6 +261,39 @@ fun PaymentCheckoutFooter(
|
||||
is OneClickCheckoutFooterBottomSheetUiState.RedirectingBottomSheet -> {
|
||||
RedirectingBottomSheetContent(title = bottomSheetType.titleText)
|
||||
}
|
||||
is OneClickCheckoutFooterBottomSheetUiState.Error -> {
|
||||
BottomSheetContentWithVerticalPrimarySecondaryButton(
|
||||
iconId = bottomSheetType.errorConfig.iconResId,
|
||||
headerText = bottomSheetType.errorConfig.title,
|
||||
descriptionText = bottomSheetType.errorConfig.description,
|
||||
primaryButtonText =
|
||||
bottomSheetType.errorConfig.firstPrimaryButtonConfig.text,
|
||||
secondaryButtonText =
|
||||
bottomSheetType.errorConfig.firstSecondaryButtonConfig?.text,
|
||||
onPrimaryButtonClicked = {
|
||||
coroutineScope
|
||||
.launch { sheetState.hide() }
|
||||
.invokeOnCompletion {
|
||||
naviCheckoutViewModel.onBottomSheetCloseClicked()
|
||||
}
|
||||
},
|
||||
onSecondaryButtonClicked = {
|
||||
coroutineScope
|
||||
.launch { sheetState.hide() }
|
||||
.invokeOnCompletion {
|
||||
naviCheckoutViewModel.onBottomSheetCloseClicked()
|
||||
}
|
||||
},
|
||||
onDismissClicked = {
|
||||
coroutineScope
|
||||
.launch { sheetState.hide() }
|
||||
.invokeOnCompletion {
|
||||
naviCheckoutViewModel.onBottomSheetCloseClicked()
|
||||
}
|
||||
},
|
||||
shouldShowCloseIcon = bottomSheetType.errorConfig.showDismissIcon,
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,28 +14,35 @@ import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.payment.nativepayment.db.converter.BanksEntityConverter
|
||||
import com.navi.payment.nativepayment.db.converter.PaymentsUptimeStatusConverter
|
||||
import com.navi.payment.nativepayment.db.dao.BankListDao
|
||||
import com.navi.payment.nativepayment.db.dao.PaymentsUptimeDao
|
||||
import com.navi.payment.nativepayment.db.dao.TransactionStatusRequestDao
|
||||
import com.navi.payment.nativepayment.db.model.BankListEntity
|
||||
import com.navi.payment.nativepayment.db.model.PaymentsUptimeEntity
|
||||
import com.navi.payment.nativepayment.db.model.TransactionStatusRequestEntity
|
||||
import com.navi.payment.nativepayment.model.transactionStatusRequest.TransactionStatus
|
||||
|
||||
@Database(
|
||||
entities = [TransactionStatusRequestEntity::class, BankListEntity::class],
|
||||
version = 3,
|
||||
entities =
|
||||
[TransactionStatusRequestEntity::class, BankListEntity::class, PaymentsUptimeEntity::class],
|
||||
version = 4,
|
||||
exportSchema = false,
|
||||
)
|
||||
@TypeConverters(BanksEntityConverter::class)
|
||||
@TypeConverters(BanksEntityConverter::class, PaymentsUptimeStatusConverter::class)
|
||||
abstract class NaviPaymentAppDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun transactionStatusRequestDao(): TransactionStatusRequestDao
|
||||
|
||||
abstract fun bankListDao(): BankListDao
|
||||
|
||||
abstract fun paymentUptimeDao(): PaymentsUptimeDao
|
||||
|
||||
companion object {
|
||||
const val NAVI_PAYMENT_DATABASE_NAME = "navi-payment.db"
|
||||
const val TRANSACTION_STATUS_REQUEST_TABLE = "transaction_status_request"
|
||||
const val BANKS_TABLE = "banks"
|
||||
const val UPTIME_STATUS_TABLE = "uptime_status"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,3 +112,16 @@ val NAVI_PAYMENT_APP_DATABASE_MIGRATION_2_3 =
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val NAVI_PAYMENT_APP_DATABASE_MIGRATION_3_4 =
|
||||
object : Migration(3, 4) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS ${NaviPaymentAppDatabase.UPTIME_STATUS_TABLE} (" +
|
||||
"`vertical` TEXT PRIMARY KEY NOT NULL, " +
|
||||
"`downtimeTitle` TEXT, " +
|
||||
"`downtimeDescription` TEXT, " +
|
||||
"`status` TEXT NOT NULL, "
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ constructor(private val naviPaymentAppDatabase: NaviPaymentAppDatabase) : NaviMo
|
||||
NaviPaymentAppDatabase.BANKS_TABLE -> {
|
||||
runWithCatching { naviPaymentAppDatabase.bankListDao().deleteAll() }
|
||||
}
|
||||
NaviPaymentAppDatabase.UPTIME_STATUS_TABLE -> {
|
||||
runWithCatching { naviPaymentAppDatabase.paymentUptimeDao().deleteAll() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.db.converter
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.navi.payment.nativepayment.db.model.PaymentsUptimeStatus
|
||||
|
||||
class PaymentsUptimeStatusConverter {
|
||||
|
||||
@TypeConverter
|
||||
fun fromPaymentsUptimeStatus(uptimeStatus: PaymentsUptimeStatus): String {
|
||||
return uptimeStatus.name
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun toPaymentsUptimeStatus(uptimeStatus: String): PaymentsUptimeStatus {
|
||||
return PaymentsUptimeStatus.valueOf(uptimeStatus)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import androidx.room.RawQuery
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.Upsert
|
||||
import androidx.sqlite.db.SupportSQLiteQuery
|
||||
import com.navi.payment.nativepayment.db.NaviPaymentAppDatabase.Companion.UPTIME_STATUS_TABLE
|
||||
import com.navi.payment.nativepayment.db.model.PaymentsUptimeEntity
|
||||
|
||||
@Dao
|
||||
interface PaymentsUptimeDao {
|
||||
@Upsert suspend fun insertAll(paymentsUptimeEntityList: List<PaymentsUptimeEntity>)
|
||||
|
||||
@Query("DELETE FROM $UPTIME_STATUS_TABLE") suspend fun deleteAll()
|
||||
|
||||
@RawQuery suspend fun deleteRows(query: SupportSQLiteQuery): Int
|
||||
|
||||
@Query("SELECT * FROM $UPTIME_STATUS_TABLE WHERE vertical = :vertical")
|
||||
suspend fun getPaymentsUptimeEntityForVertical(vertical: String): List<PaymentsUptimeEntity>
|
||||
|
||||
@Transaction
|
||||
suspend fun deleteAllExistingDataAndInsertAll(uptimeEntityList: List<PaymentsUptimeEntity>) {
|
||||
deleteAll()
|
||||
insertAll(uptimeEntityList)
|
||||
}
|
||||
}
|
||||
@@ -48,4 +48,9 @@ object NaviPaymentDbModule {
|
||||
@Provides
|
||||
fun providesBankListDao(naviPaymentAppDatabase: NaviPaymentAppDatabase) =
|
||||
naviPaymentAppDatabase.bankListDao()
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun providesPaymentsUptimeDao(naviPaymentAppDatabase: NaviPaymentAppDatabase) =
|
||||
naviPaymentAppDatabase.paymentUptimeDao()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.db.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverters
|
||||
import com.google.firebase.firestore.DocumentSnapshot
|
||||
import com.navi.pay.utils.getIfscForBankUptime
|
||||
import com.navi.payment.nativepayment.db.NaviPaymentAppDatabase.Companion.UPTIME_STATUS_TABLE
|
||||
import com.navi.payment.nativepayment.db.converter.PaymentsUptimeStatusConverter
|
||||
|
||||
@Entity(tableName = UPTIME_STATUS_TABLE)
|
||||
data class PaymentsUptimeEntity(
|
||||
@PrimaryKey @ColumnInfo("vertical") val vertical: String,
|
||||
@ColumnInfo("downtimeTitle") val downtimeTitle: String? = null,
|
||||
@ColumnInfo("downtimeDescription") val downtimeDescription: String? = null,
|
||||
@ColumnInfo("status")
|
||||
@TypeConverters(PaymentsUptimeStatusConverter::class)
|
||||
val status: PaymentsUptimeStatus,
|
||||
)
|
||||
|
||||
fun DocumentSnapshot.toPaymentsUptimeEntity(): PaymentsUptimeEntity {
|
||||
return PaymentsUptimeEntity(
|
||||
vertical = this.id.getIfscForBankUptime(),
|
||||
downtimeTitle = this.getString("downtimeTitle"),
|
||||
downtimeDescription = this.getString("downtimeDescription"),
|
||||
status =
|
||||
PaymentsUptimeStatus.getBankUptimeStatusFromString(
|
||||
bankUptimeStatus = this.getString("status") ?: ""
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.db.model
|
||||
|
||||
enum class PaymentsUptimeStatus {
|
||||
UP,
|
||||
WARNING,
|
||||
DOWN;
|
||||
|
||||
companion object {
|
||||
fun getBankUptimeStatusFromString(bankUptimeStatus: String): PaymentsUptimeStatus {
|
||||
return entries.singleOrNull { it.name.equals(bankUptimeStatus, ignoreCase = true) }
|
||||
?: UP
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
package com.navi.payment.nativepayment.model
|
||||
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentErrorConfig
|
||||
|
||||
data class OneClickCheckoutFooterBottomSheetStateHolder(
|
||||
val showBottomSheet: Boolean,
|
||||
val bottomSheetUIState: OneClickCheckoutFooterBottomSheetUiState,
|
||||
@@ -25,4 +27,7 @@ sealed class OneClickCheckoutFooterBottomSheetUiState {
|
||||
|
||||
data class RedirectingBottomSheet(val titleText: String) :
|
||||
OneClickCheckoutFooterBottomSheetUiState()
|
||||
|
||||
data class Error(val errorConfig: NaviPaymentErrorConfig) :
|
||||
OneClickCheckoutFooterBottomSheetUiState()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.repository
|
||||
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.ENABLE_NAVI_PAYMENT_KILL_SWITCH_MECHANISM
|
||||
import com.navi.payment.nativepayment.db.dao.PaymentsUptimeDao
|
||||
import com.navi.payment.nativepayment.db.model.PaymentsUptimeEntity
|
||||
import com.navi.payment.nativepayment.db.model.PaymentsUptimeStatus
|
||||
import javax.inject.Inject
|
||||
|
||||
class PaymentsUptimeRepository
|
||||
@Inject
|
||||
constructor(private val paymentsUptimeDao: PaymentsUptimeDao) {
|
||||
|
||||
suspend fun getPaymentsUptimeEntityForVertical(vertical: String): PaymentsUptimeEntity {
|
||||
|
||||
if (!FirebaseRemoteConfigHelper.getBoolean(ENABLE_NAVI_PAYMENT_KILL_SWITCH_MECHANISM)) {
|
||||
return PaymentsUptimeEntity(vertical = vertical, status = PaymentsUptimeStatus.UP)
|
||||
}
|
||||
|
||||
val paymentsUptimeEntity = paymentsUptimeDao.getPaymentsUptimeEntityForVertical(vertical)
|
||||
|
||||
return paymentsUptimeEntity.firstOrNull()
|
||||
?: PaymentsUptimeEntity(vertical = vertical, status = PaymentsUptimeStatus.UP)
|
||||
}
|
||||
|
||||
suspend fun deleteAllExistingDataAndInsertAll(uptimeEntityList: List<PaymentsUptimeEntity>) =
|
||||
paymentsUptimeDao.deleteAllExistingDataAndInsertAll(uptimeEntityList = uptimeEntityList)
|
||||
}
|
||||
@@ -12,20 +12,26 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.navi.base.AppServiceManager
|
||||
import com.navi.base.utils.ResourceProvider
|
||||
import com.navi.base.utils.orElse
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.common.upi.UpiDataType
|
||||
import com.navi.common.usecase.LitmusExperimentsUseCase
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.naviwidgets.R as WidgetsR
|
||||
import com.navi.pay.R as NaviPayR
|
||||
import com.navi.pay.common.setup.NaviPayManager
|
||||
import com.navi.pay.common.usecase.NaviPayConfigUseCase
|
||||
import com.navi.pay.common.viewmodel.NaviPayBaseVM.Companion.ERROR_DEFAULT_TAG
|
||||
import com.navi.pay.management.lite.models.NaviPayUpiLiteConfig
|
||||
import com.navi.pay.utils.UPI_LITE_CONFIG
|
||||
import com.navi.payment.R
|
||||
import com.navi.payment.model.common.PaymentSdkInitParams
|
||||
import com.navi.payment.model.initiatesdk.PaymentPrefetchDetail
|
||||
import com.navi.payment.model.initiatesdk.PaymentPrefetchMethodRequest
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalyticScreenName
|
||||
import com.navi.payment.nativepayment.common.usecase.PaymentsUptimePollerUseCase
|
||||
import com.navi.payment.nativepayment.common.usecase.TransactionStatusUseCase
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.ACTION_TYPE
|
||||
@@ -33,14 +39,20 @@ import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.PAYMENT_INITIATE_START_TIME
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.SCREEN_TYPE
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.UPI_LITE_MAX_PAYABLE_AMOUNT_PER_TRANSACTION
|
||||
import com.navi.payment.nativepayment.db.model.PaymentsUptimeStatus
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.NetBankingPaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.PaymentActionType
|
||||
import com.navi.payment.nativepayment.model.PaymentInitResponse
|
||||
import com.navi.payment.nativepayment.model.S2sPaymentMethodResponse
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.repository.PaymentsUptimeRepository
|
||||
import com.navi.payment.nativepayment.usecase.NetBankingUseCase
|
||||
import com.navi.payment.nativepayment.usecase.PmsLinkedAccountUseCase
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentBottomSheetButtonAction
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentButtonTheme
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentErrorButtonConfig
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentErrorConfig
|
||||
import com.navi.payment.nativepayment.utils.getPayloadBasedOnType
|
||||
import com.navi.payment.nativepayment.utils.toGenericErrorResponse
|
||||
import com.navi.payment.nativepayment.viewmodel.NaviPaymentBaseVM
|
||||
@@ -74,11 +86,21 @@ constructor(
|
||||
protected val transactionStatusUseCase: TransactionStatusUseCase,
|
||||
protected val litmusExperimentsUseCase: LitmusExperimentsUseCase,
|
||||
private val naviPayConfigUseCase: NaviPayConfigUseCase,
|
||||
private val paymentsUptimePollerUseCase: PaymentsUptimePollerUseCase,
|
||||
protected val paymentsUptimeRepository: PaymentsUptimeRepository,
|
||||
protected val resourceProvider: ResourceProvider,
|
||||
) : NaviPaymentBaseVM(screenName = NaviPaymentAnalyticScreenName.CHECKOUT_SCREEN.screenName) {
|
||||
|
||||
protected val _paymentResponse = MutableSharedFlow<PaymentInitResponse>(replay = 0)
|
||||
val paymentResponse = _paymentResponse.asSharedFlow()
|
||||
|
||||
init {
|
||||
updateUpiLiteConfig()
|
||||
viewModelScope.safeLaunch(Dispatchers.IO) {
|
||||
paymentsUptimePollerUseCase.executePollerForPaymentsUptime()
|
||||
}
|
||||
}
|
||||
|
||||
fun initiatePayment(paymentSdkInitParams: PaymentSdkInitParams) {
|
||||
viewModelScope.safeLaunch {
|
||||
initializePaymentSession(paymentSdkInitParams.paymentSource.orEmpty())
|
||||
@@ -211,7 +233,6 @@ constructor(
|
||||
protected suspend fun initializePaymentSession(source: String) {
|
||||
clearPaymentData()
|
||||
fetchPmsExperimentsData(source)
|
||||
updateUpiLiteConfig()
|
||||
paymentDataProvider.add(PAYMENT_INITIATE_START_TIME, System.currentTimeMillis())
|
||||
_paymentResponse.emit(PaymentInitResponse(isSuccess = false))
|
||||
}
|
||||
@@ -230,4 +251,35 @@ constructor(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
protected suspend fun isPaymentsServiceDown(source: String): NaviPaymentErrorConfig? {
|
||||
val paymentsUptimeEntity =
|
||||
paymentsUptimeRepository.getPaymentsUptimeEntityForVertical(source)
|
||||
return if (paymentsUptimeEntity.status == PaymentsUptimeStatus.DOWN) {
|
||||
NaviPaymentErrorConfig(
|
||||
iconResId = WidgetsR.drawable.ic_error_outlined,
|
||||
title =
|
||||
paymentsUptimeEntity.downtimeTitle.orElse(
|
||||
resourceProvider.getString(NaviPayR.string.np_psp_down_message_title)
|
||||
),
|
||||
description =
|
||||
paymentsUptimeEntity.downtimeDescription.orElse(
|
||||
resourceProvider.getString(NaviPayR.string.np_psp_down_message_desc)
|
||||
),
|
||||
buttonConfigs =
|
||||
listOf(
|
||||
NaviPaymentErrorButtonConfig(
|
||||
text = resourceProvider.getString(R.string.okay_got_it),
|
||||
type = NaviPaymentButtonTheme.Primary,
|
||||
action = NaviPaymentBottomSheetButtonAction.Dismiss,
|
||||
)
|
||||
),
|
||||
code = UNKNOWN_ERROR_CODE,
|
||||
tag = ERROR_DEFAULT_TAG,
|
||||
showDismissIcon = false,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import com.navi.payment.R
|
||||
import com.navi.payment.model.common.PaymentSdkInitParams
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalyticScreenName
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalytics
|
||||
import com.navi.payment.nativepayment.common.usecase.PaymentsUptimePollerUseCase
|
||||
import com.navi.payment.nativepayment.common.usecase.TransactionStatusUseCase
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.ACTION_TYPE
|
||||
@@ -81,9 +82,11 @@ import com.navi.payment.nativepayment.presentation.reducer.OneClickScreenContrac
|
||||
import com.navi.payment.nativepayment.presentation.reducer.OneClickScreenEffect
|
||||
import com.navi.payment.nativepayment.presentation.reducer.OneClickScreenEvent
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.repository.PaymentsUptimeRepository
|
||||
import com.navi.payment.nativepayment.usecase.NetBankingUseCase
|
||||
import com.navi.payment.nativepayment.usecase.PmsLinkedAccountUseCase
|
||||
import com.navi.payment.nativepayment.utils.Constants.NAVI_PAY_ACTION
|
||||
import com.navi.payment.nativepayment.utils.NaviPaymentErrorConfig
|
||||
import com.navi.payment.nativepayment.utils.getDiscountAdjustedAmount
|
||||
import com.navi.payment.nativepayment.utils.getPreferredSelectedAccount
|
||||
import com.navi.payment.nativepayment.utils.mapToLinkedAccountEntity
|
||||
@@ -143,7 +146,9 @@ constructor(
|
||||
transactionStatusUseCase: TransactionStatusUseCase,
|
||||
litmusExperimentsUseCase: LitmusExperimentsUseCase,
|
||||
naviPayConfigUseCase: NaviPayConfigUseCase,
|
||||
private val resourceProvider: ResourceProvider,
|
||||
paymentsUptimePollerUseCase: PaymentsUptimePollerUseCase,
|
||||
paymentsUptimeRepository: PaymentsUptimeRepository,
|
||||
resourceProvider: ResourceProvider,
|
||||
private val accountListCheckBalanceUseCase: AccountListCheckBalanceUseCase,
|
||||
private val naviPayPspManager: NaviPayPspManager,
|
||||
private val arcNudgeUseCase: ArcNudgeUseCase,
|
||||
@@ -159,6 +164,9 @@ constructor(
|
||||
transactionStatusUseCase = transactionStatusUseCase,
|
||||
litmusExperimentsUseCase = litmusExperimentsUseCase,
|
||||
naviPayConfigUseCase = naviPayConfigUseCase,
|
||||
paymentsUptimePollerUseCase = paymentsUptimePollerUseCase,
|
||||
paymentsUptimeRepository = paymentsUptimeRepository,
|
||||
resourceProvider = resourceProvider,
|
||||
),
|
||||
OneClickScreenContract {
|
||||
|
||||
@@ -246,6 +254,10 @@ constructor(
|
||||
}
|
||||
|
||||
is OneClickScreenEvent.OnBankAccountItemClicked -> {
|
||||
isPaymentsServiceDown(paymentSource?.name.orEmpty())?.let {
|
||||
handlePaymentsDowntime(it)
|
||||
return@safeLaunch
|
||||
}
|
||||
navigationScreen = NaviPaymentScreenType.FULL_PAYMENT_SCREEN
|
||||
naviPaymentAnalytics.onBankAccountClicked(
|
||||
selectedBankAccountId = state.value.selectedAccount?.accountId.orEmpty()
|
||||
@@ -617,6 +629,10 @@ constructor(
|
||||
state.value.selectedAccount?.eligibilityState?.isAccountEligible?.not().orFalse()
|
||||
|
||||
private suspend fun handleCtaClicked(generateToken: () -> Unit) {
|
||||
isPaymentsServiceDown(paymentSource?.name.orEmpty())?.let {
|
||||
handlePaymentsDowntime(it)
|
||||
return
|
||||
}
|
||||
when (ctaAction) {
|
||||
CheckoutCtaAction.SEND_MONEY_NAVIGATION -> {
|
||||
navigationScreen = NaviPaymentScreenType.ONE_CLICK_CHECKOUT_SCREEN
|
||||
@@ -792,8 +808,14 @@ constructor(
|
||||
selectedBankAccountId = state.value.selectedAccount?.accountId.orEmpty()
|
||||
)
|
||||
} else {
|
||||
naviPaymentAnalytics.onRedirectingBottomSheetClosed(
|
||||
selectedBankAccountId = state.value.selectedAccount?.accountId.orEmpty()
|
||||
val error =
|
||||
(bottomSheetStateHolder.value.bottomSheetUIState
|
||||
as? OneClickCheckoutFooterBottomSheetUiState.Error)
|
||||
?.errorConfig
|
||||
naviPaymentAnalytics.onBottomSheetCloseClicked(
|
||||
bottomSheetState =
|
||||
bottomSheetStateHolder.value.bottomSheetUIState::class.java.simpleName,
|
||||
error = error,
|
||||
)
|
||||
}
|
||||
updateBottomSheetUIState(
|
||||
@@ -1108,4 +1130,11 @@ constructor(
|
||||
it <= AppServiceManager.appVersionCode
|
||||
} ?: false)
|
||||
}
|
||||
|
||||
private fun handlePaymentsDowntime(errorConfig: NaviPaymentErrorConfig) {
|
||||
updateBottomSheetUIState(
|
||||
showBottomSheet = true,
|
||||
bottomSheetUIState = OneClickCheckoutFooterBottomSheetUiState.Error(errorConfig),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * Copyright © 2024-2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
@@ -27,4 +27,6 @@ sealed class PMSErrorReason : Parcelable, ErrorReason {
|
||||
data object TokenNotFoundError : PMSErrorReason()
|
||||
|
||||
data object Unknown : PMSErrorReason()
|
||||
|
||||
data object PaymentsServiceDown : PMSErrorReason()
|
||||
}
|
||||
|
||||
@@ -170,6 +170,9 @@ object Constants {
|
||||
const val SCREEN_NAME = "screen_name"
|
||||
const val IS_AMOUNT_READ_ONLY = "is_amount_read_only"
|
||||
|
||||
// Firestore
|
||||
const val FIRESTORE_PAYMENTS_UPTIME_COLLECTION_PATH = "navipmt-uptime-status"
|
||||
|
||||
// CARDS
|
||||
const val CARD_VALIDATION_DEBOUNCE_TIME_IN_MILLIS = 50L
|
||||
const val DEFAULT_MIN_CVV_LENGTH = 3
|
||||
|
||||
Reference in New Issue
Block a user