TP-72546 | send money, collect request fixes (#11679)

This commit is contained in:
Shaurya Rehan
2024-07-04 00:17:59 +05:30
committed by GitHub
parent 0cd941da18
commit f1282d180b
5 changed files with 157 additions and 51 deletions

View File

@@ -123,6 +123,9 @@ fun MainScreen(
val rewardsNudgeDetailEntity by
sendMoneyViewModel.rewardsNudgeDetailEntity.collectAsStateWithLifecycle()
val mainCtaState by sendMoneyViewModel.mainCtaState.collectAsStateWithLifecycle()
val lastExecutedActionBeforeOnboardingSdkTrigger by
sendMoneyViewModel.lastExecutedActionBeforeOnboardingSdkTrigger
.collectAsStateWithLifecycle()
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
@@ -139,7 +142,7 @@ fun MainScreen(
LaunchedEffect(key1 = Unit) {
sendMoneyViewModel.shouldAutoFocusOnAmount.collect {
sendMoneyViewModel.clearShouldAutoFocusOnAmountReplayCache()
if (it) {
if (it && lastExecutedActionBeforeOnboardingSdkTrigger == null) {
focusRequester.requestFocus()
}
}

View File

@@ -374,7 +374,7 @@ fun SendMoneyScreen(
}
BackHandler {
if (bottomSheetState.isVisible) {
if (bottomSheetState.isVisible && bottomSheetStateHolder.showBottomSheet) {
sendMoneyViewModel.updateBottomSheetUIState(showBottomSheet = false)
} else {
onBackClick()

View File

@@ -145,6 +145,7 @@ import com.navi.pay.utils.LITMUS_EXPERIMENT_NAVIPAY_PPS_TDS
import com.navi.pay.utils.MAX_BANK_ACCOUNTS
import com.navi.pay.utils.NAVI_AXIS_UPI_HANDLE
import com.navi.pay.utils.NAVI_PAY_DEFAULT_MCC
import com.navi.pay.utils.NAVI_PAY_PURPLE_CTA_LOADER_LOTTIE
import com.navi.pay.utils.NAVI_PAY_UPI_LITE_LOGO_URL
import com.navi.pay.utils.NOTES_REGEX
import com.navi.pay.utils.NOTE_MAX_LENGTH
@@ -174,6 +175,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import java.util.concurrent.atomic.AtomicReference
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -465,7 +467,11 @@ constructor(
val statusBarColorForLottieTransition = _statusBarColorForLottieTransition.asSharedFlow()
private var naviPayCustomerStatus: String = ""
private var lastExecutedActionBeforeOnboardingSdkTrigger: SendMoneyAction? = null
private val _lastExecutedActionBeforeOnboardingSdkTrigger =
MutableStateFlow<SendMoneyAction?>(null)
val lastExecutedActionBeforeOnboardingSdkTrigger =
_lastExecutedActionBeforeOnboardingSdkTrigger.asStateFlow()
private val _onboardingSdkAction = MutableSharedFlow<Boolean>(replay = 1)
val onboardingSdkAction = _onboardingSdkAction.asSharedFlow()
@@ -506,7 +512,7 @@ constructor(
// Customer status has changed to LINKED_VPA
when (lastExecutedActionBeforeOnboardingSdkTrigger) {
when (lastExecutedActionBeforeOnboardingSdkTrigger.value) {
SendMoneyAction.StartPayment -> {
val payButtonSource =
when (mainCtaState.value) {
@@ -515,13 +521,21 @@ constructor(
else -> ""
}
startPayment(payButtonSource = payButtonSource)
showRedirectingBottomSheet()
startPayment(
payButtonSource = payButtonSource,
isAutoTriggered = true
)
}
SendMoneyAction.Approve -> {
approveCollectRequest()
showRedirectingBottomSheet()
approveCollectRequest(isAutoTriggered = true)
}
SendMoneyAction.Decline -> {
declineCollectRequest()
showRedirectingBottomSheet(
titleText = R.string.np_redirecting_decline_request
)
declineCollectRequest(isAutoTriggered = true)
}
SendMoneyAction.SetPin -> {
// No action required
@@ -534,6 +548,22 @@ constructor(
}
}
private suspend fun showRedirectingBottomSheet(
titleText: Int = R.string.np_redirecting_make_payment
) {
updateBottomSheetUIState(
showBottomSheet = true,
bottomSheetStateChange = false,
bottomSheetUIState =
SendMoneyBottomSheetType.RedirectingBottomSheet(
titleText = resourceProvider.getString(titleText),
isDescriptionClickable = false,
headerLottieFileName = NAVI_PAY_PURPLE_CTA_LOADER_LOTTIE
)
)
delay(2.seconds)
}
private fun updateLinkedAccounts(linkedAccounts: List<LinkedAccountEntity>) {
_linkedAccounts.update { linkedAccounts }
}
@@ -676,7 +706,7 @@ constructor(
fun handleSetPinClick() {
viewModelScope.launch(coroutineDispatcherProvider.io) {
lastExecutedActionBeforeOnboardingSdkTrigger = SendMoneyAction.SetPin
_lastExecutedActionBeforeOnboardingSdkTrigger.update { SendMoneyAction.SetPin }
initiateOnboardingSdk()
}
}
@@ -1184,8 +1214,11 @@ constructor(
?: linkedAccounts.last()
}
private fun checkIsInternetAvailableOrShowError(): Boolean {
private fun checkIsInternetAvailableOrShowError(isAutoTriggered: Boolean = false): Boolean {
if (!naviPayNetworkConnectivity.isInternetConnected()) {
if (isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
notifyError(getNoInternetErrorConfig())
return false
}
@@ -1216,21 +1249,30 @@ constructor(
}
}
private fun checkIsAirplaneModeOnOrShowError(): Boolean {
private fun checkIsAirplaneModeOnOrShowError(isAutoTriggered: Boolean = false): Boolean {
if (naviPayNetworkConnectivity.isAirplaneModeOn()) {
if (isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
notifyError(getAirplaneModeOnErrorConfig())
return true
}
return false
}
private suspend fun validateSimInfoOrShowError(currentSimInfoList: List<SimInfo>): Boolean {
private suspend fun validateSimInfoOrShowError(
currentSimInfoList: List<SimInfo>,
isAutoTriggered: Boolean = false
): Boolean {
val simInfoValidationResult =
NaviPayCommonUtils.validateSimInfo(
currentSimInfoList = currentSimInfoList,
deviceInfoProvider = deviceInfoProvider
)
if (!simInfoValidationResult) {
if (isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
notifyError(getSimFailureErrorConfig(isNoSimPresent = currentSimInfoList.isEmpty()))
return false
}
@@ -1285,10 +1327,12 @@ constructor(
}
}
fun startPayment(payButtonSource: String) {
fun startPayment(payButtonSource: String, isAutoTriggered: Boolean = false) {
viewModelScope.launch(coroutineDispatcherProvider.io) {
if (isUserOnboarded().not()) {
lastExecutedActionBeforeOnboardingSdkTrigger = SendMoneyAction.StartPayment
_lastExecutedActionBeforeOnboardingSdkTrigger.update {
SendMoneyAction.StartPayment
}
// Post onboarding, prefer selecting the original selected account
preferredBankAccountUniqueId =
@@ -1307,11 +1351,21 @@ constructor(
return@launch
}
if (!checkIsInternetAvailableOrShowError()) return@launch
if (checkIsAirplaneModeOnOrShowError()) return@launch
if (!checkIsInternetAvailableOrShowError(isAutoTriggered = isAutoTriggered)) {
return@launch
}
if (checkIsAirplaneModeOnOrShowError(isAutoTriggered = isAutoTriggered)) {
return@launch
}
val currentSimInfoList = naviPayNetworkConnectivity.getCurrentSimInfoList()
if (!validateSimInfoOrShowError(currentSimInfoList)) return@launch
if (!validateSimInfoOrShowError(currentSimInfoList, isAutoTriggered)) {
return@launch
}
if (selectedBankAccount.value == null && isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
var selectedBankAccount = selectedBankAccount.value ?: return@launch
@@ -1327,11 +1381,15 @@ constructor(
}
updateSetDefaultStatusBarColor(setDefaultStatusBarColor = true)
updateScreenState(
screenState =
if (isPaymentFromLiteAccount) SendMoneyScreenState.PaymentInProgressPostPinInput
else SendMoneyScreenState.PaymentInProgressPrePinInput
)
if (!isAutoTriggered) {
updateScreenState(
screenState =
if (isPaymentFromLiteAccount)
SendMoneyScreenState.PaymentInProgressPostPinInput
else SendMoneyScreenState.PaymentInProgressPrePinInput
)
}
val isExternalUpiRequestIdAvailable =
(transactionType == UpiTransactionType.SCAN_PAY ||
@@ -1343,6 +1401,9 @@ constructor(
else upiRequestIdUseCase.execute()
if (upiRequestId.isBlank()) {
if (isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
notifyError(getGenericErrorConfig())
return@launch
}
@@ -1408,6 +1469,9 @@ constructor(
) { npciResult ->
when (npciResult) {
is NpciResult.Success -> {
if (isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
onClSuccessCallback(
isExternalUpiRequestIdAvailable = isExternalUpiRequestIdAvailable,
upiRequestId = upiRequestId,
@@ -1761,6 +1825,7 @@ constructor(
}
private fun handleNpciError(npciError: NpciResult.Error, upiRequestId: String) {
updateBottomSheetUIState(showBottomSheet = false)
if (source == SendMoneyScreenSource.PMS) {
val errorConfig =
if (npciError.isUserAborted) NaviPayCommonUtils.getBackPressErrorConfig()
@@ -2175,21 +2240,32 @@ constructor(
}
}
fun approveCollectRequest() {
fun approveCollectRequest(isAutoTriggered: Boolean = false) {
viewModelScope.launch {
if (isUserOnboarded().not()) {
lastExecutedActionBeforeOnboardingSdkTrigger = SendMoneyAction.Approve
_lastExecutedActionBeforeOnboardingSdkTrigger.update { SendMoneyAction.Approve }
initiateOnboardingSdk()
return@launch
}
if (!checkIsInternetAvailableOrShowError()) return@launch
if (checkIsAirplaneModeOnOrShowError()) return@launch
if (!checkIsInternetAvailableOrShowError()) {
return@launch
}
if (checkIsAirplaneModeOnOrShowError()) {
return@launch
}
val currentSimInfoList = naviPayNetworkConnectivity.getCurrentSimInfoList()
if (!validateSimInfoOrShowError(currentSimInfoList)) return@launch
if (!validateSimInfoOrShowError(currentSimInfoList)) {
return@launch
}
if (source !is SendMoneyScreenSource.CollectRequest) return@launch
if (source !is SendMoneyScreenSource.CollectRequest) {
if (isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
return@launch
}
val updatedBankAccount =
if (source.collectType.equals(REQUEST_TYPE_MANDATE, ignoreCase = true)) {
@@ -2211,9 +2287,16 @@ constructor(
selectedBankAccount.value
}
if (updatedBankAccount == null) return@launch
if (updatedBankAccount == null) {
if (isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
return@launch
}
updateScreenState(screenState = SendMoneyScreenState.PaymentInProgressPrePinInput)
if (!isAutoTriggered) {
updateScreenState(screenState = SendMoneyScreenState.PaymentInProgressPrePinInput)
}
val upiRequestId = payeeEntity.value.transactionId ?: ""
@@ -2240,6 +2323,9 @@ constructor(
npciRepository.fetchCredentials(npciCredData = npciCredData) { npciResult ->
when (npciResult) {
is NpciResult.Success -> {
if (isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
processCollectRequest(
collectRequestAction = CollectRequestAction.APPROVE,
upiRequestId = upiRequestId,
@@ -2258,14 +2344,19 @@ constructor(
}
}
fun declineCollectRequest() {
fun declineCollectRequest(isAutoTriggered: Boolean = false) {
viewModelScope.launch(Dispatchers.IO) {
if (isUserOnboarded().not()) {
lastExecutedActionBeforeOnboardingSdkTrigger = SendMoneyAction.Decline
_lastExecutedActionBeforeOnboardingSdkTrigger.update { SendMoneyAction.Decline }
updateBottomSheetUIState(showBottomSheet = false)
initiateOnboardingSdk()
return@launch
}
if (selectedBankAccount.value == null && isAutoTriggered) {
updateBottomSheetUIState(showBottomSheet = false)
}
val selectedBankAccount = selectedBankAccount.value ?: return@launch
val upiRequestId = payeeEntity.value.transactionId ?: ""
@@ -2276,12 +2367,12 @@ constructor(
note = getNoteValue()
)
)
processCollectRequest(
collectRequestAction = CollectRequestAction.DECLINE,
upiRequestId = upiRequestId,
credBlock = null,
selectedBankAccount = selectedBankAccount
selectedBankAccount = selectedBankAccount,
isAutoTriggered = isAutoTriggered
)
}
}
@@ -2290,27 +2381,29 @@ constructor(
collectRequestAction: CollectRequestAction,
upiRequestId: String,
credBlock: String?,
selectedBankAccount: LinkedAccountEntity
selectedBankAccount: LinkedAccountEntity,
isAutoTriggered: Boolean = false
) {
if (source !is SendMoneyScreenSource.CollectRequest) return
viewModelScope.launch(coroutineDispatcherProvider.io) {
if (!naviPayNetworkConnectivity.isInternetConnected()) {
notifyError(getNoInternetErrorConfig())
if (!checkIsInternetAvailableOrShowError(isAutoTriggered = isAutoTriggered)) {
return@launch
}
sharedPreferenceRepository.saveBooleanValue(PENDING_REQUEST_REFRESHED_REQUIRED, true)
if (collectRequestAction == CollectRequestAction.DECLINE) {
updateBottomSheetUIState(
showBottomSheet = true,
bottomSheetUIState =
SendMoneyBottomSheetType.Loading(
headerResId = R.string.declining_request,
descriptionResId = R.string.loading_bottom_sheet_description
),
bottomSheetStateChange = false
)
if (!isAutoTriggered) {
updateBottomSheetUIState(
showBottomSheet = true,
bottomSheetUIState =
SendMoneyBottomSheetType.Loading(
headerResId = R.string.declining_request,
descriptionResId = R.string.loading_bottom_sheet_description
),
bottomSheetStateChange = false
)
}
} else {
// for approve case, showing full screen loader. So hiding bottom sheet.
updateBottomSheetUIState(showBottomSheet = false)

View File

@@ -1542,29 +1542,35 @@ constructor(
)
}
private fun checkIsInternetAvailableOrShowError(): Boolean {
private fun checkIsInternetAvailableOrShowError(isAutoTriggered: Boolean = false): Boolean {
if (!naviPayNetworkConnectivity.isInternetConnected()) {
if (isAutoTriggered) updateBottomSheetUIState(bottomSheetStateChange = false)
notifyError(getNoInternetErrorConfig())
return false
}
return true
}
private fun checkIsAirplaneModeOnOrShowError(): Boolean {
private fun checkIsAirplaneModeOnOrShowError(isAutoTriggered: Boolean = false): Boolean {
if (naviPayNetworkConnectivity.isAirplaneModeOn()) {
if (isAutoTriggered) updateBottomSheetUIState(bottomSheetStateChange = false)
notifyError(getAirplaneModeOnErrorConfig())
return true
}
return false
}
private suspend fun validateSimInfoOrShowError(currentSimInfoList: List<SimInfo>): Boolean {
private suspend fun validateSimInfoOrShowError(
currentSimInfoList: List<SimInfo>,
isAutoTriggered: Boolean = false
): Boolean {
val simInfoValidationResult =
NaviPayCommonUtils.validateSimInfo(
currentSimInfoList = currentSimInfoList,
deviceInfoProvider = deviceInfoProvider
)
if (!simInfoValidationResult) {
if (isAutoTriggered) updateBottomSheetUIState(bottomSheetStateChange = false)
notifyError(getSimFailureErrorConfig(isNoSimPresent = currentSimInfoList.isEmpty()))
return false
}
@@ -1879,11 +1885,13 @@ constructor(
shouldAutoInitTopUp: Boolean = false
) {
viewModelScope.launch(coroutineDispatcherProvider.io) {
if (!checkIsInternetAvailableOrShowError()) return@launch
if (checkIsAirplaneModeOnOrShowError()) return@launch
if (!checkIsInternetAvailableOrShowError(isAutoTriggered = shouldAutoInitTopUp))
return@launch
if (checkIsAirplaneModeOnOrShowError(isAutoTriggered = shouldAutoInitTopUp))
return@launch
val currentSimInfoList = naviPayNetworkConnectivity.getCurrentSimInfoList()
if (!validateSimInfoOrShowError(currentSimInfoList)) return@launch
if (!validateSimInfoOrShowError(currentSimInfoList, shouldAutoInitTopUp)) return@launch
updateEnableButtonLottieState(isLoaderVisible = false)
if (loadMoneyType == LoadMoneyType.INITIAL_TOPUP || shouldAutoInitTopUp) {

View File

@@ -850,4 +850,6 @@
<string name="np_bbps_payment_failed">Payment failed</string>
<string name="np_bbps_pending_payment_description">We will update the payment status soon.</string>
<string name="np_bbps_recharge_pending_message">Your recharge may reflect within 48 hours</string>
<string name="np_redirecting_make_payment">Redirecting you to make payment</string>
<string name="np_redirecting_decline_request">Declining the payment request</string>
</resources>