TP-56884 | collect request IAN changes (#9866)

This commit is contained in:
Shaurya Rehan
2024-03-08 12:46:11 +05:30
committed by GitHub
parent 855e090972
commit 3d01bce657
7 changed files with 101 additions and 77 deletions

View File

@@ -8,8 +8,10 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.withStyle
import androidx.core.net.toUri
import com.navi.base.model.LineItem
import com.navi.design.font.FontWeightEnum
import com.navi.design.theme.getFontWeight
import com.navi.pay.utils.IS_FROM_IAN
import com.naviapp.analytics.utils.NaviAnalytics
import com.naviapp.common.navigator.NaviDeepLinkNavigator
import com.naviapp.deeplinkmanagement.ui.DeeplinkManagementActivity
@@ -112,7 +114,14 @@ fun handleNotificationClick(
}
} else {
notification.notificationPayload?.cta?.let {
NaviDeepLinkNavigator.navigate(activity = activity, ctaData = it)
val ctaParams = it.parameters?.toMutableList() ?: mutableListOf()
ctaParams.add(
LineItem(
key = IS_FROM_IAN,
value = "true"
)
)
NaviDeepLinkNavigator.navigate(activity = activity, ctaData = it.copy(parameters = ctaParams))
}
}

View File

@@ -51,7 +51,9 @@ import com.navi.pay.management.moneytransfer.scanpay.util.getPayeeEntity
import com.navi.pay.onboarding.account.add.model.view.AccountType
import com.navi.pay.utils.ACTION_PIN_SET
import com.navi.pay.utils.BANK_ACCOUNT_UNIQUE_ID
import com.navi.pay.utils.IS_FROM_IAN
import com.navi.pay.utils.NAVI_PAY_LOCAL_URI_SCHEME
import com.navi.pay.utils.NAVI_PAY_NOTIFICATION_DATA_BUNDLE
import com.navi.pay.utils.NAVI_PAY_OF_TYPE_INTENT_TRANSACTION
import com.navi.pay.utils.NAVI_PAY_UPI_URI_KEY
import com.navi.pay.utils.NEEDS_RESULT
@@ -77,6 +79,9 @@ object NaviPayRouter {
Uri.Builder().scheme(NAVI_PAY_LOCAL_URI_SCHEME).authority(screenName ?: "").build()
ctaData.parameters?.forEach { keyValue -> bundle.putString(keyValue.key, keyValue.value) }
val isFromIan =
ctaData.parameters?.any { it.key == IS_FROM_IAN && it.value == "true" } ?: false
val isIntentFlow = bundle.getBoolean(NAVI_PAY_OF_TYPE_INTENT_TRANSACTION)
val isNaviPayOriginatedIntent = isNaviPayOriginatedIntent(uri)
val needResultFromNaviPay =
@@ -90,6 +95,10 @@ object NaviPayRouter {
if (isIntentFlow && !isNaviPayOriginatedIntent) {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
}
// For Ian flow, replicate the same flow as that of PN
if (isFromIan) {
putExtra(NAVI_PAY_NOTIFICATION_DATA_BUNDLE, bundle)
}
}
if (needResultFromNaviPay) {
activity.startActivityForResult(intent, requestCode)

View File

@@ -170,7 +170,8 @@ sealed class SendMoneyScreenSource : Parcelable {
val collectType: String,
val totalPendingRequests: Int = 0,
val payerVpa: String,
val umn: String? = null
val umn: String? = null,
val source: CollectRequestSource = CollectRequestSource.CollectRequestScreen
) : SendMoneyScreenSource()
@Parcelize
@@ -258,3 +259,13 @@ enum class PayeeSeverity {
LOW_RISK,
HIGH_RISK
}
enum class CollectRequestSource {
PN,
IAN,
CollectRequestScreen;
companion object {
fun CollectRequestSource.isSourceFromNotification(): Boolean = this != CollectRequestScreen
}
}

View File

@@ -58,6 +58,7 @@ import com.navi.pay.destinations.QrScannerScreenDestination
import com.navi.pay.destinations.SelectBankScreenDestination
import com.navi.pay.destinations.TransactionHistoryScreenDestination
import com.navi.pay.entry.NaviPayActivity
import com.navi.pay.management.common.sendmoney.model.view.CollectRequestSource.Companion.isSourceFromNotification
import com.navi.pay.management.common.sendmoney.model.view.PayeeEntity
import com.navi.pay.management.common.sendmoney.model.view.PayeeTransactionHistoryEntity
import com.navi.pay.management.common.sendmoney.model.view.SendMoneyBackPressAction
@@ -203,9 +204,16 @@ fun SendMoneyScreen(
NaviPayEventBus.resetEventBus()
when (it.errorConfig.tag) {
COLLECT_REQUEST_ERROR -> {
resultNavigator.navigateBack(
result = SendMoneyUserAction.RefreshCollectRequests
)
if (
sendMoneyScreenSource is SendMoneyScreenSource.CollectRequest &&
sendMoneyScreenSource.source.isSourceFromNotification()
) {
naviPayActivity.finish()
} else {
resultNavigator.navigateBack(
result = SendMoneyUserAction.RefreshCollectRequests
)
}
}
INTENT_OR_SCAN_PAY_TRANSACTION_ERROR,
INVALID_VPA,

View File

@@ -71,6 +71,7 @@ import com.navi.pay.management.common.sendmoney.model.network.TransactionInitiat
import com.navi.pay.management.common.sendmoney.model.network.TransactionResponse
import com.navi.pay.management.common.sendmoney.model.view.BankAccountsState
import com.navi.pay.management.common.sendmoney.model.view.CollectRequestAction
import com.navi.pay.management.common.sendmoney.model.view.CollectRequestSource.Companion.isSourceFromNotification
import com.navi.pay.management.common.sendmoney.model.view.LinkedAccountEntityState
import com.navi.pay.management.common.sendmoney.model.view.PayeeSeverity
import com.navi.pay.management.common.sendmoney.model.view.SendMoneyBackPressAction
@@ -2179,26 +2180,33 @@ constructor(
fun handleBackPress(needsResult: Boolean) {
viewModelScope.launch(coroutineDispatcherProvider.main) {
when {
isBackPressDisabled() -> {
_backPressAction.emit(SendMoneyBackPressAction.DoNothing)
}
shouldGoToTransactions() -> {
_backPressAction.emit(SendMoneyBackPressAction.GoToTransactions)
}
needsResult && transactionType == UpiTransactionType.SCAN_PAY -> {
_backPressAction.emit(SendMoneyBackPressAction.GoBack)
}
needsResult && transactionType == UpiTransactionType.INTENT_PAY -> {
_backPressAction.emit(SendMoneyBackPressAction.FinishScreen)
}
else -> {
_backPressAction.emit(SendMoneyBackPressAction.GoBack)
val backPressAction = determineBackPressAction(needsResult = needsResult)
_backPressAction.emit(value = backPressAction)
}
}
private fun determineBackPressAction(needsResult: Boolean): SendMoneyBackPressAction {
return when {
isBackPressDisabled() -> SendMoneyBackPressAction.DoNothing
shouldGoToTransactions() -> SendMoneyBackPressAction.GoToTransactions
needsResult -> {
when {
transactionType == UpiTransactionType.SCAN_PAY ->
SendMoneyBackPressAction.GoBack
transactionType == UpiTransactionType.INTENT_PAY ||
isCollectRequestFromNotification() -> SendMoneyBackPressAction.FinishScreen
else -> SendMoneyBackPressAction.GoBack
}
}
else -> SendMoneyBackPressAction.GoBack
}
}
private fun isCollectRequestFromNotification(): Boolean {
return if (source !is SendMoneyScreenSource.CollectRequest) false
else source.source.isSourceFromNotification()
}
private fun isBackPressDisabled(): Boolean {
return screenState.value is SendMoneyScreenState.PaymentInProgress &&
latestTransactionStartedAt != null &&

View File

@@ -29,6 +29,7 @@ import com.navi.pay.common.utils.DeviceInfoProvider
import com.navi.pay.common.utils.NaviPayCommonUtils
import com.navi.pay.common.viewmodel.NaviPayBaseVM
import com.navi.pay.management.collectrequest.model.view.CollectRequestEntity
import com.navi.pay.management.common.sendmoney.model.view.CollectRequestSource
import com.navi.pay.management.common.sendmoney.model.view.PayeeEntity
import com.navi.pay.management.common.sendmoney.model.view.SendMoneyScreenSource
import com.navi.pay.management.mandate.model.network.MandateDetailRequest
@@ -39,6 +40,7 @@ import com.navi.pay.management.moneytransfer.scanpay.model.view.UpiUriResult
import com.navi.pay.management.moneytransfer.scanpay.util.UpiUriParser
import com.navi.pay.onboarding.launcher.model.view.LauncherScreenToNextScreenNavigate
import com.navi.pay.utils.DEFAULT_INITIATION_MODE_INTENT_MANDATE_AND_TRANSACTION
import com.navi.pay.utils.IS_FROM_IAN
import com.navi.pay.utils.NAVI_PAY_ENCRYPT_SHARED_PREF_DATA_KEYS
import com.navi.pay.utils.NAVI_PAY_INTENT_COLLECT_HOST
import com.navi.pay.utils.NAVI_PAY_INTENT_MANDATE_HOST
@@ -91,13 +93,10 @@ constructor(
private fun initLauncher() {
viewModelScope.launch(Dispatchers.IO) {
naviPayAnalytics.trackEvent(eventName = eventName, message = "initLauncherCalled")
logEvent(message = "initLauncherCalled")
when (val customerStatus = naviPayCustomerStatusHandler.getCustomerStatus()) {
NaviPayCustomerStatus.LINKED_VPA -> {
naviPayAnalytics.trackEvent(
eventName = eventName,
message = "LinkedVpa Customer status initLauncher"
)
logEvent(message = "LinkedVpa Customer status initLauncher")
updateNavigateToNextScreenValue(
value =
LauncherScreenToNextScreenNavigate.OnLocalDataValidState(
@@ -106,17 +105,11 @@ constructor(
)
}
NaviPayCustomerStatus.DEVICE_BOUNDED -> {
naviPayAnalytics.trackEvent(
eventName = eventName,
message = "Device bounded status initLauncher"
)
logEvent(message = "Device bounded status initLauncher")
navigateToNextScreenBasedOnCustomerStatus(customerStatus.name)
}
else -> {
naviPayAnalytics.trackEvent(
eventName = eventName,
message = "else case start splash called"
)
logEvent(message = "else case start splash called")
_verifyUserDetails.emit(true)
}
}
@@ -125,8 +118,7 @@ constructor(
fun verifyUserDetailsAndProceedToNextScreen(currentDeviceId: String, packageName: String) {
viewModelScope.launch(Dispatchers.IO) {
naviPayAnalytics.trackEvent(
eventName = eventName,
logEvent(
message = "verifyUserDetailsAndProceedToNextScreen. Starting naviPaySetupUseCase"
)
val naviPaySetupStatus =
@@ -136,10 +128,7 @@ constructor(
packageName = packageName,
source = NAVI_PAY_LAUNCHER
)
naviPayAnalytics.trackEvent(
eventName = eventName,
message = "setupStatus result: $naviPaySetupStatus"
)
logEvent(message = "setupStatus result: $naviPaySetupStatus")
when (naviPaySetupStatus) {
is NaviPaySetupStatus.Failure -> {
when (naviPaySetupStatus.failureReason) {
@@ -210,17 +199,10 @@ constructor(
private suspend fun checkUriTypeFromSuperAppAndNavigate(uri: Uri, customerStatus: String) =
withContext(Dispatchers.IO) {
naviPayAnalytics.trackEvent(
eventName = eventName,
message = "checkUriTypeFromSuperAppAndNavigate. Uri is $uri"
)
logEvent(message = "checkUriTypeFromSuperAppAndNavigate. Uri is $uri")
when (val upiUriResult = upiUriParser.parseForUpiUri(uri)) {
is UpiUriResult.Error -> {
naviPayAnalytics.trackEvent(
eventName = eventName,
message = "UpiUriResult.Error. Navigating based on customer status"
)
logEvent(message = "UpiUriResult.Error. Navigating based on customer status")
navigateToNextScreenBasedOnCustomerStatus(customerStatus = customerStatus)
}
is UpiUriResult.Success -> {
@@ -241,8 +223,7 @@ constructor(
)
)
} catch (e: Exception) {
naviPayAnalytics.trackEvent(
eventName = eventName,
logEvent(
message =
"checkUriTypeFromSuperAppAndNavigate for mandate case. Exception: ${e.message}"
)
@@ -305,18 +286,14 @@ constructor(
) =
withContext(Dispatchers.IO) {
val ctaData = notificationData[NAVI_PAY_NOTIFICATION_DATA_CTA_KEY].toString()
naviPayAnalytics.trackEvent(
eventName = eventName,
message = "checkNotificationDataAndNavigate. Cta data is $ctaData"
)
val isFromIan = notificationData.any { it.key == IS_FROM_IAN && it.value == "true" }
logEvent(message = "checkNotificationDataAndNavigate. Cta data is $ctaData")
when (ctaData) {
NAVI_PAY_NOTIFICATION_APPROVE_OR_DECLINE_MANDATE,
NAVI_PAY_NOTIFICATION_MODIFY_MANDATE -> {
val mandateReferenceId = notificationData["mandateReferenceId"].toString()
if (mandateReferenceId.isEmpty()) {
naviPayAnalytics.trackEvent(
eventName = eventName,
logEvent(
message =
"MandateReferenceId is empty. Navigating based on customer status. CustomerStatus: $customerStatus"
)
@@ -335,7 +312,8 @@ constructor(
NAVI_PAY_NOTIFICATION_COLLECT_REQUEST -> {
processCollectRequestAndNavigate(
notificationData = notificationData,
customerStatus = customerStatus
customerStatus = customerStatus,
isFromInAppNotification = isFromIan
)
return@withContext
}
@@ -346,10 +324,9 @@ constructor(
getDirectionFromCtaUrl(url = ctaData, sourceScreenName = NAVI_PAY_LAUNCHER)
if (nextScreenDestination != null) {
naviPayAnalytics.trackEvent(
eventName = eventName,
logEvent(
message =
"checkNotificationDataAndNavigate Next screen destination is $nextScreenDestination"
"checkNotificationDataAndNavigate. Next screen destination is $nextScreenDestination"
)
updateNavigateToNextScreenValue(
value =
@@ -362,11 +339,11 @@ constructor(
private suspend fun processCollectRequestAndNavigate(
notificationData: HashMap<String, String>,
customerStatus: String
customerStatus: String,
isFromInAppNotification: Boolean
) {
try {
naviPayAnalytics.trackEvent(
eventName = eventName,
logEvent(
message = "processCollectRequestAndNavigate. Notification data is $notificationData"
)
val collectRequestEntity =
@@ -375,7 +352,10 @@ constructor(
var sendMoneyScreenSource =
SendMoneyScreenSource.CollectRequest(
collectType = collectRequestEntity.collectType,
payerVpa = collectRequestEntity.payerVpa
payerVpa = collectRequestEntity.payerVpa,
source =
if (isFromInAppNotification) CollectRequestSource.IAN
else CollectRequestSource.PN
)
if (collectRequestEntity.collectType == REQUEST_TYPE_MANDATE) {
@@ -410,10 +390,7 @@ constructor(
)
)
} catch (exception: Exception) {
naviPayAnalytics.trackEvent(
eventName = eventName,
message = "processCollectRequestAndNavigate. Exception: ${exception.message}"
)
logEvent(message = "processCollectRequestAndNavigate. Exception: ${exception.message}")
navigateToNextScreenBasedOnCustomerStatus(customerStatus = customerStatus)
}
}
@@ -425,8 +402,7 @@ constructor(
) =
withContext(Dispatchers.IO) {
if (naviPayUri.scheme != NAVI_PAY_LOCAL_URI_SCHEME) {
naviPayAnalytics.trackEvent(
eventName = eventName,
logEvent(
message =
"checkNaviPayLocalUriAndNavigate NaviPayScheme is not valid. Scheme is ${naviPayUri.scheme}"
)
@@ -441,20 +417,18 @@ constructor(
)
}
if (nextScreenDestination != null) {
naviPayAnalytics.trackEvent(
eventName = eventName,
logEvent(
message =
"checkNaviPayLocalUriAndNavigate Next screen destination is $nextScreenDestination"
"checkNaviPayLocalUriAndNavigate. Next screen destination is $nextScreenDestination"
)
updateNavigateToNextScreenValue(
value =
LauncherScreenToNextScreenNavigate.OtherHomeOptions(
nextScreenDestination
nextScreenDestination = nextScreenDestination
)
)
} else {
naviPayAnalytics.trackEvent(
eventName = eventName,
logEvent(
message = "checkNaviPayLocalUriAndNavigate. Next screen destination is null"
)
navigateToNextScreenBasedOnCustomerStatus(customerStatus = customerStatus)
@@ -462,6 +436,10 @@ constructor(
}
}
private fun logEvent(message: String) {
naviPayAnalytics.trackEvent(eventName = eventName, message = message)
}
private fun mapToCollectRequestEntity(notificationData: HashMap<String, String>) =
CollectRequestEntity(
transactionId = notificationData["gatewayTransactionId"].toString(),

View File

@@ -16,6 +16,7 @@ const val LINKED_ACCOUNTS_IN_DB_REFRESH_MIN_TIMESTAMP = 86400000L // 1 day
const val FREQUENT_TRANSACTIONS_IN_DB_REFRESH_MIN_TIMESTAMP = 86400000L // 1 day
const val PHONE_NUMBER_LENGTH = 10
const val ZERO_STRING = "0"
const val IS_FROM_IAN = "IS_FROM_IAN"
// Send & Request money constants
const val NOTE_MAX_LENGTH = 50