diff --git a/app/build.gradle b/app/build.gradle index 4a6716b61a..c1963138fb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -231,7 +231,7 @@ dependencies { implementation "com.jakewharton.rxbinding:rxbinding-recyclerview-v7:$rx_binding_version" implementation "com.jakewharton.rxbinding:rxbinding-support-v4:$rx_binding_version" implementation "com.jakewharton.timber:timber:5.0.1" - implementation 'com.stripe:stripe-android:20.16.1' + implementation 'com.stripe:stripe-android:20.42.0' final okhttp_version = '4.10.+' implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version" implementation "com.squareup.okhttp3:okhttp-urlconnection:$okhttp_version" diff --git a/app/src/main/java/com/kickstarter/libs/featureflag/FeatureFlagClient.kt b/app/src/main/java/com/kickstarter/libs/featureflag/FeatureFlagClient.kt index 0e71c43cef..52a2206568 100644 --- a/app/src/main/java/com/kickstarter/libs/featureflag/FeatureFlagClient.kt +++ b/app/src/main/java/com/kickstarter/libs/featureflag/FeatureFlagClient.kt @@ -63,7 +63,8 @@ enum class FlagKey(val key: String) { ANDROID_DARK_MODE_ENABLED("android_dark_mode_enabled"), ANDROID_POST_CAMPAIGN_PLEDGES("android_post_campaign_pledges"), ANDROID_OAUTH("android_oauth"), - ANDROID_ENCRYPT("android_encrypt_token") + ANDROID_ENCRYPT("android_encrypt_token"), + ANDROID_STRIPE_LINK("android_stripe_link") } fun FeatureFlagClient.getFetchInterval(): Long = diff --git a/app/src/main/java/com/kickstarter/libs/utils/extensions/ContextExt.kt b/app/src/main/java/com/kickstarter/libs/utils/extensions/ContextExt.kt index cdf944b093..816b79d5c7 100644 --- a/app/src/main/java/com/kickstarter/libs/utils/extensions/ContextExt.kt +++ b/app/src/main/java/com/kickstarter/libs/utils/extensions/ContextExt.kt @@ -103,11 +103,25 @@ fun Context.showAlertDialog( * Provides the configuration for the PaymentSheet, following the specs * @see [link](https://stripe.com/docs/payments/accept-a-payment?platform=android&ui=elements#android-flowcontroller) */ -fun Context.getPaymentSheetConfiguration(): PaymentSheet.Configuration { +fun Context.getPaymentSheetConfiguration(userEmail: String, alwaysHideLink: Boolean): PaymentSheet.Configuration { + val stripeLinkEnabled = this.getEnvironment()?.featureFlagClient()?.getBoolean(FlagKey.ANDROID_STRIPE_LINK) ?: false + val billingDetailsCollectionConfiguration = + if (alwaysHideLink || !stripeLinkEnabled) { + PaymentSheet.BillingDetailsCollectionConfiguration( + email = PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode.Always // Turn off Link + ) + } else { + PaymentSheet.BillingDetailsCollectionConfiguration( + email = PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode.Automatic + ) + } + return PaymentSheet.Configuration( merchantDisplayName = getString(R.string.app_name), allowsDelayedPaymentMethods = true, - appearance = this.getPaymentSheetAppearance() + appearance = this.getPaymentSheetAppearance(), + defaultBillingDetails = PaymentSheet.BillingDetails(email = userEmail), + billingDetailsCollectionConfiguration = billingDetailsCollectionConfiguration ) } diff --git a/app/src/main/java/com/kickstarter/ui/activities/PaymentMethodsSettingsActivity.kt b/app/src/main/java/com/kickstarter/ui/activities/PaymentMethodsSettingsActivity.kt index 5d5ea1f181..1a353421d1 100644 --- a/app/src/main/java/com/kickstarter/ui/activities/PaymentMethodsSettingsActivity.kt +++ b/app/src/main/java/com/kickstarter/ui/activities/PaymentMethodsSettingsActivity.kt @@ -146,7 +146,7 @@ class PaymentMethodsSettingsActivity : AppCompatActivity() { private fun flowControllerPresentPaymentOption(clientSecret: String) { flowController.configureWithSetupIntent( setupIntentClientSecret = clientSecret, - configuration = this.getPaymentSheetConfiguration(), + configuration = this.getPaymentSheetConfiguration("", true), // Always hide Link on settings page callback = ::onConfigured ) } diff --git a/app/src/main/java/com/kickstarter/ui/activities/ProjectPageActivity.kt b/app/src/main/java/com/kickstarter/ui/activities/ProjectPageActivity.kt index 25d52891e2..674072e837 100644 --- a/app/src/main/java/com/kickstarter/ui/activities/ProjectPageActivity.kt +++ b/app/src/main/java/com/kickstarter/ui/activities/ProjectPageActivity.kt @@ -576,7 +576,7 @@ class ProjectPageActivity : LaunchedEffect(Unit) { latePledgeCheckoutViewModel.clientSecretForNewPaymentMethod.collect { - flowControllerPresentPaymentOption(it) + flowControllerPresentPaymentOption(it, latePledgeCheckoutUIState.userEmail) } } @@ -1262,10 +1262,10 @@ class ProjectPageActivity : } } - private fun flowControllerPresentPaymentOption(clientSecret: String) { + private fun flowControllerPresentPaymentOption(clientSecret: String, userEmail: String) { flowController.configureWithSetupIntent( setupIntentClientSecret = clientSecret, - configuration = getPaymentSheetConfiguration(), + configuration = getPaymentSheetConfiguration(userEmail, false), callback = ::onConfigured ) } diff --git a/app/src/main/java/com/kickstarter/ui/activities/compose/FormularyScreen.kt b/app/src/main/java/com/kickstarter/ui/activities/compose/FormularyScreen.kt index 33ba5b5606..027e3d4ab6 100644 --- a/app/src/main/java/com/kickstarter/ui/activities/compose/FormularyScreen.kt +++ b/app/src/main/java/com/kickstarter/ui/activities/compose/FormularyScreen.kt @@ -112,7 +112,7 @@ fun FormularyScreen( value = outputs.email().subscribeAsState(initial = "").value, onValueChange = {}, readOnly = true, - label = { Text(stringResource(id = R.string.email)) }, + label = { Text(stringResource(id = R.string.Email)) }, colors = TextFieldDefaults.textFieldColors( backgroundColor = colors.kds_support_200, errorLabelColor = colors.kds_alert, diff --git a/app/src/main/java/com/kickstarter/ui/activities/compose/login/ResetPasswordScreen.kt b/app/src/main/java/com/kickstarter/ui/activities/compose/login/ResetPasswordScreen.kt index a5761e61c7..d0fd70e018 100644 --- a/app/src/main/java/com/kickstarter/ui/activities/compose/login/ResetPasswordScreen.kt +++ b/app/src/main/java/com/kickstarter/ui/activities/compose/login/ResetPasswordScreen.kt @@ -190,7 +190,7 @@ fun ResetPasswordScreen( ) ) .testTag(ResetPasswordTestTag.EMAIL.name), - label = stringResource(id = R.string.email), + label = stringResource(id = R.string.Email), initialValue = initialEmail, onValueChanged = { value -> emailInput = value diff --git a/app/src/main/java/com/kickstarter/ui/fragments/PledgeFragment.kt b/app/src/main/java/com/kickstarter/ui/fragments/PledgeFragment.kt index 3bc900035a..a018059364 100644 --- a/app/src/main/java/com/kickstarter/ui/fragments/PledgeFragment.kt +++ b/app/src/main/java/com/kickstarter/ui/fragments/PledgeFragment.kt @@ -583,9 +583,9 @@ class PledgeFragment : this.viewModel.outputs.presentPaymentSheet() .observeOn(AndroidSchedulers.mainThread()) - .subscribe { - setupClientId = it - flowControllerPresentPaymentOption(it) + .subscribe { clientSecretAndUserEmail: Pair -> + setupClientId = clientSecretAndUserEmail.first + flowControllerPresentPaymentOption(clientSecretAndUserEmail.first, clientSecretAndUserEmail.second) } .addToDisposable(disposables) @@ -697,11 +697,11 @@ class PledgeFragment : } } - private fun flowControllerPresentPaymentOption(clientSecret: String) { + private fun flowControllerPresentPaymentOption(clientSecret: String, userEmail: String) { context?.let { flowController.configureWithSetupIntent( setupIntentClientSecret = clientSecret, - configuration = it.getPaymentSheetConfiguration(), + configuration = it.getPaymentSheetConfiguration(userEmail, false), callback = ::onConfigured ) } diff --git a/app/src/main/java/com/kickstarter/ui/toolbars/compose/ToolBar.kt b/app/src/main/java/com/kickstarter/ui/toolbars/compose/ToolBar.kt index 9e17360432..e25876360b 100644 --- a/app/src/main/java/com/kickstarter/ui/toolbars/compose/ToolBar.kt +++ b/app/src/main/java/com/kickstarter/ui/toolbars/compose/ToolBar.kt @@ -70,7 +70,7 @@ fun TopToolBar( ) { Icon( imageVector = leftIcon, - contentDescription = stringResource(id = R.string.back), + contentDescription = stringResource(id = R.string.Back), tint = leftIconColor ?: colors.kds_black ) } diff --git a/app/src/main/java/com/kickstarter/ui/views/compose/search/SearchTopBar.kt b/app/src/main/java/com/kickstarter/ui/views/compose/search/SearchTopBar.kt index 104fdb7ae3..155729c558 100644 --- a/app/src/main/java/com/kickstarter/ui/views/compose/search/SearchTopBar.kt +++ b/app/src/main/java/com/kickstarter/ui/views/compose/search/SearchTopBar.kt @@ -77,7 +77,7 @@ fun SearchTopBar( ) { Icon( imageVector = Icons.Filled.ArrowBack, - contentDescription = stringResource(id = R.string.back), + contentDescription = stringResource(id = R.string.Back), tint = colors.kds_black ) } diff --git a/app/src/main/java/com/kickstarter/viewmodels/PledgeFragmentViewModel.kt b/app/src/main/java/com/kickstarter/viewmodels/PledgeFragmentViewModel.kt index 1b543ddd91..6bade10b6f 100644 --- a/app/src/main/java/com/kickstarter/viewmodels/PledgeFragmentViewModel.kt +++ b/app/src/main/java/com/kickstarter/viewmodels/PledgeFragmentViewModel.kt @@ -332,7 +332,7 @@ interface PledgeFragmentViewModel { fun localPickUpName(): Observable /** Emits the String with the SetupIntent ClientID to present the PaymentSheet **/ - fun presentPaymentSheet(): Observable + fun presentPaymentSheet(): Observable> fun showError(): Observable @@ -464,7 +464,7 @@ interface PledgeFragmentViewModel { private val localPickUpIsGone = BehaviorSubject.create() private val localPickUpName = BehaviorSubject.create() - private val presentPaymentSheet = PublishSubject.create() + private val presentPaymentSheet = PublishSubject.create>() private val paymentSheetResult = PublishSubject.create() private val paySheetPresented = PublishSubject.create() private val showError = PublishSubject.create() @@ -1253,6 +1253,7 @@ interface PledgeFragmentViewModel { shouldPresentPaymentSheet .compose(valuesV2()) + .compose(combineLatestPair(userEmail())) .subscribe { this.presentPaymentSheet.onNext(it) } @@ -1847,6 +1848,12 @@ interface PledgeFragmentViewModel { .compose(neverErrorV2()) } + private fun userEmail(): Observable { + return this.apolloClient.userPrivacy() + .compose(neverErrorV2()) + .map { it.email } + } + override fun onCleared() { disposables.clear() super.onCleared() @@ -2035,7 +2042,7 @@ interface PledgeFragmentViewModel { override fun localPickUpName(): Observable = localPickUpName - override fun presentPaymentSheet(): Observable = + override fun presentPaymentSheet(): Observable> = this.presentPaymentSheet override fun showError(): Observable = diff --git a/app/src/test/java/com/kickstarter/viewmodels/PledgeFragmentViewModelTest.kt b/app/src/test/java/com/kickstarter/viewmodels/PledgeFragmentViewModelTest.kt index f6bafdbeac..5e5b66dbd7 100644 --- a/app/src/test/java/com/kickstarter/viewmodels/PledgeFragmentViewModelTest.kt +++ b/app/src/test/java/com/kickstarter/viewmodels/PledgeFragmentViewModelTest.kt @@ -107,7 +107,7 @@ class PledgeFragmentViewModelTest : KSRobolectricTestCase() { private val shippingSummaryAmount = TestSubscriber() private val shippingSummaryIsGone = TestSubscriber() private val shippingSummaryLocation = TestSubscriber() - private val presentPaymentSheet = TestSubscriber() + private val presentPaymentSheet = TestSubscriber>() private val showPledgeError = TestSubscriber() private val showPledgeSuccess = TestSubscriber>() private val showSelectedCard = TestSubscriber>() @@ -1966,7 +1966,7 @@ class PledgeFragmentViewModelTest : KSRobolectricTestCase() { // - Configure PaymentSheet this.vm.inputs.newCardButtonClicked() - this.presentPaymentSheet.assertValue(clientSecretID) + this.presentPaymentSheet.assertValue(Pair(clientSecretID, "some@email.com")) this.segmentTrack.assertValue(EventName.PAGE_VIEWED.eventName) this.pledgeButtonIsEnabled.assertValues(true, false) this.loadingState.assertValues(State.LOADING) @@ -2021,7 +2021,7 @@ class PledgeFragmentViewModelTest : KSRobolectricTestCase() { setUpEnvironment(environment, RewardFactory.noReward(), backedProject, PledgeReason.FIX_PLEDGE) this.vm.inputs.newCardButtonClicked() - this.presentPaymentSheet.assertValue("") + this.presentPaymentSheet.assertValue(Pair("", "some@email.com")) this.segmentTrack.assertNoValues() this.pledgeButtonIsEnabled.assertValues(false, false) this.loadingState.assertValues(State.LOADING) @@ -2042,7 +2042,7 @@ class PledgeFragmentViewModelTest : KSRobolectricTestCase() { setUpEnvironment(environment, RewardFactory.noReward(), backedProject, PledgeReason.UPDATE_PAYMENT) this.vm.inputs.newCardButtonClicked() - this.presentPaymentSheet.assertValue("") + this.presentPaymentSheet.assertValue(Pair("", "some@email.com")) this.segmentTrack.assertValue(EventName.PAGE_VIEWED.eventName) this.pledgeButtonIsEnabled.assertValues(true, false) this.loadingState.assertValues(State.LOADING)