From 7fc4f263a6198ff047c95b5292003ac7ad4c5070 Mon Sep 17 00:00:00 2001 From: Tim Chow Date: Tue, 10 Dec 2024 14:35:00 -0600 Subject: [PATCH] Venmo - Add deep link fallback (#1237) --- CHANGELOG.md | 1 + Demo/src/main/AndroidManifest.xml | 1 + .../braintreepayments/demo/VenmoFragment.java | 34 ++-- .../api/venmo/VenmoClient.kt | 75 ++++++--- .../api/venmo/VenmoClientUnitTest.java | 154 +++++++++++++----- 5 files changed, 183 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e8db3f936..0834c20a10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Add `ThreeDSecureRequest.requestorAppUrl` * Venmo * Add `VenmoClient` constructor with `appLinkReturnUri` argument to use App Links when redirecting back from the Venmo flow + * Add `deepLinkFallbackUrlScheme` to `VenmoClient` constructor params for supporting deep link fallback * Deprecate `VenmoClient` constructor with `returnUrlScheme` argument ## 5.2.0 (2024-10-30) diff --git a/Demo/src/main/AndroidManifest.xml b/Demo/src/main/AndroidManifest.xml index 101229fb26..c09b65871d 100644 --- a/Demo/src/main/AndroidManifest.xml +++ b/Demo/src/main/AndroidManifest.xml @@ -37,6 +37,7 @@ + diff --git a/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java b/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java index 4e89b9c5dc..22684c9ce4 100644 --- a/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java +++ b/Demo/src/main/java/com/braintreepayments/demo/VenmoFragment.java @@ -14,6 +14,7 @@ import androidx.navigation.NavDirections; import androidx.navigation.fragment.NavHostFragment; +import com.braintreepayments.api.core.UserCanceledException; import com.braintreepayments.api.venmo.VenmoAccountNonce; import com.braintreepayments.api.venmo.VenmoClient; import com.braintreepayments.api.venmo.VenmoLauncher; @@ -25,7 +26,6 @@ import com.braintreepayments.api.venmo.VenmoPendingRequest; import com.braintreepayments.api.venmo.VenmoRequest; import com.braintreepayments.api.venmo.VenmoResult; -import com.braintreepayments.api.core.UserCanceledException; import java.util.ArrayList; @@ -42,6 +42,18 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c venmoButton = view.findViewById(R.id.venmo_button); venmoButton.setOnClickListener(this::launchVenmo); + if (venmoClient == null) { + if (Settings.useAppLinkReturn(requireContext())) { + venmoClient = new VenmoClient( + requireContext(), + super.getAuthStringArg(), + Uri.parse("https://mobile-sdk-demo-site-838cead5d3ab.herokuapp.com/braintree-payments"), + "com.braintreepayments.demo.braintree" + ); + } else { + venmoClient = new VenmoClient(requireContext(), super.getAuthStringArg()); + } + } venmoLauncher = new VenmoLauncher(); return view; @@ -71,11 +83,11 @@ private void handleVenmoResult(VenmoResult result) { handleError(new UserCanceledException("User canceled Venmo")); } } + private void handleVenmoAccountNonce(VenmoAccountNonce venmoAccountNonce) { super.onPaymentMethodNonceCreated(venmoAccountNonce); - NavDirections action = - VenmoFragmentDirections.actionVenmoFragmentToDisplayNonceFragment(venmoAccountNonce); + NavDirections action = VenmoFragmentDirections.actionVenmoFragmentToDisplayNonceFragment(venmoAccountNonce); NavHostFragment.findNavController(this).navigate(action); } @@ -83,23 +95,12 @@ public void launchVenmo(View v) { FragmentActivity activity = getActivity(); getActivity().setProgressBarIndeterminateVisibility(true); - if (venmoClient == null) { - if (Settings.useAppLinkReturn(activity)) { - venmoClient = new VenmoClient( - requireContext(), - super.getAuthStringArg(), - Uri.parse("https://mobile-sdk-demo-site-838cead5d3ab.herokuapp.com/braintree-payments") - ); - } else { - venmoClient = new VenmoClient(requireContext(), super.getAuthStringArg()); - } - } boolean shouldVault = - Settings.vaultVenmo(activity) && !TextUtils.isEmpty(Settings.getCustomerId(activity)); + Settings.vaultVenmo(activity) && !TextUtils.isEmpty(Settings.getCustomerId(activity)); VenmoPaymentMethodUsage venmoPaymentMethodUsage = shouldVault ? - VenmoPaymentMethodUsage.MULTI_USE : VenmoPaymentMethodUsage.SINGLE_USE; + VenmoPaymentMethodUsage.MULTI_USE : VenmoPaymentMethodUsage.SINGLE_USE; VenmoRequest venmoRequest = new VenmoRequest(venmoPaymentMethodUsage); venmoRequest.setProfileId(null); venmoRequest.setShouldVault(shouldVault); @@ -139,6 +140,7 @@ private void completeVenmoFlow(VenmoPaymentAuthResult.Success paymentAuthResult) private void storePendingRequest(VenmoPendingRequest.Started request) { PendingRequestStore.getInstance().putVenmoPendingRequest(requireContext(), request); } + private VenmoPendingRequest.Started getPendingRequest() { return PendingRequestStore.getInstance().getVenmoPendingRequest(requireContext()); } diff --git a/Venmo/src/main/java/com/braintreepayments/api/venmo/VenmoClient.kt b/Venmo/src/main/java/com/braintreepayments/api/venmo/VenmoClient.kt index e4639e1988..efaef70666 100644 --- a/Venmo/src/main/java/com/braintreepayments/api/venmo/VenmoClient.kt +++ b/Venmo/src/main/java/com/braintreepayments/api/venmo/VenmoClient.kt @@ -16,6 +16,7 @@ import com.braintreepayments.api.core.BraintreeException import com.braintreepayments.api.core.BraintreeRequestCodes import com.braintreepayments.api.core.ClientToken import com.braintreepayments.api.core.Configuration +import com.braintreepayments.api.core.GetReturnLinkUseCase import com.braintreepayments.api.core.MerchantRepository import com.braintreepayments.api.core.MetadataBuilder import org.json.JSONException @@ -32,7 +33,8 @@ class VenmoClient internal constructor( private val sharedPrefsWriter: VenmoSharedPrefsWriter = VenmoSharedPrefsWriter(), private val analyticsParamRepository: AnalyticsParamRepository = AnalyticsParamRepository.instance, private val merchantRepository: MerchantRepository = MerchantRepository.instance, - private val venmoRepository: VenmoRepository = VenmoRepository.instance + private val venmoRepository: VenmoRepository = VenmoRepository.instance, + private val getReturnLinkUseCase: GetReturnLinkUseCase = GetReturnLinkUseCase(merchantRepository) ) { /** * Used for linking events from the client to server side request @@ -52,12 +54,24 @@ class VenmoClient internal constructor( * @param authorization a Tokenization Key or Client Token used to authenticate * @param appLinkReturnUrl A [Uri] containing the Android App Link website associated with * your application to be used to return to your app from the PayPal + * @param deepLinkFallbackUrlScheme A return url scheme that will be used as a deep link fallback when returning to + * your app via App Link is not available (buyer unchecks the "Open supported links" setting). */ + @JvmOverloads constructor( context: Context, authorization: String, appLinkReturnUrl: Uri, - ) : this(BraintreeClient(context, authorization, null, appLinkReturnUrl)) + deepLinkFallbackUrlScheme: String? = null + ) : this( + BraintreeClient( + context = context, + authorization = authorization, + returnUrlScheme = null, + appLinkReturnUri = appLinkReturnUrl, + deepLinkFallbackUrlScheme = deepLinkFallbackUrlScheme + ) + ) /** * Initializes a new [VenmoClient] instance @@ -67,7 +81,8 @@ class VenmoClient internal constructor( * @param returnUrlScheme a custom return url to use for browser and app switching */ @Deprecated("Use the constructor that uses an `appLinkReturnUrl` to redirect back to your application instead.") - @JvmOverloads constructor( + @JvmOverloads + constructor( context: Context, authorization: String, returnUrlScheme: String? = null @@ -82,6 +97,7 @@ class VenmoClient internal constructor( * @param request [VenmoRequest] * @param callback [VenmoPaymentAuthRequestCallback] */ + @Suppress("LongMethod", "CyclomaticComplexMethod", "TooGenericExceptionCaught") fun createPaymentAuthRequest( context: Context, request: VenmoRequest, @@ -138,8 +154,14 @@ class VenmoClient internal constructor( merchantRepository.authorization, finalVenmoProfileId, paymentContextId, callback ) - } catch (e: JSONException) { - callbackPaymentAuthFailure(callback, VenmoPaymentAuthRequest.Failure(e)) + } catch (e: Exception) { + when (e) { + is JSONException, is BraintreeException -> { + callbackPaymentAuthFailure(callback, VenmoPaymentAuthRequest.Failure(e)) + } + + else -> throw e + } } } else { callbackPaymentAuthFailure(callback, VenmoPaymentAuthRequest.Failure(exception)) @@ -171,22 +193,27 @@ class VenmoClient internal constructor( val braintreeData = JSONObject() .put("_meta", metadata) - val applicationName = - context.packageManager.getApplicationLabel(context.applicationInfo) - .toString() + val applicationName = context.packageManager.getApplicationLabel(context.applicationInfo).toString() - val merchantBaseUri = merchantRepository.appLinkReturnUri - ?: Uri.parse("${braintreeClient.getReturnUrlScheme()}://x-callback-url/vzero/auth/venmo") + val returnLinkResult = getReturnLinkUseCase() + val merchantBaseUrl: String = when (returnLinkResult) { + is GetReturnLinkUseCase.ReturnLinkResult.AppLink -> returnLinkResult.appLinkReturnUri.toString() + is GetReturnLinkUseCase.ReturnLinkResult.DeepLink -> { + "${returnLinkResult.deepLinkFallbackUrlScheme}://x-callback-url/vzero/auth/venmo" + } - val successUri = merchantBaseUri.buildUpon().appendPath("success").build() - val cancelUri = merchantBaseUri.buildUpon().appendPath("cancel").build() - val errorUri = merchantBaseUri.buildUpon().appendPath("error").build() + is GetReturnLinkUseCase.ReturnLinkResult.Failure -> throw returnLinkResult.exception + } + + val successUri = "$merchantBaseUrl/success" + val cancelUri = "$merchantBaseUrl/cancel" + val errorUri = "$merchantBaseUrl/error" val venmoBaseURL = Uri.parse("https://venmo.com/go/checkout") .buildUpon() - .appendQueryParameter("x-success", successUri.toString()) - .appendQueryParameter("x-error", errorUri.toString()) - .appendQueryParameter("x-cancel", cancelUri.toString()) + .appendQueryParameter("x-success", successUri) + .appendQueryParameter("x-error", errorUri) + .appendQueryParameter("x-cancel", cancelUri) .appendQueryParameter("x-source", applicationName) .appendQueryParameter("braintree_merchant_id", venmoProfileId) .appendQueryParameter("braintree_access_token", configuration?.venmoAccessToken) @@ -204,11 +231,17 @@ class VenmoClient internal constructor( val browserSwitchOptions = BrowserSwitchOptions() .requestCode(BraintreeRequestCodes.VENMO.code) .url(venmoBaseURL) - .appLinkUri(merchantRepository.appLinkReturnUri) - .returnUrlScheme(braintreeClient.getReturnUrlScheme()) - val params = VenmoPaymentAuthRequestParams( - browserSwitchOptions - ) + .apply { + when (returnLinkResult) { + is GetReturnLinkUseCase.ReturnLinkResult.AppLink -> appLinkUri(returnLinkResult.appLinkReturnUri) + is GetReturnLinkUseCase.ReturnLinkResult.DeepLink -> { + returnUrlScheme(returnLinkResult.deepLinkFallbackUrlScheme) + } + + is GetReturnLinkUseCase.ReturnLinkResult.Failure -> throw returnLinkResult.exception + } + } + val params = VenmoPaymentAuthRequestParams(browserSwitchOptions) callback.onVenmoPaymentAuthRequest(VenmoPaymentAuthRequest.ReadyToLaunch(params)) } diff --git a/Venmo/src/test/java/com/braintreepayments/api/venmo/VenmoClientUnitTest.java b/Venmo/src/test/java/com/braintreepayments/api/venmo/VenmoClientUnitTest.java index 70953cb4d5..b0d0925f73 100644 --- a/Venmo/src/test/java/com/braintreepayments/api/venmo/VenmoClientUnitTest.java +++ b/Venmo/src/test/java/com/braintreepayments/api/venmo/VenmoClientUnitTest.java @@ -21,15 +21,16 @@ import com.braintreepayments.api.core.AnalyticsEventParams; import com.braintreepayments.api.core.AnalyticsParamRepository; import com.braintreepayments.api.core.ApiClient; -import com.braintreepayments.api.core.IntegrationType; -import com.braintreepayments.api.core.MerchantRepository; -import com.braintreepayments.api.testutils.Fixtures; -import com.braintreepayments.api.testutils.MockBraintreeClientBuilder; import com.braintreepayments.api.core.Authorization; import com.braintreepayments.api.core.BraintreeClient; import com.braintreepayments.api.core.BraintreeException; import com.braintreepayments.api.core.BraintreeRequestCodes; import com.braintreepayments.api.core.Configuration; +import com.braintreepayments.api.core.GetReturnLinkUseCase; +import com.braintreepayments.api.core.IntegrationType; +import com.braintreepayments.api.core.MerchantRepository; +import com.braintreepayments.api.testutils.Fixtures; +import com.braintreepayments.api.testutils.MockBraintreeClientBuilder; import org.json.JSONException; import org.json.JSONObject; @@ -91,6 +92,7 @@ public class VenmoClientUnitTest { private final MerchantRepository merchantRepository = mock(MerchantRepository.class); private final VenmoRepository venmoRepository = mock(VenmoRepository.class); + private final GetReturnLinkUseCase getReturnLinkUseCase = mock(GetReturnLinkUseCase.class); @Before public void beforeEach() throws JSONException { @@ -116,6 +118,7 @@ public void beforeEach() throws JSONException { when(merchantRepository.getIntegrationType()).thenReturn(IntegrationType.CUSTOM); when(merchantRepository.getApplicationContext()).thenReturn(context); when(venmoRepository.getVenmoUrl()).thenReturn(appSwitchUrl); + when(getReturnLinkUseCase.invoke()).thenReturn(new GetReturnLinkUseCase.ReturnLinkResult.AppLink(appSwitchUrl)); } @Test @@ -144,7 +147,8 @@ public void createPaymentAuthRequest_whenCreatePaymentContextFails_collectAddres sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -158,13 +162,14 @@ public void createPaymentAuthRequest_whenCreatePaymentContextFails_collectAddres } @Test - public void createPaymentAuthRequest_whenCreatePaymentContextSucceeds_createsVenmoAuthChallenge() { + public void createPaymentAuthRequest_withDeepLink_whenCreatePaymentContextSucceeds_createsVenmoAuthChallenge() { BraintreeClient braintreeClient = new MockBraintreeClientBuilder() .configuration(venmoEnabledConfiguration) .returnUrlScheme("com.example") .build(); when(merchantRepository.getAuthorization()).thenReturn(clientToken); + when(getReturnLinkUseCase.invoke()).thenReturn(new GetReturnLinkUseCase.ReturnLinkResult.DeepLink("com.example")); VenmoApi venmoApi = new MockVenmoApiBuilder() .createPaymentContextSuccess("venmo-payment-context-id") @@ -181,7 +186,8 @@ public void createPaymentAuthRequest_whenCreatePaymentContextSucceeds_createsVen sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -231,7 +237,8 @@ public void createPaymentAuthRequest_whenConfigurationException_forwardsExceptio sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -261,7 +268,8 @@ public void createPaymentAuthRequest_whenVenmoNotEnabled_forwardsExceptionToList sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -297,7 +305,8 @@ public void createPaymentAuthRequest_whenProfileIdIsNull_appSwitchesWithMerchant sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -316,41 +325,78 @@ public void createPaymentAuthRequest_whenProfileIdIsNull_appSwitchesWithMerchant @Test public void createPaymentAuthRequest_whenAppLinkUriSet_appSwitchesWithAppLink() { BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(venmoEnabledConfiguration) - .build(); + .configuration(venmoEnabledConfiguration) + .build(); VenmoApi venmoApi = new MockVenmoApiBuilder() - .createPaymentContextSuccess("venmo-payment-context-id") - .build(); + .createPaymentContextSuccess("venmo-payment-context-id") + .build(); VenmoRequest request = new VenmoRequest(VenmoPaymentMethodUsage.SINGLE_USE); request.setProfileId(null); request.setShouldVault(false); - when(merchantRepository.getAppLinkReturnUri()).thenReturn(Uri.parse("https://example.com/payments")); - VenmoClient sut = new VenmoClient( - braintreeClient, - apiClient, - venmoApi, - sharedPrefsWriter, - analyticsParamRepository, - merchantRepository, - venmoRepository + braintreeClient, + apiClient, + venmoApi, + sharedPrefsWriter, + analyticsParamRepository, + merchantRepository, + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); ArgumentCaptor captor = - ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); + ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); verify(venmoPaymentAuthRequestCallback).onVenmoPaymentAuthRequest(captor.capture()); VenmoPaymentAuthRequest paymentAuthRequest = captor.getValue(); VenmoPaymentAuthRequestParams params = ((VenmoPaymentAuthRequest.ReadyToLaunch) paymentAuthRequest).getRequestParams(); BrowserSwitchOptions browserSwitchOptions = params.getBrowserSwitchOptions(); Uri url = browserSwitchOptions.getUrl(); - assertEquals("https://example.com/payments/success", url.getQueryParameter("x-success")); - assertEquals("https://example.com/payments/error", url.getQueryParameter("x-error")); - assertEquals("https://example.com/payments/cancel", url.getQueryParameter("x-cancel")); + assertEquals("https://example.com/success", url.getQueryParameter("x-success")); + assertEquals("https://example.com/error", url.getQueryParameter("x-error")); + assertEquals("https://example.com/cancel", url.getQueryParameter("x-cancel")); + } + + @Test + public void createPaymentAuthRequest_throws_error_when_getReturnLinkUseCase_returnsFailure() { + BraintreeException exception = new BraintreeException(); + BraintreeClient braintreeClient = new MockBraintreeClientBuilder() + .configuration(venmoEnabledConfiguration) + .build(); + + when(merchantRepository.getAuthorization()).thenReturn(clientToken); + when(getReturnLinkUseCase.invoke()).thenReturn(new GetReturnLinkUseCase.ReturnLinkResult.Failure(exception)); + + VenmoApi venmoApi = new MockVenmoApiBuilder() + .createPaymentContextSuccess("venmo-payment-context-id") + .build(); + + VenmoRequest request = new VenmoRequest(VenmoPaymentMethodUsage.SINGLE_USE); + request.setProfileId("second-pwv-profile-id"); + request.setShouldVault(false); + + VenmoClient sut = new VenmoClient( + braintreeClient, + apiClient, + venmoApi, + sharedPrefsWriter, + analyticsParamRepository, + merchantRepository, + venmoRepository, + getReturnLinkUseCase + ); + sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); + + ArgumentCaptor captor = + ArgumentCaptor.forClass(VenmoPaymentAuthRequest.class); + verify(venmoPaymentAuthRequestCallback).onVenmoPaymentAuthRequest(captor.capture()); + VenmoPaymentAuthRequest paymentAuthRequest = captor.getValue(); + assertTrue(paymentAuthRequest instanceof VenmoPaymentAuthRequest.Failure); + assertEquals(exception, ((VenmoPaymentAuthRequest.Failure) paymentAuthRequest).getError()); } @Test @@ -376,7 +422,8 @@ public void createPaymentAuthRequest_whenProfileIdIsSpecified_appSwitchesWithPro sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -411,7 +458,8 @@ public void createPaymentAuthRequest_sendsAnalyticsEvent() { sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); verify(braintreeClient).sendAnalyticsEvent(VenmoAnalytics.TOKENIZE_STARTED, new AnalyticsEventParams()); @@ -440,7 +488,8 @@ public void createPaymentAuthRequest_whenShouldVaultIsTrue_persistsVenmoVaultTru sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -470,7 +519,8 @@ public void createPaymentAuthRequest_whenShouldVaultIsFalse_persistsVenmoVaultFa sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -500,7 +550,8 @@ public void createPaymentAuthRequest_withTokenizationKey_persistsVenmoVaultFalse sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -529,7 +580,8 @@ public void createPaymentAuthRequest_whenVenmoApiError_forwardsErrorToListener_a sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.createPaymentAuthRequest(context, request, venmoPaymentAuthRequestCallback); @@ -557,7 +609,8 @@ public void tokenize_withPaymentContextId_requestFromVenmoApi() { sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -583,7 +636,8 @@ public void tokenize_withPaymentAuthResult_whenUserCanceled_returnsCancelAndSend sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -618,7 +672,8 @@ public void tokenize_onGraphQLPostSuccess_returnsNonceToListener_andSendsAnalyti sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -656,7 +711,8 @@ public void tokenize_onGraphQLPostFailure_forwardsExceptionToListener_andSendsAn sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -698,7 +754,8 @@ public void tokenize_withPaymentContext_performsVaultRequestIfRequestPersisted() sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -719,7 +776,8 @@ public void tokenize_postsPaymentMethodNonceOnSuccess() { sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -754,7 +812,8 @@ public void tokenize_performsVaultRequestIfRequestPersisted() throws JSONExcepti sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -777,7 +836,8 @@ public void tokenize_doesNotPerformRequestIfTokenizationKeyUsed() { sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -808,7 +868,8 @@ public void tokenize_withSuccessfulVaultCall_forwardsResultToActivityResultListe sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -849,7 +910,8 @@ public void tokenize_withPaymentContext_withSuccessfulVaultCall_forwardsNonceToC sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -885,7 +947,8 @@ public void tokenize_withFailedVaultCall_forwardsErrorToActivityResultListener_a sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback); @@ -930,7 +993,8 @@ public void tokenize_withPaymentContext_withFailedVaultCall_forwardsErrorToCallb sharedPrefsWriter, analyticsParamRepository, merchantRepository, - venmoRepository + venmoRepository, + getReturnLinkUseCase ); sut.tokenize(paymentAuthResult, venmoTokenizeCallback);