Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shipping details to payment sheet #5419

Merged
merged 2 commits into from
Aug 19, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 13 additions & 5 deletions link/api/link.api
Expand Up @@ -18,8 +18,8 @@ public final class com/stripe/android/link/LinkActivityContract$Args : com/strip
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
public static final field Companion Lcom/stripe/android/link/LinkActivityContract$Args$Companion;
public final fun copy (Lcom/stripe/android/model/StripeIntent;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/stripe/android/model/PaymentMethodCreateParams;Lcom/stripe/android/link/LinkActivityContract$Args$InjectionParams;)Lcom/stripe/android/link/LinkActivityContract$Args;
public static synthetic fun copy$default (Lcom/stripe/android/link/LinkActivityContract$Args;Lcom/stripe/android/model/StripeIntent;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/stripe/android/model/PaymentMethodCreateParams;Lcom/stripe/android/link/LinkActivityContract$Args$InjectionParams;ILjava/lang/Object;)Lcom/stripe/android/link/LinkActivityContract$Args;
public final fun copy (Lcom/stripe/android/model/StripeIntent;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lcom/stripe/android/model/PaymentMethodCreateParams;Lcom/stripe/android/link/LinkActivityContract$Args$InjectionParams;)Lcom/stripe/android/link/LinkActivityContract$Args;
public static synthetic fun copy$default (Lcom/stripe/android/link/LinkActivityContract$Args;Lcom/stripe/android/model/StripeIntent;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lcom/stripe/android/model/PaymentMethodCreateParams;Lcom/stripe/android/link/LinkActivityContract$Args$InjectionParams;ILjava/lang/Object;)Lcom/stripe/android/link/LinkActivityContract$Args;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
Expand Down Expand Up @@ -184,8 +184,8 @@ public final class com/stripe/android/link/LinkPaymentLauncher$Companion {
public final class com/stripe/android/link/LinkPaymentLauncher_Factory {
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lcom/stripe/android/link/LinkPaymentLauncher_Factory;
public fun get (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/stripe/android/link/LinkPaymentLauncher;
public static fun newInstance (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/content/Context;Ljava/util/Set;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ZLkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/CoroutineContext;Lcom/stripe/android/networking/PaymentAnalyticsRequestFactory;Lcom/stripe/android/core/networking/AnalyticsRequestExecutor;Lcom/stripe/android/networking/StripeRepository;Lcom/stripe/android/ui/core/forms/resources/ResourceRepository;)Lcom/stripe/android/link/LinkPaymentLauncher;
public fun get (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Lcom/stripe/android/link/LinkPaymentLauncher;
public static fun newInstance (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Landroid/content/Context;Ljava/util/Set;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ZLkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/CoroutineContext;Lcom/stripe/android/networking/PaymentAnalyticsRequestFactory;Lcom/stripe/android/core/networking/AnalyticsRequestExecutor;Lcom/stripe/android/networking/StripeRepository;Lcom/stripe/android/ui/core/forms/resources/ResourceRepository;)Lcom/stripe/android/link/LinkPaymentLauncher;
}

public final class com/stripe/android/link/account/CookieStore_Factory : dagger/internal/Factory {
Expand Down Expand Up @@ -252,6 +252,14 @@ public final class com/stripe/android/link/injection/LinkActivityContractArgsMod
public static fun provideCustomerPhone (Lcom/stripe/android/link/LinkActivityContract$Args;)Ljava/lang/String;
}

public final class com/stripe/android/link/injection/LinkActivityContractArgsModule_Companion_ProvideInitialValuesMapFactory : dagger/internal/Factory {
public fun <init> (Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;)Lcom/stripe/android/link/injection/LinkActivityContractArgsModule_Companion_ProvideInitialValuesMapFactory;
public synthetic fun get ()Ljava/lang/Object;
public fun get ()Ljava/util/Map;
public static fun provideInitialValuesMap (Lcom/stripe/android/link/LinkActivityContract$Args;)Ljava/util/Map;
}

public final class com/stripe/android/link/injection/LinkActivityContractArgsModule_Companion_ProvideMerchantNameFactory : dagger/internal/Factory {
public fun <init> (Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;)Lcom/stripe/android/link/injection/LinkActivityContractArgsModule_Companion_ProvideMerchantNameFactory;
Expand All @@ -270,7 +278,7 @@ public final class com/stripe/android/link/injection/LinkActivityContractArgsMod

public final class com/stripe/android/link/injection/LinkPaymentLauncherFactory_Impl : com/stripe/android/link/injection/LinkPaymentLauncherFactory {
public static fun create (Lcom/stripe/android/link/LinkPaymentLauncher_Factory;)Ljavax/inject/Provider;
public fun create (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/stripe/android/link/LinkPaymentLauncher;
public fun create (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Lcom/stripe/android/link/LinkPaymentLauncher;
}

public final class com/stripe/android/link/injection/NamedConstantsKt {
Expand Down
Expand Up @@ -9,6 +9,7 @@ import androidx.core.os.bundleOf
import com.stripe.android.core.injection.InjectorKey
import com.stripe.android.model.PaymentMethodCreateParams
import com.stripe.android.model.StripeIntent
import com.stripe.android.ui.core.elements.IdentifierSpec
import com.stripe.android.view.ActivityStarter
import kotlinx.parcelize.Parcelize

Expand Down Expand Up @@ -40,6 +41,7 @@ class LinkActivityContract :
internal val merchantName: String,
internal val customerEmail: String? = null,
internal val customerPhone: String? = null,
internal val initialValueMap: Map<IdentifierSpec, String?>? = null,
internal val prefilledCardParams: PaymentMethodCreateParams? = null,
internal val injectionParams: InjectionParams? = null
) : ActivityStarter.Args {
Expand Down
Expand Up @@ -20,6 +20,7 @@ import com.stripe.android.link.injection.DaggerLinkPaymentLauncherComponent
import com.stripe.android.link.injection.LinkComponent
import com.stripe.android.link.injection.LinkPaymentLauncherComponent
import com.stripe.android.link.injection.MERCHANT_NAME
import com.stripe.android.link.injection.INITIAL_VALUES_MAP
import com.stripe.android.link.model.AccountStatus
import com.stripe.android.link.ui.cardedit.CardEditViewModel
import com.stripe.android.link.ui.inline.InlineSignupViewModel
Expand All @@ -35,6 +36,7 @@ import com.stripe.android.networking.PaymentAnalyticsRequestFactory
import com.stripe.android.networking.StripeRepository
import com.stripe.android.payments.core.injection.PRODUCT_USAGE
import com.stripe.android.ui.core.address.AddressRepository
import com.stripe.android.ui.core.elements.IdentifierSpec
import com.stripe.android.ui.core.forms.resources.ResourceRepository
import com.stripe.android.ui.core.injection.NonFallbackInjectable
import com.stripe.android.ui.core.injection.NonFallbackInjector
Expand All @@ -54,6 +56,7 @@ class LinkPaymentLauncher @AssistedInject internal constructor(
@Assisted(MERCHANT_NAME) private val merchantName: String,
@Assisted(CUSTOMER_EMAIL) private val customerEmail: String?,
@Assisted(CUSTOMER_PHONE) private val customerPhone: String?,
@Assisted(INITIAL_VALUES_MAP) private val initialValuesMap: Map<IdentifierSpec, String?>?,
context: Context,
@Named(PRODUCT_USAGE) private val productUsage: Set<String>,
@Named(PUBLISHABLE_KEY) private val publishableKeyProvider: () -> String,
Expand All @@ -71,6 +74,7 @@ class LinkPaymentLauncher @AssistedInject internal constructor(
.merchantName(merchantName)
.customerEmail(customerEmail)
.customerPhone(customerPhone)
.initialValuesMap(initialValuesMap)
.context(context)
.ioContext(ioContext)
.uiContext(uiContext)
Expand Down Expand Up @@ -149,6 +153,7 @@ class LinkPaymentLauncher @AssistedInject internal constructor(
merchantName,
customerEmail,
customerPhone,
initialValuesMap,
prefilledNewCardParams,
LinkActivityContract.Args.InjectionParams(
injectorKey,
Expand Down
Expand Up @@ -38,5 +38,10 @@ internal interface LinkActivityContractArgsModule {
@Singleton
@Named(CUSTOMER_PHONE)
fun provideCustomerPhone(args: LinkActivityContract.Args) = args.customerPhone

@Provides
@Singleton
@Named(INITIAL_VALUES_MAP)
fun provideInitialValuesMap(args: LinkActivityContract.Args) = args.initialValueMap
}
}
Expand Up @@ -17,6 +17,7 @@ import com.stripe.android.networking.PaymentAnalyticsRequestFactory
import com.stripe.android.networking.StripeRepository
import com.stripe.android.payments.core.injection.PRODUCT_USAGE
import com.stripe.android.ui.core.address.AddressRepository
import com.stripe.android.ui.core.elements.IdentifierSpec
import com.stripe.android.ui.core.forms.resources.ResourceRepository
import dagger.BindsInstance
import dagger.Component
Expand Down Expand Up @@ -57,6 +58,9 @@ internal abstract class LinkPaymentLauncherComponent {
@BindsInstance
fun stripeIntent(@Named(LINK_INTENT) stripeIntent: StripeIntent): Builder

@BindsInstance
fun initialValuesMap(@Named(INITIAL_VALUES_MAP) initialValuesMap: Map<IdentifierSpec, String?>?): Builder

@BindsInstance
fun context(context: Context): Builder

Expand Down
Expand Up @@ -2,6 +2,7 @@ package com.stripe.android.link.injection

import androidx.annotation.RestrictTo
import com.stripe.android.link.LinkPaymentLauncher
import com.stripe.android.ui.core.elements.IdentifierSpec
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory

Expand All @@ -11,6 +12,7 @@ interface LinkPaymentLauncherFactory {
fun create(
@Assisted(MERCHANT_NAME) merchantName: String,
@Assisted(CUSTOMER_EMAIL) customerEmail: String?,
@Assisted(CUSTOMER_PHONE) customerPhone: String?
@Assisted(CUSTOMER_PHONE) customerPhone: String?,
@Assisted(INITIAL_VALUES_MAP) initialValuesMap: Map<IdentifierSpec, String?>?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make the names more descriptive? It's not clear what's in the map. Something like INITIAL_SHIPPING_ADDRESS_VALUES_MAP, initialShippingAddressValuesMap is clearer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or if you're thinking of making this generic (not only for shipping address), maybe initialFormValuesMap

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can make it less generic

I like initialFormValuesMap

): LinkPaymentLauncher
}
Expand Up @@ -20,6 +20,12 @@ const val CUSTOMER_EMAIL = "customerEmail"
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
const val CUSTOMER_PHONE = "customerPhone"

/**
* Identifies the shipping address passed in from the customer, used to pre-fill address forms.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
const val INITIAL_VALUES_MAP = "initialValuesMap"

/**
* Identifies the Stripe Intent being processed by Link.
*/
Expand Down
Expand Up @@ -72,16 +72,19 @@ internal class PaymentMethodViewModel @Inject constructor(
val formController = MutableStateFlow<FormController?>(null)

fun init(loadFromArgs: Boolean) {
val cardMap = args.prefilledCardParams?.toParamMap()
?.takeIf { loadFromArgs }
?.let { convertToFormValuesMap(it) }
?: emptyMap()
val initialValuesMap = args.initialValueMap
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should loadFromArgs be used here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadFromArgs exists because when you launch Link passing in the pre-filled card params, you'll want the form to be pre-filled with those values. But then if the user navigates within Link and ends up in this screen again, we won't want to load the values from the initial arguments. How does this logic apply to address?

?: emptyMap()
val combinedMap = cardMap + initialValuesMap
formController.value =
formControllerProvider.get()
.formSpec(LayoutSpec(paymentMethod.formSpec))
.viewOnlyFields(emptySet())
.viewModelScope(viewModelScope)
.initialValues(
args.prefilledCardParams?.toParamMap()?.takeIf { loadFromArgs }?.let {
convertToFormValuesMap(it)
} ?: emptyMap()
)
.initialValues(combinedMap)
.stripeIntent(args.stripeIntent)
.merchantName(args.merchantName)
.build().formController
Expand Down
Expand Up @@ -27,6 +27,7 @@ class LinkActivityContractTest {
"customer@email.com",
"1234567890",
null,
null,
injectionParams
)

Expand Down
Expand Up @@ -38,6 +38,7 @@ class LinkActivityViewModelTest {
CUSTOMER_EMAIL,
CUSTOMER_PHONE,
null,
null,
LinkActivityContract.Args.InjectionParams(
INJECTOR_KEY,
setOf(PRODUCT_USAGE),
Expand Down
Expand Up @@ -27,6 +27,7 @@ class LinkPaymentLauncherTest {
MERCHANT_NAME,
null,
null,
null,
context,
setOf(PRODUCT_USAGE),
{ PUBLISHABLE_KEY },
Expand Down
Expand Up @@ -52,6 +52,7 @@ class SignUpViewModelTest {
CUSTOMER_EMAIL,
CUSTOMER_PHONE,
null,
null,
LinkActivityContract.Args.InjectionParams(
INJECTOR_KEY,
setOf(PRODUCT_USAGE),
Expand Down
63 changes: 62 additions & 1 deletion payments-ui-core/api/payments-ui-core.api
Expand Up @@ -68,6 +68,35 @@ public final class com/stripe/android/ui/core/address/AddressRepository_Factory
public static fun newInstance (Landroid/content/res/Resources;)Lcom/stripe/android/ui/core/address/AddressRepository;
}

public final class com/stripe/android/ui/core/address/ShippingAddress : android/os/Parcelable {
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lcom/stripe/android/model/Address;Ljava/lang/Boolean;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Lcom/stripe/android/model/Address;
public final fun component4 ()Ljava/lang/Boolean;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Lcom/stripe/android/model/Address;Ljava/lang/Boolean;)Lcom/stripe/android/ui/core/address/ShippingAddress;
public static synthetic fun copy$default (Lcom/stripe/android/ui/core/address/ShippingAddress;Ljava/lang/String;Ljava/lang/String;Lcom/stripe/android/model/Address;Ljava/lang/Boolean;ILjava/lang/Object;)Lcom/stripe/android/ui/core/address/ShippingAddress;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getAddress ()Lcom/stripe/android/model/Address;
public final fun getName ()Ljava/lang/String;
public final fun getPhone ()Ljava/lang/String;
public final fun getSameAsShippingEnabled ()Ljava/lang/Boolean;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}

public final class com/stripe/android/ui/core/address/ShippingAddress$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/ui/core/address/ShippingAddress;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lcom/stripe/android/ui/core/address/ShippingAddress;
public synthetic fun newArray (I)[Ljava/lang/Object;
}

public final class com/stripe/android/ui/core/databinding/ActivityCardScanBinding : androidx/viewbinding/ViewBinding {
public final field fragmentContainer Landroidx/fragment/app/FragmentContainerView;
public static fun bind (Landroid/view/View;)Lcom/stripe/android/ui/core/databinding/ActivityCardScanBinding;
Expand Down Expand Up @@ -263,7 +292,7 @@ public abstract class com/stripe/android/ui/core/elements/CardNumberController :
public final fun onCardScanResult (Lcom/stripe/android/stripecardscan/cardscan/CardScanSheetResult;)V
}

public final class com/stripe/android/ui/core/elements/CheckboxElementUiKt {
public final class com/stripe/android/ui/core/elements/CheckboxElementUIKt {
}

public final class com/stripe/android/ui/core/elements/ComposableSingletons$SectionUIKt {
Expand Down Expand Up @@ -441,12 +470,21 @@ public final class com/stripe/android/ui/core/elements/IdentifierSpec$Companion
public final fun getOneLineAddress ()Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public final fun getPhone ()Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public final fun getPostalCode ()Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public final fun getSameAsShipping ()Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public final fun getSaveForFutureUse ()Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public final fun getSortingCode ()Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public final fun getState ()Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class com/stripe/android/ui/core/elements/IdentifierSpec$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lcom/stripe/android/ui/core/elements/IdentifierSpec;
public synthetic fun newArray (I)[Ljava/lang/Object;
}

public final class com/stripe/android/ui/core/elements/KeyboardType : java/lang/Enum {
public static final field Ascii Lcom/stripe/android/ui/core/elements/KeyboardType;
public static final field Companion Lcom/stripe/android/ui/core/elements/KeyboardType$Companion;
Expand Down Expand Up @@ -574,6 +612,25 @@ public final class com/stripe/android/ui/core/elements/PhoneNumberState$Companio
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class com/stripe/android/ui/core/elements/SameAsShippingController : com/stripe/android/ui/core/elements/InputController {
public static final field $stable I
public fun <init> (Z)V
public fun getError ()Lkotlinx/coroutines/flow/Flow;
public fun getFieldValue ()Lkotlinx/coroutines/flow/Flow;
public fun getFormFieldValue ()Lkotlinx/coroutines/flow/Flow;
public fun getLabel ()Lkotlinx/coroutines/flow/Flow;
public fun getRawFieldValue ()Lkotlinx/coroutines/flow/Flow;
public fun getShowOptionalLabel ()Z
public final fun getValue ()Lkotlinx/coroutines/flow/Flow;
public fun isComplete ()Lkotlinx/coroutines/flow/Flow;
public fun onRawValueChange (Ljava/lang/String;)V
public final fun onValueChange (Z)V
}

public final class com/stripe/android/ui/core/elements/SameAsShippingElementUIKt {
public static final field SAME_AS_SHIPPING_CHECKBOX_TEST_TAG Ljava/lang/String;
}

public final class com/stripe/android/ui/core/elements/SaveForFutureUseElementUIKt {
public static final field SAVE_FOR_FUTURE_CHECKBOX_TEST_TAG Ljava/lang/String;
}
Expand All @@ -598,6 +655,10 @@ public final class com/stripe/android/ui/core/elements/SaveForFutureUseSpec$Comp
public final class com/stripe/android/ui/core/elements/SectionElementUIKt {
}

public final class com/stripe/android/ui/core/elements/SectionFieldElement$DefaultImpls {
public static fun getShouldRenderOutsideCard (Lcom/stripe/android/ui/core/elements/SectionFieldElement;)Z
}

public final class com/stripe/android/ui/core/elements/SectionUIKt {
}

Expand Down
1 change: 1 addition & 0 deletions payments-ui-core/res/values/totranslate.xml
Expand Up @@ -13,4 +13,5 @@
<string name="stripe_paymentsheet_autocomplete_no_results_found">No results found</string>
<string name="stripe_paymentsheet_address_element_shipping_address">Shipping Address</string>
<string name="stripe_paymentsheet_address_element_primary_button">Save Address</string>
<string name="stripe_paymentsheet_address_element_same_as_shipping">Billing address is same as shipping</string>
</resources>
@@ -0,0 +1,13 @@
package com.stripe.android.ui.core.address

import android.os.Parcelable
import com.stripe.android.model.Address
import kotlinx.parcelize.Parcelize

@Parcelize
data class ShippingAddress(
tillh-stripe marked this conversation as resolved.
Show resolved Hide resolved
val name: String?,
val phone: String?,
val address: Address?,
val sameAsShippingEnabled: Boolean?
) : Parcelable