From 18124e573d7bd0e90462f4a08c4a9e8d451c7769 Mon Sep 17 00:00:00 2001 From: shreyansu raj Date: Tue, 16 Jul 2024 15:19:23 +0530 Subject: [PATCH] TP-72001 | Payment sdk integration (#11788) --- .../custom_payments/CustomPaymentActivity.kt | 135 +++++++++++++++++- .../CustomPaymentCalendarReviewFragment.kt | 30 +++- .../fragments/ForecloseLoanFragment.kt | 29 +++- .../fragments/LoanRepaymentOptionsFragment.kt | 28 +++- .../fragments/RepaymentTypeFragment.kt | 34 ++++- .../listener/InitiatePaymentListener.kt | 23 +++ .../home/compose/activity/HomePageActivity.kt | 99 +++++++------ ...PartPrePaymentEmiCalendarReviewFragment.kt | 31 +++- .../fragments/PaymentBehaviourFragment.kt | 18 ++- .../emi/fragments/EMIDateChangeFragment.kt | 31 +++- .../common/utils/PaymentSdkResultUtil.kt | 49 +++++++ .../paymentscreen/ui/PaymentLoaderFragment.kt | 10 +- 12 files changed, 427 insertions(+), 90 deletions(-) create mode 100644 android/app/src/main/java/com/naviapp/custom_payments/listener/InitiatePaymentListener.kt create mode 100644 android/app/src/main/java/com/naviapp/personalloanrevamp/common/utils/PaymentSdkResultUtil.kt diff --git a/android/app/src/main/java/com/naviapp/custom_payments/CustomPaymentActivity.kt b/android/app/src/main/java/com/naviapp/custom_payments/CustomPaymentActivity.kt index 454434f753..d874428f98 100644 --- a/android/app/src/main/java/com/naviapp/custom_payments/CustomPaymentActivity.kt +++ b/android/app/src/main/java/com/naviapp/custom_payments/CustomPaymentActivity.kt @@ -9,34 +9,62 @@ package com.naviapp.custom_payments import android.content.Intent import android.os.Bundle +import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels import androidx.databinding.DataBindingUtil import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope import com.navi.base.model.CtaData import com.navi.common.listeners.FragmentInterchangeListener import com.navi.common.model.ModuleNameV2 +import com.navi.common.utils.observeNullable +import com.navi.payment.model.common.PaymentSdkInitParams +import com.navi.payment.model.common.PaymentSdkTypes +import com.navi.payment.model.initiatesdk.PaymentPrefetchMethodRequest +import com.navi.payment.nativepayment.router.NaviPaymentRouter +import com.navi.payment.nativepayment.sharedviewmodel.NaviCheckoutViewModel import com.navi.payment.paymentscreen.model.PaymentActivityResponse import com.navi.payment.paymentscreen.viewmodel.PaymentScreenSharedViewModel +import com.navi.payment.utils.Constants.FULL_PAYMENT_SCREEN +import com.navi.payment.utils.PaymentSource +import com.navi.paymentclients.model.InitiatePaymentRequest import com.naviapp.R import com.naviapp.analytics.utils.NaviAnalytics import com.naviapp.common.navigator.NaviDeepLinkNavigator +import com.naviapp.custom_payments.listener.InitiatePaymentListener import com.naviapp.dashboard.DashboardBaseActivity import com.naviapp.databinding.ActivityCustomPaymentBinding import com.naviapp.part_prepayment.FragmentMapper +import com.naviapp.payment.activities.FeedbackActivity +import com.naviapp.payment.models.Amount +import com.naviapp.payment.viewmodel.PaymentVM import com.naviapp.utils.Constants +import com.naviapp.utils.Constants.LOAN_TYPE +import com.naviapp.utils.Constants.TYPE_PERSONAL_LOAN +import com.naviapp.utils.IS_SYNC_FLOW +import com.naviapp.utils.LOAN_ACCOUNT_NUMBER +import com.naviapp.utils.LOAN_ACCOUNT_REQUEST_ID import dagger.hilt.android.AndroidEntryPoint +import java.util.Locale import javax.inject.Inject @AndroidEntryPoint -class CustomPaymentActivity : DashboardBaseActivity(), FragmentInterchangeListener { +class CustomPaymentActivity : + DashboardBaseActivity(), FragmentInterchangeListener, InitiatePaymentListener { private lateinit var binding: ActivityCustomPaymentBinding @Inject lateinit var fragmentMapper: FragmentMapper + private val paymentVM by viewModels() + private val paymentScreenSharedViewModel by lazy { ViewModelProvider(this)[PaymentScreenSharedViewModel::class.java] } + private val naviCheckoutViewModel by viewModels() + private var loanAccountNumber: String? = null + override fun onCreate(savedInstanceState: Bundle?) { binding = DataBindingUtil.setContentView(this, R.layout.activity_custom_payment) super.onCreate(savedInstanceState) @@ -44,6 +72,9 @@ class CustomPaymentActivity : DashboardBaseActivity(), FragmentInterchangeListen intent?.extras?.getString(Constants.REDIRECT_STATUS).orEmpty(), intent?.extras ?: Bundle() ) + initError(paymentVM, actionErrorV2Enabled = true) + observePaymentListener() + observeInitiatePaymentStatus() } override val screenName: String @@ -112,4 +143,106 @@ class CustomPaymentActivity : DashboardBaseActivity(), FragmentInterchangeListen ) } } + + override fun initiatePayment( + amount: Amount, + isPreClosure: Boolean, + repaymentType: String?, + sourceOfFunds: String?, + otherSourceOfFunds: String?, + partPrePaymentRescheduleType: String?, + loanAccountNumber: String?, + loanType: String? + ) { + this.loanAccountNumber = loanAccountNumber + if ( + System.currentTimeMillis() - apiCallLastTime <= + Constants.API_CALL_MULTI_CLICK_THRESOLD_DUR + ) + return + showLoader() + NaviAnalytics.naviAnalytics.Payment().onPlPaymentInitiatePaymentCalled(loanType) + paymentVM.setIsPaymentLoaderShowing(true) + val data = + InitiatePaymentRequest( + loanAccountNumber, + com.navi.paymentclients.model.Amount( + value = amount.value, + currency = amount.currency, + symbol = amount.symbol + ), + isPreClosure, + repaymentType, + sourceOfFunds, + otherSourceOfFunds, + partPrePaymentRescheduleType + ) + paymentVM.initiatePayment(data) + } + + private fun observePaymentListener() { + paymentVM.initPaymentResponse.observeNullable(this) { paymentResponse -> + hideLoader() + val paymentSdkInitParams = + PaymentSdkInitParams( + token = paymentResponse?.tokenDetails?.token.orEmpty(), + requestId = null, + mintToken = false, + paymentPreFetchMethodRequest = + PaymentPrefetchMethodRequest( + callSdkExitOnBack = false, + previousScreenName = PaymentSource.PL.name + ), + screenType = FULL_PAYMENT_SCREEN, + paymentSource = PaymentSource.PL.name + ) + naviCheckoutViewModel.initiatePayment(paymentSdkInitParams) + } + } + + private fun observeInitiatePaymentStatus() { + lifecycleScope.launchWhenResumed { + naviCheckoutViewModel.paymentResponse.collect { data -> + if (data) { + NaviPaymentRouter.startPayment( + composePaymentsResultLauncher, + this@CustomPaymentActivity + ) + } + } + } + } + + private val composePaymentsResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == 0) return@registerForActivityResult + val status = + result + ?.data + ?.extras + ?.getString( + com.navi.payment.utils.Constants.STATUS.uppercase(Locale.getDefault()) + ) + when (status) { + PaymentSdkTypes.DISMISS_LOADER.name -> Unit + PaymentSdkTypes.TRANSACTION_SUCCESS.name -> { + showLoader() + redirectToPaymentSuccessScreen() + } + else -> Unit + } + } + + private fun redirectToPaymentSuccessScreen() { + val intent = Intent(this, FeedbackActivity::class.java) + intent.putExtra(LOAN_ACCOUNT_NUMBER, loanAccountNumber) + intent.putExtra( + LOAN_ACCOUNT_REQUEST_ID, + paymentVM.initPaymentResponse.value?.requestId.toString() + ) + intent.putExtra(IS_SYNC_FLOW, true) + intent.putExtra(LOAN_TYPE, TYPE_PERSONAL_LOAN) + startActivity(intent) + finish() + } } diff --git a/android/app/src/main/java/com/naviapp/custom_payments/fragments/CustomPaymentCalendarReviewFragment.kt b/android/app/src/main/java/com/naviapp/custom_payments/fragments/CustomPaymentCalendarReviewFragment.kt index 4abbdaa5cd..d671566e7d 100644 --- a/android/app/src/main/java/com/naviapp/custom_payments/fragments/CustomPaymentCalendarReviewFragment.kt +++ b/android/app/src/main/java/com/naviapp/custom_payments/fragments/CustomPaymentCalendarReviewFragment.kt @@ -7,6 +7,7 @@ package com.naviapp.custom_payments.fragments +import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -27,6 +28,7 @@ import com.navi.naviwidgets.widgets.BaseNaviWidgetLayout import com.naviapp.R import com.naviapp.analytics.utils.NaviAnalytics import com.naviapp.common.fragment.InfoBottomSheetListener +import com.naviapp.custom_payments.listener.InitiatePaymentListener import com.naviapp.custom_payments.view_models.CustomPaymentCalendarVM import com.naviapp.databinding.FragmentCustomPaymentCalendarReviewBinding import com.naviapp.part_prepayment.PartPrePaymentActivity @@ -36,6 +38,7 @@ import com.naviapp.payment.activities.NaviPaymentActivity import com.naviapp.payment.models.Amount import com.naviapp.utils.Constants import com.naviapp.utils.Constants.LOAN_TYPE +import com.naviapp.utils.Constants.TYPE_PERSONAL_LOAN import com.naviapp.utils.LOAN_ACCOUNT_NUMBER import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch @@ -47,6 +50,7 @@ class CustomPaymentCalendarReviewFragment : ViewModelProvider(this).get(CustomPaymentCalendarVM::class.java) } private lateinit var binding: FragmentCustomPaymentCalendarReviewBinding + private lateinit var initiatePaymentListener: InitiatePaymentListener override fun onCreateView( inflater: LayoutInflater, @@ -63,6 +67,11 @@ class CustomPaymentCalendarReviewFragment : return binding.root } + override fun onAttach(context: Context) { + super.onAttach(context) + initiatePaymentListener = context as InitiatePaymentListener + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initError(customPaymentCalendarVM, actionErrorV2Enabled = true) @@ -148,12 +157,21 @@ class CustomPaymentCalendarReviewFragment : val symbol = firstOrNull { it.key == PartPrePaymentActivity.SYMBOL }?.value val paymentType = firstOrNull { it.key == PartPrePaymentActivity.PAYMENT_TYPE }?.value loanType = firstOrNull { it.key == Constants.LOAN_TYPE }?.value - startPayment( - Amount(amountData?.toDoubleOrNull(), currency = currency, symbol = symbol), - partPrePaymentRescheduleType = repaymentType, - paymentType = paymentType, - loanType = loanType - ) + if (loanType == TYPE_PERSONAL_LOAN && ::initiatePaymentListener.isInitialized) { + initiatePaymentListener.initiatePayment( + amount = Amount(amountData?.toDoubleOrNull(), currency, symbol), + repaymentType = paymentType, + loanAccountNumber = loanAccountNumber, + loanType = loanType + ) + } else { + startPayment( + Amount(amountData?.toDoubleOrNull(), currency = currency, symbol = symbol), + partPrePaymentRescheduleType = repaymentType, + paymentType = paymentType, + loanType = loanType + ) + } } } diff --git a/android/app/src/main/java/com/naviapp/custom_payments/fragments/ForecloseLoanFragment.kt b/android/app/src/main/java/com/naviapp/custom_payments/fragments/ForecloseLoanFragment.kt index 01b1a2f897..1c6f1db1b6 100644 --- a/android/app/src/main/java/com/naviapp/custom_payments/fragments/ForecloseLoanFragment.kt +++ b/android/app/src/main/java/com/naviapp/custom_payments/fragments/ForecloseLoanFragment.kt @@ -7,6 +7,7 @@ package com.naviapp.custom_payments.fragments +import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -33,6 +34,7 @@ import com.navi.naviwidgets.widgets.BaseNaviWidgetLayout import com.naviapp.R import com.naviapp.analytics.utils.NaviAnalytics import com.naviapp.common.fragment.InfoBottomSheetListener +import com.naviapp.custom_payments.listener.InitiatePaymentListener import com.naviapp.databinding.FragmentForecloseLoanBinding import com.naviapp.network.ApiErrorTagType import com.naviapp.part_prepayment.PartPrePaymentActivity @@ -43,6 +45,7 @@ import com.naviapp.payment.fragments.PaymentType import com.naviapp.payment.models.Amount import com.naviapp.utils.CLOSURE_TYPE import com.naviapp.utils.Constants.LOAN_TYPE +import com.naviapp.utils.Constants.TYPE_PERSONAL_LOAN import com.naviapp.utils.LOAN_ACCOUNT_NUMBER import kotlinx.coroutines.launch @@ -61,6 +64,7 @@ class ForecloseLoanFragment : private var termsAndConditionsBottomSheet: BottomSheetInfo? = null private var paymentFooterWidget: PaymentFooterWidget? = null private var repaymentType: String? = null + private lateinit var initiatePaymentListener: InitiatePaymentListener override fun onCreateView( inflater: LayoutInflater, @@ -93,6 +97,11 @@ class ForecloseLoanFragment : initObservers() } + override fun onAttach(context: Context) { + super.onAttach(context) + initiatePaymentListener = context as InitiatePaymentListener + } + private fun initObservers() { viewLifecycleOwner.lifecycleScope.launchWhenStarted { launch { @@ -266,12 +275,20 @@ class ForecloseLoanFragment : val currency = firstOrNull { it.key == PartPrePaymentActivity.CURRENCY }?.value val symbol = firstOrNull { it.key == PartPrePaymentActivity.SYMBOL }?.value loanType = firstOrNull { it.key == LOAN_TYPE }?.value - onPaymentClick( - Amount(amountData?.toDoubleOrNull(), currency = currency, symbol = symbol), - true, - repaymentType = repaymentType ?: PaymentType.SCHEDULED_PRE_CLOSURE.name, - loanType - ) + if (loanType == TYPE_PERSONAL_LOAN && ::initiatePaymentListener.isInitialized) { + initiatePaymentListener.initiatePayment( + amount = Amount(amountData?.toDoubleOrNull(), currency, symbol), + loanAccountNumber = loanAccountNumber, + loanType = loanType + ) + } else { + onPaymentClick( + Amount(amountData?.toDoubleOrNull(), currency = currency, symbol = symbol), + true, + repaymentType = repaymentType ?: PaymentType.SCHEDULED_PRE_CLOSURE.name, + loanType + ) + } } } } diff --git a/android/app/src/main/java/com/naviapp/custom_payments/fragments/LoanRepaymentOptionsFragment.kt b/android/app/src/main/java/com/naviapp/custom_payments/fragments/LoanRepaymentOptionsFragment.kt index 4843725655..50b0b22bff 100644 --- a/android/app/src/main/java/com/naviapp/custom_payments/fragments/LoanRepaymentOptionsFragment.kt +++ b/android/app/src/main/java/com/naviapp/custom_payments/fragments/LoanRepaymentOptionsFragment.kt @@ -7,6 +7,7 @@ package com.naviapp.custom_payments.fragments +import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -52,6 +53,7 @@ import com.naviapp.R import com.naviapp.analytics.utils.NaviAnalytics import com.naviapp.analytics.utils.NaviAnalytics.Companion.NORMAL_FLOW import com.naviapp.common.fragment.InfoBottomSheetListener +import com.naviapp.custom_payments.listener.InitiatePaymentListener import com.naviapp.custom_payments.view_models.LoanRepaymentTypeVM import com.naviapp.databinding.FragmentLoanRepaymentOptionsBinding import com.naviapp.part_prepayment.PartPrePaymentActivity @@ -84,6 +86,7 @@ class LoanRepaymentOptionsFragment : private var inputBinding: ViewDataBinding? = null private var infoWithTimerV2WidgetBinding: ViewDataBinding? = null private var loanTypeFromArgument = "" + private lateinit var initiatePaymentListener: InitiatePaymentListener override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -110,6 +113,11 @@ class LoanRepaymentOptionsFragment : return binding.root } + override fun onAttach(context: Context) { + super.onAttach(context) + initiatePaymentListener = context as InitiatePaymentListener + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) init() @@ -448,11 +456,21 @@ class LoanRepaymentOptionsFragment : repaymentType = paymentType ) } - initiatePayment( - amount = Amount(amountData.toDoubleOrNull(), currency, symbol), - isPreClosure = preClosure, - repaymentType = paymentType - ) + if (loanType == TYPE_PERSONAL_LOAN && ::initiatePaymentListener.isInitialized) { + initiatePaymentListener.initiatePayment( + amount = Amount(amountData.toDoubleOrNull(), currency, symbol), + isPreClosure = preClosure, + repaymentType = paymentType, + loanAccountNumber = loanAccountNumber, + loanType = loanType + ) + } else { + initiatePayment( + amount = Amount(amountData.toDoubleOrNull(), currency, symbol), + isPreClosure = preClosure, + repaymentType = paymentType + ) + } } } } diff --git a/android/app/src/main/java/com/naviapp/custom_payments/fragments/RepaymentTypeFragment.kt b/android/app/src/main/java/com/naviapp/custom_payments/fragments/RepaymentTypeFragment.kt index 38bcb46046..bd5718f065 100644 --- a/android/app/src/main/java/com/naviapp/custom_payments/fragments/RepaymentTypeFragment.kt +++ b/android/app/src/main/java/com/naviapp/custom_payments/fragments/RepaymentTypeFragment.kt @@ -7,6 +7,7 @@ package com.naviapp.custom_payments.fragments +import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -44,6 +45,7 @@ import com.naviapp.analytics.utils.NaviAnalytics.Companion.COLENDING_BALANCE_TRA import com.naviapp.analytics.utils.NaviAnalytics.Companion.ELIGIBLE_FOR_BALANCE_TRANSFER import com.naviapp.analytics.utils.NaviAnalytics.Companion.FALSE import com.naviapp.common.fragment.InfoBottomSheetListener +import com.naviapp.custom_payments.listener.InitiatePaymentListener import com.naviapp.custom_payments.view_models.CustomPaymentTypeVM import com.naviapp.databinding.FragmentRepaymentTypeBinding import com.naviapp.network.ApiErrorTagType @@ -59,6 +61,7 @@ import com.naviapp.utils.Constants.LOAN_TYPE import com.naviapp.utils.Constants.PART_PRE_PAYMENT import com.naviapp.utils.Constants.SAVE_AGREEMENT import com.naviapp.utils.Constants.TRUE +import com.naviapp.utils.Constants.TYPE_PERSONAL_LOAN import com.naviapp.utils.LOAN_ACCOUNT_NUMBER import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch @@ -84,6 +87,7 @@ class RepaymentTypeFragment : InitiateRescheduleLoanAgreementGenerationRequest? = null private var loanTypeFromArgument = "" + private lateinit var initiatePaymentListener: InitiatePaymentListener override fun onCreateView( inflater: LayoutInflater, @@ -128,6 +132,11 @@ class RepaymentTypeFragment : init() } + override fun onAttach(context: Context) { + super.onAttach(context) + initiatePaymentListener = context as InitiatePaymentListener + } + private fun init() { viewLifecycleOwner.lifecycleScope.launchWhenStarted { launch { customPaymentTypeVM.widgetDataResponse.collect { setWidgetState(it) } } @@ -339,12 +348,25 @@ class RepaymentTypeFragment : val paymentType = firstOrNull { it.key == PartPrePaymentActivity.PAYMENT_TYPE }?.value loanType = firstOrNull { it.key == Constants.LOAN_TYPE }?.value - startPayment( - Amount(amountData?.toDoubleOrNull(), currency = currency, symbol = symbol), - partPrePaymentRescheduleType = type as? String, - paymentType = paymentType, - loanType = loanType - ) + if (loanType == TYPE_PERSONAL_LOAN && ::initiatePaymentListener.isInitialized) { + initiatePaymentListener.initiatePayment( + amount = Amount(amountData?.toDoubleOrNull(), currency, symbol), + repaymentType = paymentType, + loanAccountNumber = loanAccountNumber, + loanType = loanType + ) + } else { + startPayment( + Amount( + amountData?.toDoubleOrNull(), + currency = currency, + symbol = symbol + ), + partPrePaymentRescheduleType = type as? String, + paymentType = paymentType, + loanType = loanType + ) + } } } } diff --git a/android/app/src/main/java/com/naviapp/custom_payments/listener/InitiatePaymentListener.kt b/android/app/src/main/java/com/naviapp/custom_payments/listener/InitiatePaymentListener.kt new file mode 100644 index 0000000000..971a7a803b --- /dev/null +++ b/android/app/src/main/java/com/naviapp/custom_payments/listener/InitiatePaymentListener.kt @@ -0,0 +1,23 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.naviapp.custom_payments.listener + +import com.naviapp.payment.models.Amount + +interface InitiatePaymentListener { + fun initiatePayment( + amount: Amount, + isPreClosure: Boolean = false, + repaymentType: String? = null, + sourceOfFunds: String? = null, + otherSourceOfFunds: String? = null, + partPrePaymentRescheduleType: String? = null, + loanAccountNumber: String? = null, + loanType: String? = null + ) +} diff --git a/android/app/src/main/java/com/naviapp/home/compose/activity/HomePageActivity.kt b/android/app/src/main/java/com/naviapp/home/compose/activity/HomePageActivity.kt index 57cfafce7d..72d96454d9 100644 --- a/android/app/src/main/java/com/naviapp/home/compose/activity/HomePageActivity.kt +++ b/android/app/src/main/java/com/naviapp/home/compose/activity/HomePageActivity.kt @@ -19,6 +19,8 @@ import android.widget.Toast import androidx.activity.SystemBarStyle import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle @@ -46,7 +48,6 @@ import com.navi.base.utils.ConnectivityObserver import com.navi.base.utils.ConnectivityObserverImpl import com.navi.base.utils.DateUtils import com.navi.base.utils.isNotNull -import com.navi.base.utils.isNotNullAndNotEmpty import com.navi.base.utils.isNull import com.navi.base.utils.orElse import com.navi.base.utils.orFalse @@ -86,7 +87,6 @@ import com.navi.common.utils.Constants.ScreenLockConstants.IS_SCREEN_LOCK_ENABLE import com.navi.common.utils.TemporaryStorageHelper import com.navi.common.utils.getDensityName import com.navi.common.utils.getDeviceSignature -import com.navi.common.utils.getErrorData import com.navi.common.utils.getInstalledDynamicModulesCommaSeparated import com.navi.common.utils.getLocalStorageLocation import com.navi.common.utils.getNetworkType @@ -129,15 +129,16 @@ import com.navi.payment.model.initiatesdk.PaymentPrefetchMethodRequest import com.navi.payment.model.paymentmethod.PaymentMethodResponse import com.navi.payment.model.paymentmethod.PaymentScreenIntegrationMethodDetailResponse import com.navi.payment.model.paymentresult.PaymentPrefetchMethodDetailsResponse +import com.navi.payment.nativepayment.router.NaviPaymentRouter +import com.navi.payment.nativepayment.sharedviewmodel.NaviCheckoutViewModel import com.navi.payment.paymenthandler.model.PaymentRequest import com.navi.payment.paymenthandler.model.PaymentStatusData import com.navi.payment.paymentscreen.model.PaymentActivityResponse -import com.navi.payment.paymentscreen.model.PaymentInitiateConfig import com.navi.payment.paymentscreen.ui.PaymentMethodSuccessFragment import com.navi.payment.paymentscreen.utils.PaymentNavigator import com.navi.payment.paymentscreen.viewmodel.PaymentScreenSharedViewModel +import com.navi.payment.utils.Constants.FULL_PAYMENT_SCREEN import com.navi.payment.utils.Constants.PAYMENT_METHOD_REQUEST_CODE -import com.navi.payment.utils.PaymentAnalytics import com.navi.payment.utils.PaymentSource import com.navi.paymentclients.model.InitiatePaymentRequest as PMSInitiatePaymentRequest import com.navi.paymentclients.viewmodel.base.PaymentManager @@ -202,6 +203,7 @@ import com.naviapp.payment.models.InitiatePaymentRequest import com.naviapp.payment.states.BottomSheetInfoV2State import com.naviapp.payment.viewmodel.PaymentVM import com.naviapp.personalloan.getloan.loandetails.fragments.DailyOfferBottomSheet +import com.naviapp.personalloanrevamp.common.utils.PaymentSdkResultUtil import com.naviapp.personalloanrevamp.customview.DailyOfferBottomSheetV2 import com.naviapp.registration.helper.AppsFlyerDeeplinkHandler import com.naviapp.registration.helper.isLocationPermissionGranted @@ -227,6 +229,7 @@ import com.naviapp.utils.toast import dagger.hilt.android.AndroidEntryPoint import io.branch.referral.Branch import java.lang.ref.WeakReference +import java.util.Locale import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineScope @@ -282,6 +285,8 @@ class HomePageActivity : private val connectivityObserver: ConnectivityObserver by lazy { ConnectivityObserverImpl(context = applicationContext) } + private val naviCheckoutViewModel by viewModels() + private val naviAnalyticsWidgetEventTracker = NaviAnalytics.naviAnalytics.Widget() private val userDataAnalyticsTracker = NaviAnalytics.naviAnalytics.UserData() @@ -589,6 +594,7 @@ class HomePageActivity : } } } + observeInitiatePaymentStatus() } private fun observeGIPaymentFailed() { @@ -2104,50 +2110,33 @@ class HomePageActivity : private fun observeInitPaymentRequestData() { if (isEnabled() && paymentVM.initPaymentResponse.hasObservers()) return - paymentVM.initPaymentResponse.observeNullable(this) { data -> - paymentInitListener?.setPaymentSyncStatus(data?.syncFlow.orFalse()) - if (data?.syncFlow.orFalse()) { - NaviAnalytics.naviAnalytics - .Payment() - .onPlPaymentTokenRecieved( - isValidToken = data?.tokenDetails?.token.isNotNullAndNotEmpty() + val paymentSdkInitParams = + PaymentSdkInitParams( + token = data?.tokenDetails?.token.orEmpty(), + requestId = null, + mintToken = false, + paymentPreFetchMethodRequest = + PaymentPrefetchMethodRequest( + callSdkExitOnBack = false, + previousScreenName = PaymentSource.PL.name + ), + screenType = FULL_PAYMENT_SCREEN, + paymentSource = PaymentSource.PL.name + ) + naviCheckoutViewModel.initiatePayment(paymentSdkInitParams) + } + } + + private fun observeInitiatePaymentStatus() { + lifecycleScope.launch { + naviCheckoutViewModel.paymentResponse.collect { dataRecieved -> + if (dataRecieved) { + hideLoader() + NaviPaymentRouter.startPayment( + composePaymentsResultLauncher, + this@HomePageActivity ) - if (data?.tokenDetails?.token.isNullOrEmpty()) { - paymentVM.setErrorData( - listOf( - getErrorData( - context = this, - logMessage = "pl_${PaymentAnalytics.EMPTY_TOKEN_RECEIVED}" - ) - ) - ) - } else { - this.repaymentType = data?.repaymentType.orEmpty() - this.notificationPath = data?.notificationPath.orEmpty() - paymentManager.init( - token = data?.tokenDetails?.token.orEmpty(), - activity = this, - listener = this, - requestId = data?.requestId, - initiatePaymentRequest = paymentVM.paymentInitiateRequest, - razorPaySDK = paymentInitListener?.getRazorPaySDK(), - optimisationDisable = - FirebaseRemoteConfigHelper.getBoolean( - FirebaseRemoteConfigHelper.PAYMENT_OPTIMISATION_DISABLE - ), - paymentInitiateConfig = PaymentInitiateConfig.S2S_INTEGRATION - ) - } - } else { - data?.requestId?.let { - firebaseInit( - it, - INIT_REPAYMENT, - data.notificationPath.orEmpty(), - data.repaymentType - ) - apiPollInit(it, INIT_REPAYMENT, data.repaymentType) } } } @@ -2346,4 +2335,22 @@ class HomePageActivity : } } } + + private val composePaymentsResultLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == 0) return@registerForActivityResult + val status = + result + ?.data + ?.extras + ?.getString( + com.navi.payment.utils.Constants.STATUS.uppercase(Locale.getDefault()) + ) + PaymentSdkResultUtil.paymentSdkCallbackStatus( + status, + this, + loanAccountNumber, + paymentVM.initPaymentResponse.value?.requestId.toString() + ) + } } diff --git a/android/app/src/main/java/com/naviapp/part_prepayment/fragments/PartPrePaymentEmiCalendarReviewFragment.kt b/android/app/src/main/java/com/naviapp/part_prepayment/fragments/PartPrePaymentEmiCalendarReviewFragment.kt index d379b92d7f..4054a605b6 100644 --- a/android/app/src/main/java/com/naviapp/part_prepayment/fragments/PartPrePaymentEmiCalendarReviewFragment.kt +++ b/android/app/src/main/java/com/naviapp/part_prepayment/fragments/PartPrePaymentEmiCalendarReviewFragment.kt @@ -7,6 +7,7 @@ package com.naviapp.part_prepayment.fragments +import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -27,6 +28,7 @@ import com.navi.naviwidgets.widgets.BaseNaviWidgetLayout import com.naviapp.R import com.naviapp.analytics.utils.NaviAnalytics import com.naviapp.common.fragment.InfoBottomSheetListener +import com.naviapp.custom_payments.listener.InitiatePaymentListener import com.naviapp.databinding.FragmentPartPrePaymentEmiCalendarReviewBinding import com.naviapp.part_prepayment.PartPrePaymentActivity import com.naviapp.part_prepayment.states.GenericWidgetState @@ -35,6 +37,7 @@ import com.naviapp.payment.activities.NaviPaymentActivity import com.naviapp.payment.models.Amount import com.naviapp.utils.Constants import com.naviapp.utils.Constants.LOAN_TYPE +import com.naviapp.utils.Constants.TYPE_PERSONAL_LOAN import com.naviapp.utils.LOAN_ACCOUNT_NUMBER import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch @@ -48,6 +51,8 @@ class PartPrePaymentEmiCalendarReviewFragment : } private lateinit var binding: FragmentPartPrePaymentEmiCalendarReviewBinding + private lateinit var initiatePaymentListener: InitiatePaymentListener + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -70,6 +75,11 @@ class PartPrePaymentEmiCalendarReviewFragment : init() } + override fun onAttach(context: Context) { + super.onAttach(context) + initiatePaymentListener = context as InitiatePaymentListener + } + override fun onClick(naviClickAction: NaviClickAction, widgetId: String?) { if (naviClickAction is CtaData) { when (naviClickAction.url) { @@ -103,12 +113,21 @@ class PartPrePaymentEmiCalendarReviewFragment : val symbol = firstOrNull { it.key == PartPrePaymentActivity.SYMBOL }?.value val paymentType = firstOrNull { it.key == PartPrePaymentActivity.PAYMENT_TYPE }?.value loanType = firstOrNull() { it.key == Constants.LOAN_TYPE }?.value - startPayment( - Amount(amountData?.toDoubleOrNull(), currency = currency, symbol = symbol), - partPrePaymentRescheduleType = repaymentType, - paymentType = paymentType, - loanType = loanType - ) + if (loanType == TYPE_PERSONAL_LOAN && ::initiatePaymentListener.isInitialized) { + initiatePaymentListener.initiatePayment( + amount = Amount(amountData?.toDoubleOrNull(), currency, symbol), + repaymentType = paymentType, + loanAccountNumber = loanAccountNumber, + loanType = loanType + ) + } else { + startPayment( + Amount(amountData?.toDoubleOrNull(), currency = currency, symbol = symbol), + partPrePaymentRescheduleType = repaymentType, + paymentType = paymentType, + loanType = loanType + ) + } } } diff --git a/android/app/src/main/java/com/naviapp/payment_behaviour/fragments/PaymentBehaviourFragment.kt b/android/app/src/main/java/com/naviapp/payment_behaviour/fragments/PaymentBehaviourFragment.kt index 0ac26561f0..a46f17d4d2 100644 --- a/android/app/src/main/java/com/naviapp/payment_behaviour/fragments/PaymentBehaviourFragment.kt +++ b/android/app/src/main/java/com/naviapp/payment_behaviour/fragments/PaymentBehaviourFragment.kt @@ -9,6 +9,7 @@ package com.naviapp.payment_behaviour.fragments import android.animation.Animator import android.animation.ValueAnimator +import android.content.Context import android.graphics.Color import android.media.MediaPlayer import android.os.Bundle @@ -62,6 +63,7 @@ import com.naviapp.common.fragment.InfoBottomSheetV3 import com.naviapp.common.navigator.NaviDeepLinkNavigator import com.naviapp.custom_payments.fragments.PaymentFooterBottomSheet import com.naviapp.custom_payments.fragments.PaymentFooterBottomSheetListener +import com.naviapp.custom_payments.listener.InitiatePaymentListener import com.naviapp.databinding.FragmentPaymentBehaviourBinding import com.naviapp.databinding.LayoutAnimatedTextWithLoaderFullScreenViewBinding import com.naviapp.part_prepayment.PartPrePaymentActivity @@ -102,6 +104,7 @@ class PaymentBehaviourFragment : widgetCallback = this, factory = ViewHolderFactoryImpl() ) + private lateinit var initiatePaymentListener: InitiatePaymentListener override fun onCreateView( inflater: LayoutInflater, @@ -120,6 +123,11 @@ class PaymentBehaviourFragment : init() } + override fun onAttach(context: Context) { + super.onAttach(context) + initiatePaymentListener = context as InitiatePaymentListener + } + override fun widgetAnalytics(genericAnalyticsData: GenericAnalyticsData?) { NaviAnalytics.naviAnalytics.sendGenericAnalyticsData(genericAnalyticsData, screenName) } @@ -533,7 +541,15 @@ class PaymentBehaviourFragment : amount = Amount(amountData.toDoubleOrNull(), currency, symbol) ) } - initiatePayment(amount = Amount(amountData.toDoubleOrNull(), currency, symbol)) + if (loanType == TYPE_PERSONAL_LOAN && ::initiatePaymentListener.isInitialized) { + initiatePaymentListener.initiatePayment( + amount = Amount(amountData.toDoubleOrNull(), currency, symbol), + loanAccountNumber = loanAccountNumber, + loanType = loanType + ) + } else { + initiatePayment(amount = Amount(amountData.toDoubleOrNull(), currency, symbol)) + } } } } diff --git a/android/app/src/main/java/com/naviapp/personalloan/getloan/emi/fragments/EMIDateChangeFragment.kt b/android/app/src/main/java/com/naviapp/personalloan/getloan/emi/fragments/EMIDateChangeFragment.kt index 8ec7c8cc2d..3a67959986 100644 --- a/android/app/src/main/java/com/naviapp/personalloan/getloan/emi/fragments/EMIDateChangeFragment.kt +++ b/android/app/src/main/java/com/naviapp/personalloan/getloan/emi/fragments/EMIDateChangeFragment.kt @@ -45,6 +45,7 @@ import com.naviapp.analytics.utils.NaviAnalytics import com.naviapp.common.listeners.FooterInteractionListener import com.naviapp.common.listeners.KeyValueListener import com.naviapp.common.navigator.NaviDeepLinkNavigator +import com.naviapp.custom_payments.listener.InitiatePaymentListener import com.naviapp.dashboard.listeners.FragmentInteractionListener import com.naviapp.databinding.EmiDateChangeFragmentBinding import com.naviapp.models.AnimationData @@ -84,6 +85,7 @@ class EMIDateChangeFragment : PaymentBaseFragment(), FooterInteractionListener { private val viewModel by lazy { ViewModelProvider(this).get(EMIDateChangeFragmentVM::class.java) } + private lateinit var initiatePaymentListener: InitiatePaymentListener override val screenName: String get() = TAG @@ -93,6 +95,7 @@ class EMIDateChangeFragment : PaymentBaseFragment(), FooterInteractionListener { headerInteractionListener = context as? HeaderInteractionListener listener = context as? FragmentInteractionListener fragmentInterchangeListener = context as? FragmentInterchangeListener + initiatePaymentListener = context as InitiatePaymentListener } override fun onDetach() { @@ -494,10 +497,30 @@ class EMIDateChangeFragment : PaymentBaseFragment(), FooterInteractionListener { ) ) } - initiatePayment( - amount = - Amount(amountData.toDoubleOrNull(), currency, symbol) - ) + if ( + loanType == TYPE_PERSONAL_LOAN && + ::initiatePaymentListener.isInitialized + ) { + initiatePaymentListener.initiatePayment( + amount = + Amount( + amountData.toDoubleOrNull(), + currency, + symbol + ), + loanAccountNumber = loanAccountNumber, + loanType = loanType + ) + } else { + initiatePayment( + amount = + Amount( + amountData.toDoubleOrNull(), + currency, + symbol + ) + ) + } } } CtaType.CLOSE_BOTTOM_SHEET.name -> { diff --git a/android/app/src/main/java/com/naviapp/personalloanrevamp/common/utils/PaymentSdkResultUtil.kt b/android/app/src/main/java/com/naviapp/personalloanrevamp/common/utils/PaymentSdkResultUtil.kt new file mode 100644 index 0000000000..ca03a1ef02 --- /dev/null +++ b/android/app/src/main/java/com/naviapp/personalloanrevamp/common/utils/PaymentSdkResultUtil.kt @@ -0,0 +1,49 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.naviapp.personalloanrevamp.common.utils + +import android.content.Intent +import com.navi.payment.model.common.PaymentSdkTypes +import com.naviapp.home.compose.activity.HomePageActivity +import com.naviapp.payment.activities.FeedbackActivity +import com.naviapp.utils.Constants.LOAN_TYPE +import com.naviapp.utils.Constants.TYPE_PERSONAL_LOAN +import com.naviapp.utils.IS_SYNC_FLOW +import com.naviapp.utils.LOAN_ACCOUNT_NUMBER +import com.naviapp.utils.LOAN_ACCOUNT_REQUEST_ID + +object PaymentSdkResultUtil { + + fun paymentSdkCallbackStatus( + status: String?, + activity: HomePageActivity, + loanAccountNumber: String?, + requestId: String + ) { + when (status) { + PaymentSdkTypes.DISMISS_LOADER.name -> Unit + PaymentSdkTypes.TRANSACTION_SUCCESS.name -> { + redirectToPaymentSuccessScreen(activity, loanAccountNumber, requestId) + } + else -> Unit + } + } + + private fun redirectToPaymentSuccessScreen( + activity: HomePageActivity, + loanAccountNumber: String?, + requestId: String + ) { + val intent = Intent(activity, FeedbackActivity::class.java) + intent.putExtra(LOAN_ACCOUNT_NUMBER, loanAccountNumber) + intent.putExtra(LOAN_ACCOUNT_REQUEST_ID, requestId) + intent.putExtra(IS_SYNC_FLOW, true) + intent.putExtra(LOAN_TYPE, TYPE_PERSONAL_LOAN) + activity.startActivity(intent) + } +} diff --git a/android/navi-payment/src/main/java/com/navi/payment/paymentscreen/ui/PaymentLoaderFragment.kt b/android/navi-payment/src/main/java/com/navi/payment/paymentscreen/ui/PaymentLoaderFragment.kt index c7c9b3a469..9d61c44281 100644 --- a/android/navi-payment/src/main/java/com/navi/payment/paymentscreen/ui/PaymentLoaderFragment.kt +++ b/android/navi-payment/src/main/java/com/navi/payment/paymentscreen/ui/PaymentLoaderFragment.kt @@ -66,8 +66,6 @@ import com.navi.payment.paymentscreen.utils.PaymentScreenUtil import com.navi.payment.paymentscreen.viewmodel.PaymentLoaderUiState import com.navi.payment.paymentscreen.viewmodel.PaymentLoaderViewModel import com.navi.payment.paymentscreen.viewmodel.PaymentScreenSharedViewModel -import com.navi.payment.utils.Constants.CHANNEL_PL -import com.navi.payment.utils.Constants.CLIENT import com.navi.payment.utils.Constants.CLIENT_STATUS_POLL_API_FAILURE import com.navi.payment.utils.Constants.FLOW_PAYMENT_LOADER_RESPONSE import com.navi.payment.utils.Constants.KEY_CTA_URL @@ -216,13 +214,7 @@ class PaymentLoaderFragment : PaymentScreenBaseFragment(), PaymentBackListener { if (response.clientPollRequired.orTrue()) { // The below check is for legacy handling, going forward clients need to // handle the client polling to their BE - if ( - viewModel.loaderScreenBundleData.value - ?.paymentSource - ?.equals(CHANNEL_PL, true) == true - ) { - apiPollInitForClientOrderStatus(type = CLIENT) - } else if (response.data?.metadata == null) { + if (response.data?.metadata == null) { postResultAndFinish(response.data, TRANSACTION_SUCCESS) } else { showPaymentSuccessLoader(