NTP-17756 | Shiv Natani | implemented send money usecase for navi pay (#14116)
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.pay.common.usecase
|
||||
|
||||
import com.navi.common.network.models.RepoResult
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.pay.common.repository.SharedPreferenceRepository
|
||||
import com.navi.pay.common.utils.DeviceInfoProvider
|
||||
import com.navi.pay.common.utils.getMetricInfo
|
||||
import com.navi.pay.management.common.sendmoney.model.network.GatewayPayeeInfo
|
||||
import com.navi.pay.management.common.sendmoney.model.network.GatewayPayerInfo
|
||||
import com.navi.pay.management.common.sendmoney.model.network.GatewayTxnInfo
|
||||
import com.navi.pay.management.common.sendmoney.model.network.SendMoneyRequest
|
||||
import com.navi.pay.management.common.sendmoney.model.network.TransactionInitiationType.Companion.getTransactionInitiationTypeFromSendMoneyScreenSource
|
||||
import com.navi.pay.management.common.sendmoney.model.network.TransactionResponse
|
||||
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.common.sendmoney.model.view.UpiTransactionType
|
||||
import com.navi.pay.management.common.sendmoney.repository.SendMoneyRepository
|
||||
import com.navi.pay.management.common.transaction.model.network.TransactionInstrumentType
|
||||
import com.navi.pay.management.lite.util.UPILitePurposeCodes
|
||||
import com.navi.pay.npcicl.CredDataProvider
|
||||
import com.navi.pay.npcicl.NpciRepository
|
||||
import com.navi.pay.npcicl.NpciResult
|
||||
import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
|
||||
import com.navi.pay.utils.KEY_IS_FIRST_TRANSACTION_SUCCESSFUL
|
||||
import com.navi.pay.utils.PAY_AGAIN
|
||||
import com.navi.pay.utils.UPI_LITE_CREDBLOCK_INITIAL
|
||||
import com.navi.pay.utils.UPI_LITE_CREDBLOCK_SIGNATURE
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.measureTimedValue
|
||||
|
||||
class SendMoneyUseCase
|
||||
@Inject
|
||||
constructor(
|
||||
private val npciRepository: NpciRepository,
|
||||
private val deviceInfoProvider: DeviceInfoProvider,
|
||||
private val credDataProvider: CredDataProvider,
|
||||
private val upiLiteBalanceUseCase: UpiLiteBalanceUseCase,
|
||||
private val sendMoneyRepository: SendMoneyRepository,
|
||||
private val sharedPreferenceRepository: SharedPreferenceRepository,
|
||||
) {
|
||||
|
||||
private fun modifyCredBlockForLiteTxn(credBlock: String): String {
|
||||
return credBlock.replace(UPI_LITE_CREDBLOCK_SIGNATURE, UPI_LITE_CREDBLOCK_INITIAL)
|
||||
}
|
||||
|
||||
suspend fun generateCredBlock(
|
||||
selectedBankAccount: LinkedAccountEntity,
|
||||
upiRequestId: String,
|
||||
payeeEntity: PayeeEntity,
|
||||
screenName: String,
|
||||
txnTimeStamp: String,
|
||||
isPaymentFromLiteAccount: Boolean = false,
|
||||
onNpciResultSuccess: suspend (credBlock: String) -> Unit,
|
||||
onNpciResultError: (isUserAborted: Boolean) -> Unit,
|
||||
triggerEventForUpiLitePayment: () -> Unit = {},
|
||||
onNpciCredentialsFetched: () -> Unit = {},
|
||||
) {
|
||||
val lrn = selectedBankAccount.activeLiteAccountLrn
|
||||
if (isPaymentFromLiteAccount) triggerEventForUpiLitePayment()
|
||||
val npciCredData =
|
||||
if (isPaymentFromLiteAccount) {
|
||||
credDataProvider.upiLiteSendMoneyCred(
|
||||
linkedAccountEntity = selectedBankAccount,
|
||||
payerLiteAccountNumber = lrn,
|
||||
upiRequestId = upiRequestId,
|
||||
payeeEntity = payeeEntity,
|
||||
txnTimeStamp = txnTimeStamp
|
||||
)
|
||||
} else {
|
||||
credDataProvider.payCred(
|
||||
accountEntity = selectedBankAccount,
|
||||
payeeEntity = payeeEntity,
|
||||
upiRequestId = upiRequestId
|
||||
)
|
||||
}
|
||||
val npciResult =
|
||||
npciRepository.fetchCredentials(
|
||||
npciCredData = npciCredData,
|
||||
metricInfo = getMetricInfo(screenName = screenName),
|
||||
)
|
||||
onNpciCredentialsFetched()
|
||||
when (npciResult) {
|
||||
is NpciResult.Success -> {
|
||||
val credBlock =
|
||||
if (isPaymentFromLiteAccount) modifyCredBlockForLiteTxn(npciResult.data)
|
||||
else npciResult.data
|
||||
onNpciResultSuccess(credBlock)
|
||||
}
|
||||
is NpciResult.Error -> {
|
||||
onNpciResultError(npciResult.isUserAborted)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun executeSendMoney(
|
||||
payeeEntity: PayeeEntity,
|
||||
upiRequestId: String,
|
||||
selectedBankAccount: LinkedAccountEntity,
|
||||
txnTimeStamp: String,
|
||||
credBlock: String,
|
||||
isPaymentFromLiteAccount: Boolean = false,
|
||||
sendMoneyScreenSource: SendMoneyScreenSource,
|
||||
transactionType: UpiTransactionType,
|
||||
tstoreOrderId: String?,
|
||||
metadata: String?,
|
||||
screenName: String,
|
||||
onPaymentSuccess:
|
||||
suspend (
|
||||
transactionCompletionTime: Long,
|
||||
isTransactionEligibleForNpsComs: Boolean,
|
||||
sendMoneyResponse: TransactionResponse,
|
||||
) -> Unit,
|
||||
onPaymentFailure:
|
||||
suspend (
|
||||
sendMoneyResponse: RepoResult<TransactionResponse>,
|
||||
sendMoneyRequest: SendMoneyRequest,
|
||||
) -> Unit,
|
||||
saveDataInSavedBeneficiary: (sendMoneyRequest: SendMoneyRequest) -> Unit = {},
|
||||
) {
|
||||
val sendMoneyRequest =
|
||||
SendMoneyRequest(
|
||||
gatewayPayeeInfo =
|
||||
GatewayPayeeInfo(
|
||||
vpa = payeeEntity.vpa,
|
||||
name = payeeEntity.name,
|
||||
bankIfsc = payeeEntity.bankIfsc,
|
||||
bankAccountUniqueId = payeeEntity.bankAccountUniqueId,
|
||||
bankAccountNumber = payeeEntity.maskedAccountNumber,
|
||||
bankName = payeeEntity.bankName,
|
||||
bankCode = payeeEntity.bankCode,
|
||||
mobileNumber = payeeEntity.phoneNumber,
|
||||
upiNumber = payeeEntity.upiNumber,
|
||||
mcc = payeeEntity.mcc,
|
||||
),
|
||||
gatewayPayerInfo =
|
||||
GatewayPayerInfo(
|
||||
merchantCustomerId = deviceInfoProvider.getMerchantCustomerId(),
|
||||
vpa = selectedBankAccount.vpa,
|
||||
name = selectedBankAccount.name,
|
||||
bankAccountUniqueId = selectedBankAccount.accountId,
|
||||
lrn =
|
||||
if (isPaymentFromLiteAccount) selectedBankAccount.activeLiteAccountLrn
|
||||
else null,
|
||||
liteCurrBalance = upiLiteBalanceUseCase.execute(),
|
||||
bankCode = selectedBankAccount.bankCode,
|
||||
),
|
||||
gatewayTxnInfo =
|
||||
GatewayTxnInfo(
|
||||
amount = payeeEntity.amount,
|
||||
upiRequestId = upiRequestId,
|
||||
currency = payeeEntity.currency,
|
||||
initiationMode = payeeEntity.mode,
|
||||
purpose =
|
||||
if (isPaymentFromLiteAccount) UPILitePurposeCodes.SEND_MONEY.purposeCode
|
||||
else payeeEntity.purpose,
|
||||
remarks = payeeEntity.note,
|
||||
timeStamp = txnTimeStamp,
|
||||
credBlock =
|
||||
if (isPaymentFromLiteAccount) modifyCredBlockForLiteTxn(credBlock)
|
||||
else credBlock,
|
||||
refCategory = payeeEntity.refCategory,
|
||||
refUrl = payeeEntity.refUrl,
|
||||
transactionType = transactionType.name,
|
||||
transactionReference = payeeEntity.transactionReference,
|
||||
paymentMode =
|
||||
getTransactionInitiationTypeFromSendMoneyScreenSource(
|
||||
sendMoneyScreenSource = sendMoneyScreenSource
|
||||
)
|
||||
.name +
|
||||
if (
|
||||
sendMoneyScreenSource is
|
||||
SendMoneyScreenSource.TransactionHistoryDetail ||
|
||||
sendMoneyScreenSource is
|
||||
SendMoneyScreenSource.PaymentSummary
|
||||
)
|
||||
PAY_AGAIN
|
||||
else "",
|
||||
instrumentType = TransactionInstrumentType.TRANSACTION.name,
|
||||
tstoreOrderId = tstoreOrderId,
|
||||
txnRequestType = null
|
||||
),
|
||||
deviceData = deviceInfoProvider.getDeviceData(),
|
||||
metaData = metadata,
|
||||
)
|
||||
saveDataInSavedBeneficiary(sendMoneyRequest)
|
||||
val measureTimedSendMoneyResponse = measureTimedValue {
|
||||
sendMoneyRepository.sendMoney(
|
||||
sendMoneyRequest = sendMoneyRequest,
|
||||
metricInfo = getMetricInfo(screenName = screenName)
|
||||
)
|
||||
}
|
||||
val response = measureTimedSendMoneyResponse.value
|
||||
val transactionCompletionTime = measureTimedSendMoneyResponse.duration.inWholeMilliseconds
|
||||
|
||||
// isTransactionEligibleForNpsComms is true for all type of sendMoney case
|
||||
// Just that KEY_IS_FIRST_TRANSACTION_SUCCESSFUL should be false
|
||||
val isTransactionEligibleForNpsComms =
|
||||
!sharedPreferenceRepository.getBooleanValue(
|
||||
key = KEY_IS_FIRST_TRANSACTION_SUCCESSFUL,
|
||||
defValue = true
|
||||
)
|
||||
|
||||
if (response.isSuccessWithData()) {
|
||||
onPaymentSuccess(
|
||||
transactionCompletionTime,
|
||||
isTransactionEligibleForNpsComms,
|
||||
response.data!!
|
||||
)
|
||||
} else {
|
||||
onPaymentFailure(measureTimedSendMoneyResponse.value, sendMoneyRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@ import com.navi.pay.common.usecase.AccountListCheckBalanceUseCase
|
||||
import com.navi.pay.common.usecase.LinkedAccountsUseCase
|
||||
import com.navi.pay.common.usecase.LiteAccountSyncUseCase
|
||||
import com.navi.pay.common.usecase.NaviPayConfigUseCase
|
||||
import com.navi.pay.common.usecase.SendMoneyUseCase
|
||||
import com.navi.pay.common.usecase.UpiLiteBalanceUseCase
|
||||
import com.navi.pay.common.usecase.UpiLiteExperimentationUseCase
|
||||
import com.navi.pay.common.usecase.UpiRequestIdUseCase
|
||||
@@ -137,7 +138,6 @@ import com.navi.pay.navtype.payeeEntityNavType
|
||||
import com.navi.pay.navtype.sendMoneyScreenSourceNavType
|
||||
import com.navi.pay.navtype.upiTransactionTypeEnumNavType
|
||||
import com.navi.pay.npcicl.CredDataProvider
|
||||
import com.navi.pay.npcicl.NpciCredData
|
||||
import com.navi.pay.npcicl.NpciRepository
|
||||
import com.navi.pay.npcicl.NpciResult
|
||||
import com.navi.pay.onboarding.account.add.model.view.AccountType
|
||||
@@ -261,7 +261,8 @@ constructor(
|
||||
private val upiLiteCommsAndMandateExecutionHandler: UpiLiteCommsAndMandateExecutionHandler,
|
||||
val accountListCheckBalanceUseCase: AccountListCheckBalanceUseCase,
|
||||
private val litmusExperimentsUseCase: LitmusExperimentsUseCase,
|
||||
naviPayActivityDataProvider: NaviPayActivityDataProvider
|
||||
private val sendMoneyUseCase: SendMoneyUseCase,
|
||||
naviPayActivityDataProvider: NaviPayActivityDataProvider,
|
||||
) : NaviPayBaseVM() {
|
||||
|
||||
private val _menuAction = MutableStateFlow(SendMoneyUserAction.None)
|
||||
@@ -1594,61 +1595,37 @@ constructor(
|
||||
)
|
||||
|
||||
val txnTimeStamp = DateTime.now().toString()
|
||||
|
||||
var liteSendMoneyCred: NpciCredData? = null
|
||||
var npciCredData: NpciCredData? = null
|
||||
val lrn = selectedBankAccount.activeLiteAccountLrn
|
||||
|
||||
if (isPaymentFromLiteAccount) {
|
||||
liteSendMoneyCred =
|
||||
credDataProvider.upiLiteSendMoneyCred(
|
||||
linkedAccountEntity = selectedBankAccount,
|
||||
payerLiteAccountNumber = lrn,
|
||||
upiRequestId = upiRequestId,
|
||||
payeeEntity = payeeEntity.value,
|
||||
txnTimeStamp = txnTimeStamp
|
||||
)
|
||||
upiLiteAnalytics.onDevGenericEvent(
|
||||
event = "startPayment",
|
||||
params = mapOf("isPaymentFromLiteAccount" to "true")
|
||||
)
|
||||
} else {
|
||||
npciCredData =
|
||||
credDataProvider.payCred(
|
||||
accountEntity = selectedBankAccount,
|
||||
payeeEntity = payeeEntity.value,
|
||||
upiRequestId = upiRequestId
|
||||
)
|
||||
}
|
||||
|
||||
val npciResult =
|
||||
npciRepository.fetchCredentials(
|
||||
npciCredData =
|
||||
if (isPaymentFromLiteAccount) liteSendMoneyCred!! else npciCredData!!,
|
||||
metricInfo = getMetricInfo(screenName = screenName),
|
||||
)
|
||||
|
||||
updateTriggerDismissBottomSheet()
|
||||
when (npciResult) {
|
||||
is NpciResult.Success -> {
|
||||
sendMoneyUseCase.generateCredBlock(
|
||||
isPaymentFromLiteAccount = isPaymentFromLiteAccount,
|
||||
upiRequestId = upiRequestId,
|
||||
selectedBankAccount = selectedBankAccount,
|
||||
payeeEntity = payeeEntity.value,
|
||||
screenName = screenName,
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
onNpciResultSuccess = { credBlock ->
|
||||
if (isAutoTriggered) {
|
||||
updateTriggerDismissBottomSheet()
|
||||
}
|
||||
onClSuccessCallback(
|
||||
isExternalUpiRequestIdAvailable = isExternalUpiRequestIdAvailable,
|
||||
upiRequestId = upiRequestId,
|
||||
credBlock =
|
||||
if (isPaymentFromLiteAccount) modifyCredBlockForLiteTxn(npciResult.data)
|
||||
else npciResult.data,
|
||||
credBlock = credBlock,
|
||||
selectedBankAccountEntity = selectedBankAccount,
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
isPaymentFromLiteAccount = isPaymentFromLiteAccount
|
||||
)
|
||||
}
|
||||
is NpciResult.Error ->
|
||||
handleNpciError(npciError = npciResult, upiRequestId = upiRequestId)
|
||||
else -> Unit
|
||||
}
|
||||
},
|
||||
onNpciResultError = { isUserAborted ->
|
||||
handleNpciError(isUserAborted = isUserAborted, upiRequestId = upiRequestId)
|
||||
},
|
||||
triggerEventForUpiLitePayment = {
|
||||
upiLiteAnalytics.onDevGenericEvent(
|
||||
event = "startPayment",
|
||||
params = mapOf("isPaymentFromLiteAccount" to "true")
|
||||
)
|
||||
},
|
||||
onNpciCredentialsFetched = ::updateTriggerDismissBottomSheet
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1700,13 +1677,46 @@ constructor(
|
||||
if (!isPaymentFromLiteAccount) {
|
||||
updateScreenState(screenState = SendMoneyScreenState.PaymentInProgressPostPinInput)
|
||||
}
|
||||
executeSendMoneyPostCredBlockGeneration(
|
||||
isExternalUpiRequestIdAvailable = isExternalUpiRequestIdAvailable,
|
||||
latestTransactionStartedAt = System.currentTimeMillis()
|
||||
sendMoneyUseCase.executeSendMoney(
|
||||
payeeEntity = payeeEntity.value,
|
||||
upiRequestId = upiRequestId,
|
||||
selectedBankAccount = selectedBankAccount.value!!,
|
||||
credBlock = credBlock,
|
||||
selectedBankAccount = selectedBankAccountEntity,
|
||||
isPaymentFromLiteAccount = isPaymentFromLiteAccount,
|
||||
sendMoneyScreenSource = source,
|
||||
transactionType = transactionType,
|
||||
tstoreOrderId = tstoreOrderId,
|
||||
metadata = metadata,
|
||||
saveDataInSavedBeneficiary = { sendMoneyRequest ->
|
||||
viewModelScope.launch {
|
||||
processRequestForSavedBeneficiaryData(sendMoneyRequest = sendMoneyRequest)
|
||||
}
|
||||
},
|
||||
screenName = screenName,
|
||||
txnTimeStamp = txnTimeStamp,
|
||||
isPaymentFromLiteAccount = isPaymentFromLiteAccount
|
||||
onPaymentSuccess = {
|
||||
transactionCompletionTime,
|
||||
isTransactionEligibleForNpsComms,
|
||||
response ->
|
||||
processPaymentSuccess(
|
||||
sendMoneyResponse = response,
|
||||
isTransactionEligibleForNpsComms = isTransactionEligibleForNpsComms,
|
||||
isPaymentThroughLiteAccount = isPaymentFromLiteAccount,
|
||||
upiRequestId = upiRequestId,
|
||||
transactionCompletionTime = transactionCompletionTime
|
||||
)
|
||||
},
|
||||
onPaymentFailure = { response, sendMoneyRequest ->
|
||||
processPaymentFailure(
|
||||
response = response,
|
||||
accountId = selectedBankAccount.value!!.accountId,
|
||||
isExternalUpiRequestIdAvailable = isExternalUpiRequestIdAvailable,
|
||||
isPaymentThroughLite = isPaymentFromLiteAccount,
|
||||
payeeVpa = sendMoneyRequest.gatewayPayeeInfo.vpa,
|
||||
upiRequestId = upiRequestId
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -2028,11 +2038,11 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleNpciError(npciError: NpciResult.Error, upiRequestId: String) {
|
||||
private fun handleNpciError(isUserAborted: Boolean, upiRequestId: String) {
|
||||
updateTriggerDismissBottomSheet()
|
||||
if (source == SendMoneyScreenSource.PMS) {
|
||||
val errorConfig =
|
||||
if (npciError.isUserAborted) NaviPayCommonUtils.getBackPressErrorConfig()
|
||||
if (isUserAborted) NaviPayCommonUtils.getBackPressErrorConfig()
|
||||
else getGenericErrorConfig()
|
||||
viewModelScope.launch(Dispatchers.Main) {
|
||||
pmsPostMPINCallBack?.invoke(
|
||||
@@ -2066,7 +2076,7 @@ constructor(
|
||||
} else {
|
||||
updateScreenState(screenState = SendMoneyScreenState.MainScreen)
|
||||
updateSetDefaultStatusBarColor(setDefaultStatusBarColor = true)
|
||||
if (!npciError.isUserAborted) {
|
||||
if (!isUserAborted) {
|
||||
notifyError()
|
||||
}
|
||||
}
|
||||
@@ -2688,7 +2698,10 @@ constructor(
|
||||
)
|
||||
}
|
||||
is NpciResult.Error ->
|
||||
handleNpciError(npciError = npciResult, upiRequestId = upiRequestId)
|
||||
handleNpciError(
|
||||
isUserAborted = npciResult.isUserAborted,
|
||||
upiRequestId = upiRequestId
|
||||
)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user