diff --git a/app/build.gradle b/app/build.gradle index 8013c15dcd..518ac5e0d1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -141,7 +141,7 @@ android { buildConfigField 'String', 'SSL_PINNING_KEY', formatString('sha256/nUU7NjGrGo/mxijjsX+MHerUbpIHBidF8LAYOEPFWA8=') buildConfigField 'String', 'ALFRED_API_KEY', formatString('oMv77fgpBg9NFGom0Psizbf7lbrdBVJz') manifestPlaceholders = [ - TRUECALLER_KEY : "6E6TX0cd28bada2b14cf28534dfce68c6a245", + TRUECALLER_KEY : "yicxl1xh6jidagslpi0h9d-uklfeinnx4a6mb6rdgyi", FACEBOOK_APP_ID: "0" ] } @@ -159,7 +159,7 @@ android { buildConfigField 'String', 'SSL_PINNING_KEY', formatString('sha256/nUU7NjGrGo/mxijjsX+MHerUbpIHBidF8LAYOEPFWA8=') buildConfigField 'String', 'ALFRED_API_KEY', formatString('oMv77fgpBg9NFGom0Psizbf7lbrdBVJz') manifestPlaceholders = [ - TRUECALLER_KEY : "6E6TX0cd28bada2b14cf28534dfce68c6a245", + TRUECALLER_KEY : "yicxl1xh6jidagslpi0h9d-uklfeinnx4a6mb6rdgyi", FACEBOOK_APP_ID: "0" ] } @@ -177,7 +177,7 @@ android { buildConfigField 'String', 'SSL_PINNING_KEY', formatString('sha256/4sMl7dWjcM6O5RKWBw3DUpd5Qy5OX5pvcHMKQIF1bgM=') buildConfigField 'String', 'ALFRED_API_KEY', formatString('oMv77fgpBg9NFGom0Psizbf7lbrdBVJz') manifestPlaceholders = [ - TRUECALLER_KEY : "aBkmX155b2ed283a44b008d62e8975388a4d5", + TRUECALLER_KEY : "yicxl1xh6jidagslpi0h9d-uklfeinnx4a6mb6rdgyi", FACEBOOK_APP_ID: "0" ] } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 767add88ce..2b0a12cefd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -33,6 +33,8 @@ + + = Build.VERSION_CODES.N && isTrueCallerEnabled && - redirectStatus !in listOf(AUTH_VIA_LINK, WhatsAppLoginFragment.TAG) + redirectStatus !in listOf(AUTH_VIA_LINK, WhatsAppLoginFragment.TAG) ) { - randomRequestId = getUniqueRandomNumber() - FcmAnalyticsUtil.analytics.setCrashlyticRandomRequestId(randomRequestId) - TrueCallerHelper.init(this, this, randomRequestId) + stateRequested = getUniqueRandomNumber() + codeVerifier = CodeVerifierUtil.generateRandomCodeVerifier() + FcmAnalyticsUtil.analytics.setCrashlyticRandomRequestId(stateRequested) + TrueCallerFacade.init(this, this, stateRequested, codeVerifier) } initListener() initError(registrationVM) @@ -290,6 +292,16 @@ class RegistrationActivity : private fun initObservers() { registrationVM.registrationResponse.observeNonNull(this) { + analyticsTracker.truecallerNameDetails( + firstName = it.firstName, + lastName = it.lastName + ) + it.phoneNumber?.let { + phoneNumber -> BaseUtils.savePhoneNumber(phoneNumber) + analyticsTracker.loginWithTrueCaller( + number = phoneNumber, + source = source) + } onSessionTokenReceived(it, LoginType.TRUE_CALLER) } registrationVM.trueCallerFailureResponse.observeNonNull(this) { trueCallerLoginFailed -> @@ -416,55 +428,16 @@ class RegistrationActivity : registerReceiver(otpReceiver, intentFilter) } - override fun onFailureProfileShared(error: TrueError) { - if (error.errorType == TrueError.ERROR_TYPE_CONTINUE_WITH_DIFFERENT_NUMBER) { + override fun onFailure(error: TcOAuthError) { + if (error.errorCode == TcOAuthError.UserDeniedByPressingFooterError.errorCode) { analyticsTracker.onTrueCallerWithDiffNumber(source) } else { - analyticsTracker.onTrueCallerLoginError(error.errorType.orZero().toString(), source) + analyticsTracker.onTrueCallerLoginError(error.errorCode.orZero().toString(), source) } registrationSharedVM.setLoginViaMobile(true) } - override fun onSuccessProfileShared(profile: TrueProfile) { - val data = - TrueProfileData( - statusCode = API_SUCCESS_CODE, - status = SUCCESS, - accessToken = profile.accessToken, - avatarUrl = profile.avatarUrl, - city = profile.city, - companyName = profile.companyName, - countryCode = profile.countryCode, - email = profile.email, - facebookId = profile.facebookId, - firstName = profile.firstName, - gender = profile.gender, - isAmbassador = profile.isAmbassador, - isBusiness = profile.isBusiness, - isSimChanged = profile.isSimChanged, - isTrueName = profile.isTrueName, - jobTitle = profile.jobTitle, - lastName = profile.lastName, - payload = profile.payload, - phoneNumber = profile.phoneNumber, - requestNonce = profile.requestNonce, - signature = profile.signature, - signatureAlgorithm = profile.signatureAlgorithm, - street = profile.street, - twitterId = profile.twitterId, - url = profile.url, - verificationMode = profile.verificationMode, - verificationTimestamp = profile.verificationTimestamp, - zipCode = profile.zipcode, - userLocale = profile.userLocale?.language - ) - analyticsTracker.truecallerNameDetails( - firstName = profile.firstName, - lastName = profile.lastName - ) - val phone = removeCodeFromPhoneNumber(profile.phoneNumber.orEmpty()) - BaseUtils.savePhoneNumber(phone) - analyticsTracker.loginWithTrueCaller(phone, source) + override fun onSuccess(tcOAuthData: TcOAuthData) { showLoader() val gaId = PreferenceManager.getStringPreference(GOOGLE_ADVERTISING_ID) val fcmToken = PreferenceManager.getStringPreference(FCM_TOKEN) @@ -516,11 +489,16 @@ class RegistrationActivity : miPushToken = getMiPushClientRegId(applicationContext), isInstalledOnProfiles = isInstalledInProfile(applicationContext), localStorageLocation = getLocalStorageLocation(applicationContext), - sourceSignature = getDeviceSignature(applicationContext), + sourceSignature = getDeviceSignature(applicationContext) + ) + val trueCallerAuthData = + TruecallerAuthData( + authorizationCode = tcOAuthData.authorizationCode, + codeVerifier = codeVerifier ) val otpRequest = OtpRequest( - truecallerProfileData = data, + truecallerAuthData = trueCallerAuthData, loginType = LoginType.TRUE_CALLER.name, source = source, deviceDetail = deviceDetail, @@ -549,16 +527,23 @@ class RegistrationActivity : return if (parameters.size > 0) parameters else null } - override fun onVerificationRequired(error: TrueError?) { + override fun onVerificationRequired(error: TcOAuthError?) { // will only be called whenTruecallerSdkScope#SDK_OPTION_WITH_OTP is selected } override fun onFragmentOpen(type: String?) { - if (!TrueCallerHelper.isInit()) { - TrueCallerHelper.init(this, this) + if(getOsVersion() <= Build.VERSION_CODES.M) { + registrationSharedVM.setLoginViaMobile(true) + return } - if (TruecallerSDK.getInstance().isUsable) { - TruecallerSDK.getInstance().getUserProfile(this) + if (!TrueCallerFacade.isInit()) { + stateRequested = getUniqueRandomNumber() + codeVerifier = CodeVerifierUtil.generateRandomCodeVerifier() + FcmAnalyticsUtil.analytics.setCrashlyticRandomRequestId(stateRequested) + TrueCallerFacade.init(this, this, stateRequested, codeVerifier) + } + if (TcSdk.getInstance().isOAuthFlowUsable) { + TcSdk.getInstance().getAuthorizationCode(this) analyticsTracker.onTrueCallerBottomSheetOpen() } else { registrationSharedVM.setLoginViaMobile(true) @@ -567,10 +552,9 @@ class RegistrationActivity : override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (requestCode == TruecallerSDK.SHARE_PROFILE_REQUEST_CODE) { - if (TrueCallerHelper.isUsable()) { - TruecallerSDK.getInstance() - .onActivityResultObtained(this, requestCode, resultCode, data) + if (requestCode == TcSdk.SHARE_PROFILE_REQUEST_CODE) { + if (TrueCallerFacade.isUsable()) { + TcSdk.getInstance().onActivityResultObtained(this, requestCode, resultCode, data) } else { analyticsTracker.onTrueCallerInitError() } @@ -592,7 +576,7 @@ class RegistrationActivity : override fun onDestroy() { super.onDestroy() - if (isTrueCallerEnabled) TrueCallerHelper.clear() + if (isTrueCallerEnabled) TrueCallerFacade.clear() } override val screenName diff --git a/app/src/main/java/com/naviapp/registration/helper/TrueCallerFacade.kt b/app/src/main/java/com/naviapp/registration/helper/TrueCallerFacade.kt new file mode 100644 index 0000000000..a018529095 --- /dev/null +++ b/app/src/main/java/com/naviapp/registration/helper/TrueCallerFacade.kt @@ -0,0 +1,75 @@ +/* + * + * * Copyright © 2021-2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.naviapp.registration.helper + +import com.navi.design.R as DesignR +import android.content.Context +import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.navi.base.utils.orFalse +import com.navi.common.utils.log +import com.naviapp.R +import com.truecaller.android.sdk.oAuth.CodeVerifierUtil +import com.truecaller.android.sdk.oAuth.TcOAuthCallback +import com.truecaller.android.sdk.oAuth.TcSdk +import com.truecaller.android.sdk.oAuth.TcSdkOptions + + +object TrueCallerFacade { + + private var isInit: Boolean? = null + + fun init(context: Context, tcCallBack: TcOAuthCallback, stateRequested: String? = null, codeVerifier: String? = null) { + initImpl(context, tcCallBack, stateRequested, codeVerifier) + } + + private fun initImpl(context: Context, tcCallBack: TcOAuthCallback, stateRequested: String? = null, codeVerifier: String? = null){ + try { + val tcSdkOptions = TcSdkOptions.Builder(context, tcCallBack) + .buttonShapeOptions(TcSdkOptions.BUTTON_SHAPE_RECTANGLE) + .footerType(TcSdkOptions.FOOTER_TYPE_ANOTHER_MOBILE_NO) + .sdkOptions(TcSdkOptions.OPTION_VERIFY_ONLY_TC_USERS) + .ctaText(TcSdkOptions.CTA_TEXT_CONTINUE) + .buttonColor(context.resources.getColor(DesignR.color.color_1F002A)) + .buttonTextColor(context.resources.getColor(R.color.white)) + .loginTextPrefix(TcSdkOptions.LOGIN_TEXT_PREFIX_TO_CONTINUE) + .consentHeadingOption(TcSdkOptions.SDK_CONSENT_HEADING_LOG_IN_TO) + .build() + TcSdk.init(tcSdkOptions) + if (TcSdk.getInstance().isOAuthFlowUsable) { + stateRequested?.apply { TcSdk.getInstance().setOAuthState(this) } + TcSdk.getInstance().setOAuthScopes(arrayOf("profile", "phone", "openid", "offline_access")) + val codeChallenge = codeVerifier?.let { CodeVerifierUtil.getCodeChallenge(it) } + codeChallenge?.apply { TcSdk.getInstance().setCodeChallenge(this) } + } + isInit = true + } catch (e: Exception) { + isInit = null + e.log() + } + } + + fun isInit(): Boolean { + return isInit.orFalse() + } + + /** + * isUsable be true/false for SDK_OPTION_WITHOUT_OTP but always true for SDK_OPTION_WITH_OTP + */ + fun isUsable(): Boolean { + return isInit() && TcSdk.getInstance().isOAuthFlowUsable + } + + fun clear() { + try { + isInit = null + TcSdk.clear() + } catch (e: Exception) { + e.log() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/naviapp/registration/helper/TrueCallerHelper.kt b/app/src/main/java/com/naviapp/registration/helper/TrueCallerHelper.kt deleted file mode 100644 index 84a4197a52..0000000000 --- a/app/src/main/java/com/naviapp/registration/helper/TrueCallerHelper.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * * Copyright © 2021-2023 by Navi Technologies Limited - * * All rights reserved. Strictly confidential - * - */ - -package com.naviapp.registration.helper - -import com.navi.design.R as DesignR -import android.content.Context -import com.navi.base.utils.orFalse -import com.navi.common.utils.log -import com.naviapp.R -import com.truecaller.android.sdk.ITrueCallback -import com.truecaller.android.sdk.TruecallerSDK -import com.truecaller.android.sdk.TruecallerSdkScope - - -object TrueCallerHelper { - - private var isInit: Boolean? = null - - fun init(context: Context, tcCallBack: ITrueCallback, requestId: String? = null) { - initImpl(context, tcCallBack, requestId) - } - - private fun initImpl(context: Context, tcCallBack: ITrueCallback, requestId: String? = null) { - try { - val trueScope = TruecallerSdkScope.Builder(context, tcCallBack) - .consentMode(TruecallerSdkScope.CONSENT_MODE_BOTTOMSHEET) - .buttonColor(context.resources.getColor(DesignR.color.color_1F002A)) - .buttonTextColor(context.resources.getColor(R.color.white)) - // .privacyPolicyUrl("https://navi-tnc-privacy-policy-resources.s3.ap-south-1.amazonaws.com/privacy_policy/index.html") - //.termsOfServiceUrl("https://navi-tnc-privacy-policy-resources.s3.ap-south-1.amazonaws.com/privacy_policy/index.html") - .buttonShapeOptions(TruecallerSdkScope.BUTTON_SHAPE_RECTANGLE) - .footerType(TruecallerSdkScope.FOOTER_TYPE_CONTINUE) - .consentTitleOption(TruecallerSdkScope.SDK_CONSENT_TITLE_LOG_IN) - .sdkOptions(TruecallerSdkScope.SDK_OPTION_WITHOUT_OTP) // isUsable can be true/false with SDK_OPTION_WITHOUT_OTP but only true for SDK_OPTION_WITH_OTP - .build() - - TruecallerSDK.init(trueScope) - if (TruecallerSDK.getInstance().isUsable) { - requestId?.apply { TruecallerSDK.getInstance().setRequestNonce(this) } - } - isInit = true - } catch (e: Exception) { - isInit = null - e.log() - } - } - - fun isInit(): Boolean { - return isInit.orFalse() - } - - /** - * isUsable be true/false for SDK_OPTION_WITHOUT_OTP but always true for SDK_OPTION_WITH_OTP - */ - fun isUsable(): Boolean { - return isInit() && TruecallerSDK.getInstance().isUsable - } - - fun clear() { - try { - isInit = null - TruecallerSDK.clear() - } catch (e: Exception) { - - } - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b4828c2cd6..063cd09f35 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -106,7 +106,7 @@ retrofit = "2.9.0" room = "2.5.2" shawnLin-numberPicker = "2.4.13" spotless = "6.23.3" -truecaller = "2.7.0" +truecaller = "3.0.0" visit = "1.24" wasabeef-recyclerviewAnimators = "4.0.1" zetetic-androidDatabaseSqlcipher = "4.5.4" diff --git a/navi-insurance/src/main/AndroidManifest.xml b/navi-insurance/src/main/AndroidManifest.xml index 4b941c9e84..dab9487ed7 100644 --- a/navi-insurance/src/main/AndroidManifest.xml +++ b/navi-insurance/src/main/AndroidManifest.xml @@ -10,8 +10,6 @@ - -