diff --git a/android/app/src/main/java/com/naviapp/analytics/utils/NaviSDKHelper.kt b/android/app/src/main/java/com/naviapp/analytics/utils/NaviSDKHelper.kt index 3672bed084..ef6b21a7cf 100644 --- a/android/app/src/main/java/com/naviapp/analytics/utils/NaviSDKHelper.kt +++ b/android/app/src/main/java/com/naviapp/analytics/utils/NaviSDKHelper.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2019-2023 by Navi Technologies Limited + * * Copyright © 2019-2024 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -163,7 +163,7 @@ object NaviSDKHelper { RazorpayHelper().clearRazorPayData(context) UserManager.clearUser() DeeplinkManager.logOut() - NaviApplication.instance.naviPayManager.get().logout() + NaviApplication.instance.naviPayManager.get().onAppLogout() NaviApplication.instance.notificationManager.get().logout() } diff --git a/android/app/src/main/java/com/naviapp/common/navigator/NaviDeepLinkNavigator.kt b/android/app/src/main/java/com/naviapp/common/navigator/NaviDeepLinkNavigator.kt index ab403e855f..bf71455365 100644 --- a/android/app/src/main/java/com/naviapp/common/navigator/NaviDeepLinkNavigator.kt +++ b/android/app/src/main/java/com/naviapp/common/navigator/NaviDeepLinkNavigator.kt @@ -1018,7 +1018,7 @@ object NaviDeepLinkNavigator : DeepLinkListener { intent = Intent(activity, PlMandatePermissionActivity::class.java) } NAVIPAY_DELETE_USER_DATA -> { - NaviApplication.instance.naviPayManager.get().logout() + NaviApplication.instance.naviPayManager.get().triggerNaviPayHardLogout() } AP_FINISH_OK -> { activity?.setResult(RESULT_OK) diff --git a/android/app/src/main/java/com/naviapp/registration/RegistrationActivity.kt b/android/app/src/main/java/com/naviapp/registration/RegistrationActivity.kt index b0530e3b2e..0e737eff97 100644 --- a/android/app/src/main/java/com/naviapp/registration/RegistrationActivity.kt +++ b/android/app/src/main/java/com/naviapp/registration/RegistrationActivity.kt @@ -660,6 +660,9 @@ class RegistrationActivity : unblockInteractability() TemporaryStorageHelper.clear() AmcTaskManager.clearData(true) + NaviApplication.instance.naviPayManager + .get() + .onAppLogin(otpResponse.externalCustomerId) homeVM.fetchAndSaveHomeTabWithTimeOut( density = getDensityName(context = this), connectivityType = getNetworkType(context = this), diff --git a/android/app/src/main/java/com/naviapp/utils/Utility.kt b/android/app/src/main/java/com/naviapp/utils/Utility.kt index 27c7153f3d..099c9f731b 100644 --- a/android/app/src/main/java/com/naviapp/utils/Utility.kt +++ b/android/app/src/main/java/com/naviapp/utils/Utility.kt @@ -95,6 +95,8 @@ import com.navi.naviwidgets.validations.ValidationJsonDeserializer import com.navi.naviwidgets.widgets.NaviWidgetJsonDeserializer import com.navi.naviwidgets.widgets.NaviWidgetJsonSerializer import com.navi.naviwidgets.widgets.ParameterValueJsonDeserializer +import com.navi.pay.common.utils.getExcludeSecureSharedPrefKeys +import com.navi.pay.utils.NAVI_PAY_NON_ENCRYPT_SHARED_PREF_DATA_KEYS import com.navi.uitron.model.action.TriggerApiAction import com.navi.uitron.model.data.UiTronAction import com.navi.uitron.model.data.UiTronData @@ -113,7 +115,6 @@ import com.naviapp.common.navigator.NaviDeepLinkNavigator import com.naviapp.common.navigator.NaviDeepLinkNavigator.ERROR_V2 import com.naviapp.common.navigator.NaviDeepLinkNavigator.getPersonalLoanDynamicModuleIntent import com.naviapp.home.activity.OnBoardingActivity -import com.naviapp.home.compose.activity.HomePageActivity import com.naviapp.home.dashboard.models.response.DashboardContentResponse import com.naviapp.manager.usecase.UserDataUploadWorkerUseCase import com.naviapp.models.ColorData @@ -122,6 +123,7 @@ import com.naviapp.models.response.WidgetConfig import com.naviapp.models.response.WidgetConfigLayoutParams import com.naviapp.permission.fragments.MandatePermissionFragment import com.naviapp.personalloanrevamp.models.response.BottomSheetConfig +import com.naviapp.registration.RegistrationActivity import com.naviapp.utils.Constants.ERROR_DATA import com.naviapp.utils.Constants.HYPERVERGE_FILES_PATH import com.naviapp.utils.Constants.INDIAN_COUNTRY_CODE @@ -162,18 +164,20 @@ fun getAppName(): String { fun deleteCacheAndOpenLoginPage(context: Context = NaviApplication.instance) { try { if (BaseUtils.isUserLoggedIn()) { + BaseUtils.saveCurrentExternalCustomerId(BaseUtils.getExternalCustomerId().orEmpty()) TemporaryStorageHelper.clear() AmcTaskManager.clearData(true) clearData() clearHypervergeData() - val i = Intent(context, HomePageActivity::class.java) - i.addFlags( + val intent = Intent(context, RegistrationActivity::class.java) + intent.addFlags( Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP ) + intent.putExtra(LOGIN_SOURCE, Constants.DEFAULT_LOGIN_SOURCE_FOR_WHATSAPP_LOGIN) NaviSDKHelper.logoutUser(context) - NaviApplication.instance.applicationContext.startActivity(i) + NaviApplication.instance.applicationContext.startActivity(intent) stopActiveWorkers( context, listOf(UserDataUploadWorkerUseCase.PERIODIC_USER_UPLOAD_WORKER_TAG) @@ -228,7 +232,10 @@ fun isNetworkAvailable(): Boolean { } fun clearData() { - PreferenceManager.clearPrefDataSession() + PreferenceManager.clearPrefDataSession( + excludeSharedPrefKeys = NAVI_PAY_NON_ENCRYPT_SHARED_PREF_DATA_KEYS, + excludeSecureSharedPrefKeys = getExcludeSecureSharedPrefKeys() + ) NaviPreferenceManager.clearDataOnLogout() HyperServicesHolder.onLogout { log -> val naviAnalyticsEventTracker = NaviAnalytics.naviAnalytics.Dashboard() diff --git a/android/navi-base/src/main/java/com/navi/base/sharedpref/CommonPrefConstants.kt b/android/navi-base/src/main/java/com/navi/base/sharedpref/CommonPrefConstants.kt index ae8a26f9f8..7bf81853a9 100644 --- a/android/navi-base/src/main/java/com/navi/base/sharedpref/CommonPrefConstants.kt +++ b/android/navi-base/src/main/java/com/navi/base/sharedpref/CommonPrefConstants.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2021-2023 by Navi Technologies Limited + * * Copyright © 2021-2024 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -35,4 +35,5 @@ object CommonPrefConstants { const val PREFERENCE_SSL_KEY = "sslKey" const val FAQ_RECENT_SEARCH = "FAQ_RECENT_SEARCH" const val DEVICE_LOCATION = "DEVICE_LOCATION" + const val PREVIOUS_LOGGED_IN_EXTERNAL_CUSTOMER_ID = "PREVIOUS_LOGGED_IN_EXTERNAL_CUSTOMER_ID" } diff --git a/android/navi-base/src/main/java/com/navi/base/sharedpref/PreferenceManager.kt b/android/navi-base/src/main/java/com/navi/base/sharedpref/PreferenceManager.kt index b87cfe5878..79014a92ee 100644 --- a/android/navi-base/src/main/java/com/navi/base/sharedpref/PreferenceManager.kt +++ b/android/navi-base/src/main/java/com/navi/base/sharedpref/PreferenceManager.kt @@ -16,6 +16,13 @@ import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.navi.base.sharedpref.CommonPrefConstants.CURRENT_USER import com.navi.base.sharedpref.CommonPrefConstants.IS_LOAN_JOURNEY_DATA_DELETED +import com.navi.base.utils.removeSelectiveData +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.launch import timber.log.Timber object PreferenceManager { @@ -27,12 +34,12 @@ object PreferenceManager { // Cleared on logout/endOfSession private lateinit var sharedPreferencesForSession: SharedPreferences + private var secureSharedPreferencesForSession: SharedPreferences? = null // Not cleared on logout/endOfSession private lateinit var sharedPreferencesForApp: SharedPreferences private var secureSharedPreferencesForApp: SharedPreferences? = null - private var secureSharedPreferencesForSession: SharedPreferences? = null private lateinit var gson: Gson fun init(application: Application) { @@ -179,13 +186,29 @@ object PreferenceManager { } } - fun clearPrefDataSession() { - try { - sharedPreferencesForSession.edit().clear().apply() - if (shouldUseEncryptedSharedPref()) { - secureSharedPreferencesForSession?.edit()?.clear()?.apply() - } - } catch (_: Exception) {} + fun clearPrefDataSession( + excludeSharedPrefKeys: List = listOf(), + excludeSecureSharedPrefKeys: List = listOf() + ) { + CoroutineScope(Dispatchers.IO).launch { + try { + val clearSharedPrefTasks = mutableListOf>() + clearSharedPrefTasks.add( + async { + removeSelectiveData(sharedPreferencesForSession, excludeSharedPrefKeys) + } + ) + clearSharedPrefTasks.add( + async { + removeSelectiveData( + secureSharedPreferencesForSession, + excludeSecureSharedPrefKeys + ) + } + ) + clearSharedPrefTasks.awaitAll() + } catch (_: Exception) {} + } } fun removePrefData(keys: Array) { diff --git a/android/navi-base/src/main/java/com/navi/base/utils/BaseUtils.kt b/android/navi-base/src/main/java/com/navi/base/utils/BaseUtils.kt index 128dad40f2..af19a72537 100644 --- a/android/navi-base/src/main/java/com/navi/base/utils/BaseUtils.kt +++ b/android/navi-base/src/main/java/com/navi/base/utils/BaseUtils.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2021-2023 by Navi Technologies Limited + * * Copyright © 2021-2024 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -77,6 +77,10 @@ object BaseUtils { ?: run { PreferenceManager.getStringPreference(CommonPrefConstants.PHONE_NUMBER) } } + fun getExternalCustomerId(): String? { + return PreferenceManager.getStringPreference(CommonPrefConstants.USER_EXTERNAL_ID) + } + fun getEmail(): String? { return PreferenceManager.getSecureString(CommonPrefConstants.EMAIL) ?: run { PreferenceManager.getStringPreference(CommonPrefConstants.EMAIL) } @@ -579,4 +583,17 @@ object BaseUtils { } return false } + + fun saveCurrentExternalCustomerId(externalCustomerId: String) { + PreferenceManager.saveStringPreferenceAppOnMainThread( + CommonPrefConstants.PREVIOUS_LOGGED_IN_EXTERNAL_CUSTOMER_ID, + externalCustomerId + ) + } + + fun getPreviousLoggedInExternalCustomerId(): String? { + return PreferenceManager.getStringPreferenceApp( + CommonPrefConstants.PREVIOUS_LOGGED_IN_EXTERNAL_CUSTOMER_ID + ) + } } diff --git a/android/navi-base/src/main/java/com/navi/base/utils/CommonUtils.kt b/android/navi-base/src/main/java/com/navi/base/utils/CommonUtils.kt new file mode 100644 index 0000000000..199b3e5999 --- /dev/null +++ b/android/navi-base/src/main/java/com/navi/base/utils/CommonUtils.kt @@ -0,0 +1,50 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.base.utils + +import android.content.SharedPreferences + +fun removeSelectiveData( + sharedPreferencesForSession: SharedPreferences?, + excludeSharedPrefKeys: List +) { + val data = getExcludeSharedPrefKeysData(sharedPreferencesForSession, excludeSharedPrefKeys) + sharedPreferencesForSession?.edit()?.clear()?.commit() + updateExcludeSharedPrefKeysDataBackSharedPref(sharedPreferencesForSession, data) +} + +private fun getExcludeSharedPrefKeysData( + sharedPreferencesForSession: SharedPreferences?, + excludeSharedPrefKeys: List +): Map { + val excludeSharedPrefMap = mutableMapOf() + val allSharedPref = sharedPreferencesForSession?.all + excludeSharedPrefKeys.forEach { key -> + val value = allSharedPref?.get(key) + if (value != null) { + excludeSharedPrefMap[key] = value + } + } + return excludeSharedPrefMap +} + +private fun updateExcludeSharedPrefKeysDataBackSharedPref( + sharedPreferencesForSession: SharedPreferences?, + sharedPrefKeys: Map? +) { + val sharedPrefEditor = sharedPreferencesForSession?.edit() + sharedPrefKeys?.keys?.forEach { key -> + when (val value = sharedPrefKeys[key]) { + is Boolean -> sharedPrefEditor?.putBoolean(key, value) + is String -> sharedPrefEditor?.putString(key, value) + is Long -> sharedPrefEditor?.putLong(key, value) + is Float -> sharedPrefEditor?.putFloat(key, value) + } + } + sharedPrefEditor?.apply() +} diff --git a/android/navi-common/src/main/java/com/navi/common/firebaseremoteconfig/FirebaseRemoteConfigHelper.kt b/android/navi-common/src/main/java/com/navi/common/firebaseremoteconfig/FirebaseRemoteConfigHelper.kt index 2993483681..7a8183de0e 100644 --- a/android/navi-common/src/main/java/com/navi/common/firebaseremoteconfig/FirebaseRemoteConfigHelper.kt +++ b/android/navi-common/src/main/java/com/navi/common/firebaseremoteconfig/FirebaseRemoteConfigHelper.kt @@ -144,6 +144,7 @@ object FirebaseRemoteConfigHelper { const val UPI_SCRATCH_CARD_REWARDS_POLLING_CONFIG = "UPI_SCRATCH_CARD_REWARDS_POLLING_CONFIG" const val PROXY_SELECTOR_ENABLED = "PROXY_SELECTOR_ENABLED" + const val IS_UPI_SOFT_LOGGED_OUT_DISABLED = "IS_UPI_SOFT_LOGGED_OUT_DISABLED" fun init() { remoteConfig = getFirebaseRemoteConfig() diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/analytics/NaviPayAnalytics.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/analytics/NaviPayAnalytics.kt index 55d1bfbb41..392dfc2d7d 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/analytics/NaviPayAnalytics.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/analytics/NaviPayAnalytics.kt @@ -3223,6 +3223,15 @@ class NaviPayAnalytics private constructor() { } } + inner class NaviPayManager { + fun onMerchantCustomerIdMismatch(oldMcId: String, newMcId: String) { + NaviTrackEvent.trackEventOnClickStream( + "NaviPay_Dev_Customer_McId_Mismatch", + mapOf("oldMcId" to oldMcId, "newMcId" to newMcId) + ) + } + } + inner class NaviPayViewModel { fun onErrorOccurredInGetQuerySnapshot(exception: Exception) { NaviTrackEvent.trackEventOnClickStream( diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/view/DeviceData.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/view/DeviceData.kt index a28276e554..982df06f96 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/view/DeviceData.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/view/DeviceData.kt @@ -19,10 +19,7 @@ data class DeviceData( ) fun DeviceData.isAnyEmpty(): Boolean { - return (deviceFingerPrint.isEmpty() || - deviceId.isEmpty() || - packageName.isEmpty() || - provider.isAnyEmpty()) + return (deviceId.isEmpty() || packageName.isEmpty() || provider.isAnyEmpty()) } fun NetworkProvider.isAnyEmpty(): Boolean { diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/NaviPayManager.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/NaviPayManager.kt index 8d6ae86f4e..accbd95b5f 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/NaviPayManager.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/NaviPayManager.kt @@ -18,6 +18,7 @@ import com.navi.base.utils.BaseUtils import com.navi.common.constants.EMPTY import com.navi.common.upi.TYPE import com.navi.common.upi.UpiDataType +import com.navi.pay.analytics.NaviPayAnalytics import com.navi.pay.common.model.view.DeviceData import com.navi.pay.common.model.view.UpiLiteActiveAccountInfo import com.navi.pay.common.repository.SharedPreferenceRepository @@ -29,9 +30,14 @@ import com.navi.pay.common.usecase.LitmusExperimentsUseCase import com.navi.pay.common.utils.DeviceInfoProvider import com.navi.pay.common.utils.NaviPayCommonUtils import com.navi.pay.common.utils.NaviPaySdkUtils +import com.navi.pay.common.utils.isDifferentCustomerOrNewCustomer +import com.navi.pay.common.utils.isSameOrNewUPICustomer +import com.navi.pay.common.utils.isUpiSoftLogoutDisabled import com.navi.pay.common.widget.NaviPayWidgetManager import com.navi.pay.db.NaviPayAppDatabase import com.navi.pay.db.NaviPayAppEncryptedDatabase +import com.navi.pay.utils.KEY_CUSTOMER_STATUS +import com.navi.pay.utils.KEY_DEVICE_FINGERPRINT import com.navi.pay.utils.KEY_UPI_LITE_ACTIVE_ACCOUNT_INFO import com.navi.pay.utils.LITMUS_EXPERIMENT_NAVIPAY_ONECLICK import com.navi.pay.utils.RUPEE_SYMBOL @@ -47,7 +53,6 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import org.json.JSONObject @Singleton @@ -87,6 +92,9 @@ constructor( } } + private val naviPayAnalytics: NaviPayAnalytics.NaviPayManager = + NaviPayAnalytics.INSTANCE.NaviPayManager() + private var _naviPaySetupStatus: NaviPaySetupStatus = NaviPaySetupStatus.NotSetup /** @@ -135,11 +143,25 @@ constructor( ) _naviPaySetupStatus = naviPaySetupStatus if (naviPaySetupStatus is NaviPaySetupStatus.Success) { - naviPayCustomerStatusHandler - .get() - .updateCustomerStatus( - customerStatus = naviPaySetupStatus.customerStatus + val oldMcId = deviceInfoProvider.get().getMerchantCustomerId() + if ( + isSameOrNewUPICustomer( + oldMerchantCustomerId = oldMcId, + newMerchantCustomerId = naviPaySetupStatus.merchantCustomerId ) + ) { + naviPayCustomerStatusHandler + .get() + .updateCustomerStatus( + customerStatus = naviPaySetupStatus.customerStatus + ) + } else { + naviPayAnalytics.onMerchantCustomerIdMismatch( + oldMcId = oldMcId, + newMcId = naviPaySetupStatus.merchantCustomerId + ) + triggerNaviPayHardLogout() + } } } else { _naviPaySetupStatus = @@ -178,8 +200,9 @@ constructor( } } - suspend fun triggerNaviPayLogout() = - withContext(Dispatchers.IO) { + /** Removing all upi data */ + fun triggerNaviPayHardLogout() { + CoroutineScope(Dispatchers.IO).launch { val naviPayLogoutTasks = mutableListOf>() naviPayLogoutTasks.add(async { naviPaySetupUseCase.get().clearNaviPayData() }) @@ -193,20 +216,45 @@ constructor( naviPayLogoutTasks.add(async { naviPayAppEncryptedDatabase.get().clearAllTables() }) naviPayLogoutTasks.awaitAll() - return@withContext - } - - /** App level logout triggered */ - fun logout() { - CoroutineScope(Dispatchers.IO).launch { - val logoutTasks = mutableListOf>() - logoutTasks.add(async { triggerNaviPayLogout() }) - logoutTasks.add(async { naviCacheRepository.get().clearOnLogout() }) - logoutTasks.awaitAll() } naviPayWidgetManager.get().removeScanAndPayLauncherWidget() } + /** App level logout triggered, removing naviCacheRepository and upi customer status */ + fun onAppLogout() { + CoroutineScope(Dispatchers.IO).launch { naviCacheRepository.get().clearOnLogout() } + if (isUpiSoftLogoutDisabled()) { + triggerNaviPayHardLogout() + } else { + triggerNaviPaySoftLogout() + } + } + + /** Removing upi customer status and fingerprint for soft logged out */ + fun triggerNaviPaySoftLogout() { + CoroutineScope(Dispatchers.IO).launch { + naviPaySetupUseCase + .get() + .clearNaviPayData( + encryptedDataKeys = listOf(KEY_DEVICE_FINGERPRINT), + nonEncryptedDataKeys = listOf(KEY_CUSTOMER_STATUS) + ) + } + naviPayWidgetManager.get().removeScanAndPayLauncherWidget() + } + + /** Removing upi data if customer logged-in with different number */ + fun onAppLogin(externalCustomerId: String?) { + if ( + isDifferentCustomerOrNewCustomer( + oldExternalCustomerId = BaseUtils.getPreviousLoggedInExternalCustomerId(), + newExternalCustomerId = externalCustomerId + ) + ) { + triggerNaviPayHardLogout() + } + } + fun isUserOnboarded(): Boolean { return naviPayCustomerStatusHandler.get().getCustomerStatusOnMainThread() == NaviPayCustomerStatus.LINKED_VPA diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/NaviPaySetupUseCase.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/NaviPaySetupUseCase.kt index 79d71b7808..dddae561c2 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/NaviPaySetupUseCase.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/NaviPaySetupUseCase.kt @@ -14,7 +14,6 @@ import com.navi.pay.common.model.view.SimInfo import com.navi.pay.common.model.view.isAnyEmpty import com.navi.pay.common.repository.CommonRepository import com.navi.pay.common.repository.SharedPreferenceRepository -import com.navi.pay.common.setup.model.NaviPayCustomerStatus import com.navi.pay.common.setup.model.NaviPaySetupFailureReason import com.navi.pay.common.setup.model.NaviPaySetupStatus import com.navi.pay.common.utils.DeviceInfoProvider @@ -138,14 +137,10 @@ constructor( value = it ) } - - if (customerResponse?.customerStatus == NaviPayCustomerStatus.LINKED_VPA.name) { - NaviPaySetupStatus.Success(customerStatus = NaviPayCustomerStatus.LINKED_VPA.name) - } else { - NaviPaySetupStatus.Success( - customerStatus = customerResponse?.customerStatus.orEmpty() - ) - } + NaviPaySetupStatus.Success( + customerStatus = customerResponse?.customerStatus.orEmpty(), + merchantCustomerId = customerResponse?.merchantCustomerId.orEmpty() + ) } } @@ -156,10 +151,13 @@ constructor( } } - suspend fun clearNaviPayData() { + suspend fun clearNaviPayData( + encryptedDataKeys: List = NAVI_PAY_ENCRYPT_SHARED_PREF_DATA_KEYS, + nonEncryptedDataKeys: List = NAVI_PAY_NON_ENCRYPT_SHARED_PREF_DATA_KEYS + ) { sharedPreferenceRepository.clearKeyBasedSessionPreferenceData( - encryptedDataKeys = NAVI_PAY_ENCRYPT_SHARED_PREF_DATA_KEYS, - nonEncryptedDataKeys = NAVI_PAY_NON_ENCRYPT_SHARED_PREF_DATA_KEYS + encryptedDataKeys = encryptedDataKeys, + nonEncryptedDataKeys = nonEncryptedDataKeys ) } } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/model/NaviPaySetupStatus.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/model/NaviPaySetupStatus.kt index d5ae5c650d..e87abce3b0 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/model/NaviPaySetupStatus.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/common/setup/model/NaviPaySetupStatus.kt @@ -13,7 +13,8 @@ import com.navi.common.network.models.GenericErrorResponse sealed class NaviPaySetupStatus { data object NotSetup : NaviPaySetupStatus() - data class Success(val customerStatus: String) : NaviPaySetupStatus() + data class Success(val customerStatus: String, val merchantCustomerId: String) : + NaviPaySetupStatus() data class Failure(val failureReason: NaviPaySetupFailureReason) : NaviPaySetupStatus() } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/common/utils/NaviPayCommonUtils.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/common/utils/NaviPayCommonUtils.kt index a6c2cd815d..a78b0a0b41 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/common/utils/NaviPayCommonUtils.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/common/utils/NaviPayCommonUtils.kt @@ -43,6 +43,7 @@ import com.navi.base.utils.isNotNullAndNotEmpty import com.navi.base.utils.orTrue import com.navi.common.R as CommonR import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper +import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.IS_UPI_SOFT_LOGGED_OUT_DISABLED import com.navi.common.upi.CANCEL import com.navi.common.utils.CommonRootDeviceUtil import com.navi.common.utils.CommonUtils.capitalizeMeridiem @@ -63,7 +64,9 @@ import com.navi.pay.utils.DATE_TIME_FORMAT_HOUR_MINUTE import com.navi.pay.utils.DOT_IFSC_DOT_NPCI import com.navi.pay.utils.INTENT_ACTION_SMS_DELIVERED import com.navi.pay.utils.INTENT_ACTION_SMS_SENT +import com.navi.pay.utils.KEY_DEVICE_FINGERPRINT import com.navi.pay.utils.LITMUS_EXPERIMENT_NAVIPAY_ONECLICK +import com.navi.pay.utils.NAVI_PAY_ENCRYPT_SHARED_PREF_DATA_KEYS import com.navi.pay.utils.NAVI_PAY_TRANSACTION_HISTORY_TAG_SEPARATOR import com.navi.pay.utils.ONE_HOUR_IN_MILLIS import com.navi.pay.utils.ONE_MINUTE_IN_MILLIS @@ -532,6 +535,22 @@ object NaviPayCommonUtils { } } +fun isSameOrNewUPICustomer( + oldMerchantCustomerId: String?, + newMerchantCustomerId: String?, +): Boolean { + if (oldMerchantCustomerId.isNullOrEmpty()) return true + return oldMerchantCustomerId == newMerchantCustomerId +} + +fun isDifferentCustomerOrNewCustomer( + oldExternalCustomerId: String?, + newExternalCustomerId: String? +): Boolean { + if (oldExternalCustomerId.isNullOrEmpty() || newExternalCustomerId.isNullOrEmpty()) return true + return oldExternalCustomerId != newExternalCustomerId +} + val rewardsLinearGradientBrush = Brush.linearGradient( colors = @@ -542,6 +561,12 @@ val rewardsLinearGradientBrush = ) ) +fun getExcludeSecureSharedPrefKeys(): List { + val excludeSharedPrefKeys = NAVI_PAY_ENCRYPT_SHARED_PREF_DATA_KEYS.toMutableList() + excludeSharedPrefKeys.remove(KEY_DEVICE_FINGERPRINT) + return excludeSharedPrefKeys +} + fun getOneClickExperimentPayload(): OneClickExperimentPayload? { val payload = PreferenceManager.getStringPreference(key = LITMUS_EXPERIMENT_NAVIPAY_ONECLICK) if (payload.isNullOrEmpty()) { @@ -555,3 +580,6 @@ fun getOneClickExperimentPayload(): OneClickExperimentPayload? { null } } + +fun isUpiSoftLogoutDisabled() = + FirebaseRemoteConfigHelper.getBoolean(IS_UPI_SOFT_LOGGED_OUT_DISABLED) diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/binding/viewmodel/NaviPayOnboardingViewModel.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/binding/viewmodel/NaviPayOnboardingViewModel.kt index 6fa6959125..c2671ee7b1 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/binding/viewmodel/NaviPayOnboardingViewModel.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/binding/viewmodel/NaviPayOnboardingViewModel.kt @@ -822,7 +822,9 @@ constructor( private suspend fun isLocalDeviceDataAvailable(): Boolean { val deviceData = deviceInfoProvider.getDeviceData() - return !deviceData.isAnyEmpty() && !deviceData.provider.isAnyEmpty() + return !deviceData.isAnyEmpty() && + !deviceData.provider.isAnyEmpty() && + deviceData.deviceFingerPrint.isNotBlank() } private fun isCurrentAppVersionLowerThanMinimumAllowedVersionForOnboarding(): Boolean { diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/faq/viewmodel/NaviPayFaqViewModel.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/faq/viewmodel/NaviPayFaqViewModel.kt index a541cefa44..d63a7866a6 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/faq/viewmodel/NaviPayFaqViewModel.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/faq/viewmodel/NaviPayFaqViewModel.kt @@ -228,7 +228,7 @@ constructor( deRegisterAPIResponse.data?.status == NAVI_PAY_API_STATUS_SUCCESS if (isDeRegisterSuccess) { naviPayAnalytics.onDeregisterSuccess() - naviPayManager.get().triggerNaviPayLogout() + naviPayManager.get().triggerNaviPayHardLogout() _uiState.value = FaqScreenUiState.DeRegisteringSuccess } else { naviPayAnalytics.onDeregisterFailure(deRegisterAPIResponse.errors?.firstOrNull()) diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/utils/GenericErrorCtaHandler.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/utils/GenericErrorCtaHandler.kt index ca36c07da2..e4a03ef9e3 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/utils/GenericErrorCtaHandler.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/utils/GenericErrorCtaHandler.kt @@ -66,7 +66,7 @@ class GenericErrorCtaHandler @Inject constructor(private val naviPayManager: Nav } ACTION_URL_PIN_REREGISTER -> { CoroutineScope(Dispatchers.IO).launch { - naviPayManager.triggerNaviPayLogout() + naviPayManager.triggerNaviPayHardLogout() withContext(Dispatchers.Main) { destinationsNavigator?.clearBackStackUpToAndNavigate( destination = NaviPayLauncherScreenDestination, diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt index 44065b06d6..1a95697397 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt @@ -114,7 +114,8 @@ val NAVI_PAY_NON_ENCRYPT_SHARED_PREF_DATA_KEYS = KEY_MORE_OPTIONS_SAVING_ACCOUNT_COUNT, KEY_UPI_LITE_ACTIVE, KEY_UPI_LITE_ACTIVE_ACCOUNT_INFO, - KEY_UPI_LITE_NON_ACTIVE_ACCOUNT_PRESENT + KEY_UPI_LITE_NON_ACTIVE_ACCOUNT_PRESENT, + KEY_CUSTOMER_STATUS ) // Shared Preference constants ends here