NTP-14194 | Vedant Aggarwal | Supported PSP changes (#14979)
This commit is contained in:
@@ -9,7 +9,6 @@ package com.navi.pay.common.model.config
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.pay.common.model.view.NaviPayFlowType
|
||||
import com.navi.pay.common.model.view.PspType
|
||||
|
||||
data class NaviPayPspSelectionConfig(
|
||||
@SerializedName("config") val config: PspSelectionConfigContent = PspSelectionConfigContent(),
|
||||
@@ -17,14 +16,6 @@ data class NaviPayPspSelectionConfig(
|
||||
)
|
||||
|
||||
data class PspSelectionConfigContent(
|
||||
@SerializedName("flowToMandatoryBucketMap")
|
||||
val flowToMandatoryBucketMap: Map<NaviPayFlowType, String> =
|
||||
mapOf(
|
||||
NaviPayFlowType.LITE_AUTO_TOP_UP to "mandate_1",
|
||||
NaviPayFlowType.UPI_INTERNATIONAL to "mandate_2",
|
||||
NaviPayFlowType.RCC_BILL_PAYMENTS to "mandate_3",
|
||||
NaviPayFlowType.EMI_CONVERSION to "mandate_4",
|
||||
),
|
||||
@SerializedName("flowToRoutingBucketMap")
|
||||
val flowToRoutingBucketMap: Map<NaviPayFlowType, String> =
|
||||
mapOf(
|
||||
@@ -34,13 +25,5 @@ data class PspSelectionConfigContent(
|
||||
NaviPayFlowType.CHECK_BALANCE to "bucket_4",
|
||||
NaviPayFlowType.PIN_MANAGEMENT to "bucket_4",
|
||||
NaviPayFlowType.QR_HANDLING to "bucket_5",
|
||||
),
|
||||
@SerializedName("mandatoryBucketToPspListMap")
|
||||
val mandatoryBucketToPspListMap: Map<String, List<PspType>> =
|
||||
mapOf(
|
||||
"mandate_1" to listOf(PspType.JUSPAY),
|
||||
"mandate_2" to listOf(PspType.JUSPAY),
|
||||
"mandate_3" to listOf(PspType.JUSPAY),
|
||||
"mandate_4" to listOf(PspType.JUSPAY),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.navi.pay.common.setup.model.NaviPayCustomerStatus
|
||||
import com.navi.pay.common.utils.toggleNaviPayIntentActivityEnableState
|
||||
import com.navi.pay.onboarding.binding.repository.NaviPayOnboardingRepository
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class NaviPayCustomerStatusHandler
|
||||
@Inject
|
||||
@@ -23,51 +25,61 @@ constructor(
|
||||
) {
|
||||
|
||||
suspend fun getAllCustomerOnboardingData() =
|
||||
naviPayOnboardingRepository.getAllCustomerOnboardingData()
|
||||
withContext(Dispatchers.IO) { naviPayOnboardingRepository.getAllCustomerOnboardingData() }
|
||||
|
||||
suspend fun getCustomerStatus(pspType: PspType): NaviPayCustomerStatus {
|
||||
val customerOnboardingEntity =
|
||||
naviPayOnboardingRepository.getCustomerOnboardingEntity(pspType = pspType)
|
||||
return customerOnboardingEntity?.customerStatus ?: NaviPayCustomerStatus.NOT_SET
|
||||
return withContext(Dispatchers.IO) {
|
||||
val customerOnboardingEntity =
|
||||
naviPayOnboardingRepository.getCustomerOnboardingEntity(pspType = pspType)
|
||||
customerOnboardingEntity?.customerStatus ?: NaviPayCustomerStatus.NOT_SET
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun isUserOnboarded(pspType: PspType): Boolean {
|
||||
val customerOnboardingEntity =
|
||||
naviPayOnboardingRepository.getCustomerOnboardingEntity(pspType = pspType)
|
||||
return customerOnboardingEntity?.customerStatus == NaviPayCustomerStatus.LINKED_VPA
|
||||
return withContext(Dispatchers.IO) {
|
||||
val customerOnboardingEntity =
|
||||
naviPayOnboardingRepository.getCustomerOnboardingEntity(pspType = pspType)
|
||||
customerOnboardingEntity?.customerStatus == NaviPayCustomerStatus.LINKED_VPA
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun isUserOnboardedForAnyPsp(): Boolean {
|
||||
val customerEntityList = naviPayOnboardingRepository.getAllCustomerOnboardingData()
|
||||
|
||||
return customerEntityList.any { onboardingDataEntity ->
|
||||
onboardingDataEntity.customerStatus == NaviPayCustomerStatus.LINKED_VPA
|
||||
return withContext(Dispatchers.IO) {
|
||||
val customerEntityList = naviPayOnboardingRepository.getAllCustomerOnboardingData()
|
||||
customerEntityList.any { onboardingDataEntity ->
|
||||
onboardingDataEntity.customerStatus == NaviPayCustomerStatus.LINKED_VPA
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun isUserDeviceBoundForAnyPsp(): Boolean {
|
||||
val customerEntityList = naviPayOnboardingRepository.getAllCustomerOnboardingData()
|
||||
|
||||
return customerEntityList.any { onboardingDataEntity ->
|
||||
onboardingDataEntity.customerStatus.isBound
|
||||
return withContext(Dispatchers.IO) {
|
||||
val customerEntityList = naviPayOnboardingRepository.getAllCustomerOnboardingData()
|
||||
customerEntityList.any { onboardingDataEntity ->
|
||||
onboardingDataEntity.customerStatus.isBound
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getCustomerStatusMap(): Map<PspType, NaviPayCustomerStatus> {
|
||||
val customerEntityList = naviPayOnboardingRepository.getAllCustomerOnboardingData()
|
||||
return customerEntityList.associate { it.pspType to it.customerStatus }
|
||||
return withContext(Dispatchers.IO) {
|
||||
val customerEntityList = naviPayOnboardingRepository.getAllCustomerOnboardingData()
|
||||
customerEntityList.associate { it.pspType to it.customerStatus }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateCustomerStatusAndHandleNaviPayIntentActivityState(
|
||||
pspType: PspType,
|
||||
customerStatus: NaviPayCustomerStatus,
|
||||
) {
|
||||
naviPayOnboardingRepository.upsertCustomerOnboardingDataEntity(
|
||||
pspType = pspType,
|
||||
customerStatus = customerStatus,
|
||||
)
|
||||
naviPaySessionHelper.setCustomerStatus(customerStatus = customerStatus.name)
|
||||
checkAndUpdateNaviPayIntentActivity()
|
||||
withContext(Dispatchers.IO) {
|
||||
naviPayOnboardingRepository.upsertCustomerOnboardingDataEntity(
|
||||
pspType = pspType,
|
||||
customerStatus = customerStatus,
|
||||
)
|
||||
naviPaySessionHelper.setCustomerStatus(customerStatus = customerStatus.name)
|
||||
checkAndUpdateNaviPayIntentActivity()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun upsertCustomerOnboardingDataEntity(
|
||||
@@ -76,28 +88,34 @@ constructor(
|
||||
merchantCustomerId: String? = null,
|
||||
deviceFingerPrint: String? = null,
|
||||
) {
|
||||
naviPayOnboardingRepository.upsertCustomerOnboardingDataEntity(
|
||||
pspType = pspType,
|
||||
customerStatus = customerStatus,
|
||||
merchantCustomerId = merchantCustomerId,
|
||||
deviceFingerPrint = deviceFingerPrint,
|
||||
)
|
||||
checkAndUpdateNaviPayIntentActivity()
|
||||
withContext(Dispatchers.IO) {
|
||||
naviPayOnboardingRepository.upsertCustomerOnboardingDataEntity(
|
||||
pspType = pspType,
|
||||
customerStatus = customerStatus,
|
||||
merchantCustomerId = merchantCustomerId,
|
||||
deviceFingerPrint = deviceFingerPrint,
|
||||
)
|
||||
checkAndUpdateNaviPayIntentActivity()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun checkAndUpdateNaviPayIntentActivity() {
|
||||
if (isUserOnboardedForAnyPsp()) {
|
||||
toggleNaviPayIntentActivityEnableState(shouldEnable = true)
|
||||
} else if (
|
||||
FirebaseRemoteConfigHelper.getBoolean(
|
||||
key = FirebaseRemoteConfigHelper.NAVI_PAY_INTENT_ACTIVITY_CHECK_ENABLED,
|
||||
defaultValue = true,
|
||||
)
|
||||
) {
|
||||
toggleNaviPayIntentActivityEnableState(shouldEnable = false)
|
||||
withContext(Dispatchers.IO) {
|
||||
if (isUserOnboardedForAnyPsp()) {
|
||||
toggleNaviPayIntentActivityEnableState(shouldEnable = true)
|
||||
} else if (
|
||||
FirebaseRemoteConfigHelper.getBoolean(
|
||||
key = FirebaseRemoteConfigHelper.NAVI_PAY_INTENT_ACTIVITY_CHECK_ENABLED,
|
||||
defaultValue = true,
|
||||
)
|
||||
) {
|
||||
toggleNaviPayIntentActivityEnableState(shouldEnable = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getCustomerOnboardingEntity(pspType: PspType) =
|
||||
naviPayOnboardingRepository.getCustomerOnboardingEntity(pspType)
|
||||
withContext(Dispatchers.IO) {
|
||||
naviPayOnboardingRepository.getCustomerOnboardingEntity(pspType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ constructor(
|
||||
pspType: PspType,
|
||||
): Boolean =
|
||||
linkedAccountEntity.vpaEntityList.any { vpaEntity ->
|
||||
// TODO: Multibank - Add VPA status check in M1 Account Management
|
||||
PspType.fromVpa(vpaEntity.vpa) == pspType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,20 +456,8 @@ constructor(
|
||||
} ?: PspEvaluationResult()
|
||||
}
|
||||
|
||||
private fun getSupportedPspList(
|
||||
naviPayFlowType: NaviPayFlowType,
|
||||
pspSelectionConfig: PspSelectionConfigContent,
|
||||
): List<PspType> {
|
||||
val mandatoryBucket = pspSelectionConfig.flowToMandatoryBucketMap[naviPayFlowType]
|
||||
val mandatoryPspList =
|
||||
mandatoryBucket?.let { pspSelectionConfig.mandatoryBucketToPspListMap[it] }
|
||||
?: PspType.entries
|
||||
return mandatoryPspList
|
||||
}
|
||||
|
||||
private suspend fun getBoundPspList(supportedPspList: List<PspType>): List<PspType> {
|
||||
val pspCustomerStatusMap = naviPayCustomerStatusHandler.getCustomerStatusMap()
|
||||
|
||||
if (supportedPspList.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
@@ -487,6 +475,21 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getSupportedPspList(
|
||||
naviPayFlowType: NaviPayFlowType,
|
||||
pspSelectionConfig: PspSelectionConfigContent,
|
||||
): List<PspType> {
|
||||
val pspDistributionMap =
|
||||
getPspDistributionMap(
|
||||
naviPayFlowType = naviPayFlowType,
|
||||
pspSelectionConfig = pspSelectionConfig,
|
||||
) ?: return PspType.entries
|
||||
return pspDistributionMap
|
||||
.filter { (pspType, weight) -> weight > 0 && PspType.entries.contains(pspType) }
|
||||
.keys
|
||||
.toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the PSP based on routing logic and weighted distribution. If only one PSP exists,
|
||||
* it is directly selected. Otherwise, weights are used for random selection.
|
||||
@@ -505,22 +508,14 @@ constructor(
|
||||
|
||||
if (pspList.size == 1) return pspList[0]
|
||||
|
||||
val routingBucketsJson =
|
||||
naviCacheRepository.get(key = NAVI_PAY_PSP_ROUTING_BUCKETS_KEY)?.value
|
||||
// TODO: Multibank - return null after Olympus is live
|
||||
if (routingBucketsJson.isNullOrBlank()) return PspType.JUSPAY
|
||||
|
||||
val type = object : TypeToken<Map<String, Map<PspType, Double>>>() {}.type
|
||||
val routingBucketsMap: Map<String, Map<PspType, Double>> =
|
||||
gson.fromJson(routingBucketsJson, type)
|
||||
|
||||
val routingBucket =
|
||||
pspSelectionConfig.flowToRoutingBucketMap[naviPayFlowType] ?: return pspList[0]
|
||||
|
||||
val originalDistribution = routingBucketsMap[routingBucket] ?: return pspList[0]
|
||||
val pspDistributionMap =
|
||||
getPspDistributionMap(
|
||||
naviPayFlowType = naviPayFlowType,
|
||||
pspSelectionConfig = pspSelectionConfig,
|
||||
) ?: return PspType.entries[0]
|
||||
|
||||
val filteredDistribution =
|
||||
originalDistribution
|
||||
pspDistributionMap
|
||||
.filterKeys { pspType -> pspList.any { it == pspType } }
|
||||
.toMutableMap()
|
||||
|
||||
@@ -543,6 +538,26 @@ constructor(
|
||||
return null
|
||||
}
|
||||
|
||||
private suspend fun getPspDistributionMap(
|
||||
naviPayFlowType: NaviPayFlowType,
|
||||
pspSelectionConfig: PspSelectionConfigContent,
|
||||
): Map<PspType, Double>? {
|
||||
val routingBucketsJson =
|
||||
naviCacheRepository.get(key = NAVI_PAY_PSP_ROUTING_BUCKETS_KEY)?.value
|
||||
if (routingBucketsJson.isNullOrBlank()) return null
|
||||
|
||||
val type = object : TypeToken<Map<String, Map<String, Double>>>() {}.type
|
||||
val routingBucketsMap: Map<String, Map<String, Double>> =
|
||||
gson.fromJson(routingBucketsJson, type)
|
||||
|
||||
val routingBucket =
|
||||
pspSelectionConfig.flowToRoutingBucketMap[naviPayFlowType] ?: return null
|
||||
|
||||
return routingBucketsMap[routingBucket]
|
||||
?.mapNotNull { (pspName, weight) -> PspType.fromName(pspName)?.let { it to weight } }
|
||||
?.toMap()
|
||||
}
|
||||
|
||||
private suspend fun getPspSelectionConfig(): PspSelectionConfigContent {
|
||||
val naviPayDefaultAccountSelectionConfig =
|
||||
withContext(Dispatchers.IO) {
|
||||
|
||||
Reference in New Issue
Block a user