diff --git a/CHANGELOG.md b/CHANGELOG.md index 7682499eebd..81fb8ed5f4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ ### PaymentSheet * [ADDED][7302](https://github.com/stripe/stripe-android/pull/7302) PaymentSheet now supports Alma for PaymentIntents in private beta. +* [ADDED][7191](https://github.com/stripe/stripe-android/pull/7191) `PaymentSheet.GooglePayConfiguration` now takes an optional `amount` and `label`. The `amount` will be displayed in Google Pay for SetupIntents, while `label` will be displayed for both PaymentIntents and SetupIntents. + +### Payments +* [ADDED][7191](https://github.com/stripe/stripe-android/pull/7191) `GooglePayLauncher` now takes an optional `label` when presenting Google Pay for PaymentIntents, and an optional `amount` and `label` when presenting for SetupIntents. +* [ADDED][7191](https://github.com/stripe/stripe-android/pull/7191) `GooglePayPaymentMethodLauncher` now takes an optional `label` when presenting Google Pay. ## 20.30.2 - 2023-09-13 diff --git a/payments-core/api/payments-core.api b/payments-core/api/payments-core.api index 09c31c32588..8810652cc72 100644 --- a/payments-core/api/payments-core.api +++ b/payments-core/api/payments-core.api @@ -1096,7 +1096,12 @@ public final class com/stripe/android/googlepaylauncher/GooglePayLauncher { public fun (Landroidx/activity/ComponentActivity;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$ReadyCallback;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$ResultCallback;)V public fun (Landroidx/fragment/app/Fragment;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$ReadyCallback;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$ResultCallback;)V public final fun presentForPaymentIntent (Ljava/lang/String;)V + public final fun presentForPaymentIntent (Ljava/lang/String;Ljava/lang/String;)V + public static synthetic fun presentForPaymentIntent$default (Lcom/stripe/android/googlepaylauncher/GooglePayLauncher;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)V public final fun presentForSetupIntent (Ljava/lang/String;Ljava/lang/String;)V + public final fun presentForSetupIntent (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)V + public final fun presentForSetupIntent (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;)V + public static synthetic fun presentForSetupIntent$default (Lcom/stripe/android/googlepaylauncher/GooglePayLauncher;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;ILjava/lang/Object;)V } public final class com/stripe/android/googlepaylauncher/GooglePayLauncher$BillingAddressConfig : android/os/Parcelable { @@ -1263,8 +1268,10 @@ public final class com/stripe/android/googlepaylauncher/GooglePayLauncherContrac public static final field $stable I public static final field CREATOR Landroid/os/Parcelable$Creator; public fun (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;)V - public final fun copy (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;)Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$PaymentIntentArgs; - public static synthetic fun copy$default (Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$PaymentIntentArgs;Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;ILjava/lang/Object;)Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$PaymentIntentArgs; + public fun (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;)V + public synthetic fun (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun copy (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;)Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$PaymentIntentArgs; + public static synthetic fun copy$default (Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$PaymentIntentArgs;Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;ILjava/lang/Object;)Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$PaymentIntentArgs; public fun describeContents ()I public fun equals (Ljava/lang/Object;)Z public fun hashCode ()I @@ -1284,8 +1291,11 @@ public final class com/stripe/android/googlepaylauncher/GooglePayLauncherContrac public static final field $stable I public static final field CREATOR Landroid/os/Parcelable$Creator; public fun (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;)V - public final fun copy (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;)Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$SetupIntentArgs; - public static synthetic fun copy$default (Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$SetupIntentArgs;Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;ILjava/lang/Object;)Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$SetupIntentArgs; + public fun (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;Ljava/lang/Long;)V + public fun (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;)V + public synthetic fun (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun copy (Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;)Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$SetupIntentArgs; + public static synthetic fun copy$default (Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$SetupIntentArgs;Ljava/lang/String;Lcom/stripe/android/googlepaylauncher/GooglePayLauncher$Config;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;ILjava/lang/Object;)Lcom/stripe/android/googlepaylauncher/GooglePayLauncherContract$SetupIntentArgs; public fun describeContents ()I public fun equals (Ljava/lang/Object;)Z public fun hashCode ()I @@ -1350,8 +1360,9 @@ public final class com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLa public final fun present (Ljava/lang/String;ILjava/lang/String;)V public final fun present (Ljava/lang/String;J)V public final fun present (Ljava/lang/String;JLjava/lang/String;)V + public final fun present (Ljava/lang/String;JLjava/lang/String;Ljava/lang/String;)V public static synthetic fun present$default (Lcom/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncher;Ljava/lang/String;ILjava/lang/String;ILjava/lang/Object;)V - public static synthetic fun present$default (Lcom/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncher;Ljava/lang/String;JLjava/lang/String;ILjava/lang/Object;)V + public static synthetic fun present$default (Lcom/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncher;Ljava/lang/String;JLjava/lang/String;Ljava/lang/String;ILjava/lang/Object;)V } public final class com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncher$BillingAddressConfig : android/os/Parcelable { diff --git a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncher.kt b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncher.kt index 3aff106a6e6..088f420bf47 100644 --- a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncher.kt +++ b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncher.kt @@ -152,8 +152,15 @@ class GooglePayLauncher internal constructor( * object. * * @param clientSecret the PaymentIntent's [client secret](https://stripe.com/docs/api/payment_intents/object#payment_intent_object-client_secret) + * @param label An optional label to display with the amount. Google Pay may or may not display + * this label depending on its own internal logic. Defaults to a generic label if none is + * provided. */ - fun presentForPaymentIntent(clientSecret: String) { + @JvmOverloads + fun presentForPaymentIntent( + clientSecret: String, + label: String? = null, + ) { check(isReady) { "presentForPaymentIntent() may only be called when Google Pay is available on this device." } @@ -161,7 +168,8 @@ class GooglePayLauncher internal constructor( activityResultLauncher.launch( GooglePayLauncherContract.PaymentIntentArgs( clientSecret = clientSecret, - config = config + config = config, + label = label, ) ) } @@ -175,10 +183,18 @@ class GooglePayLauncher internal constructor( * * @param clientSecret the SetupIntent's [client secret](https://stripe.com/docs/api/setup_intents/object#setup_intent_object-client_secret) * @param currencyCode The ISO 4217 alphabetic currency code. + * @param amount An optional amount to display. Google Pay may or may not display this amount + * depending on its own internal logic. Defaults to 0 if none is provided. + * @param label An optional label to display with the amount. Google Pay may or may not display + * this label depending on its own internal logic. Defaults to a generic label if none is + * provided. */ + @JvmOverloads fun presentForSetupIntent( clientSecret: String, - currencyCode: String + currencyCode: String, + amount: Long? = null, + label: String? = null, ) { check(isReady) { "presentForSetupIntent() may only be called when Google Pay is available on this device." @@ -188,7 +204,9 @@ class GooglePayLauncher internal constructor( GooglePayLauncherContract.SetupIntentArgs( clientSecret = clientSecret, config = config, - currencyCode = currencyCode + currencyCode = currencyCode, + amount = amount, + label = label, ) ) } diff --git a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncherContract.kt b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncherContract.kt index 82343dd04d6..0a378fda852 100644 --- a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncherContract.kt +++ b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncherContract.kt @@ -35,19 +35,22 @@ class GooglePayLauncherContract : * Args for launching [GooglePayLauncherContract] to confirm a [PaymentIntent]. */ @Parcelize - data class PaymentIntentArgs( + data class PaymentIntentArgs @JvmOverloads constructor( override val clientSecret: String, - override val config: GooglePayLauncher.Config + override val config: GooglePayLauncher.Config, + internal val label: String? = null, ) : Args() /** * Args for launching [GooglePayLauncherContract] to confirm a [SetupIntent]. */ @Parcelize - data class SetupIntentArgs( + data class SetupIntentArgs @JvmOverloads constructor( override val clientSecret: String, override val config: GooglePayLauncher.Config, - internal val currencyCode: String + internal val currencyCode: String, + internal val amount: Long? = null, + internal val label: String? = null, ) : Args() sealed class Args : Parcelable { diff --git a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncherViewModel.kt b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncherViewModel.kt index e80780ea8e9..e36d73642b1 100644 --- a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncherViewModel.kt +++ b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayLauncherViewModel.kt @@ -84,6 +84,7 @@ internal class GooglePayLauncherViewModel( createTransactionInfo( stripeIntent = intent, currencyCode = intent.currency.orEmpty(), + label = args.label, ) } } @@ -95,6 +96,8 @@ internal class GooglePayLauncherViewModel( createTransactionInfo( stripeIntent = intent, currencyCode = args.currencyCode, + amount = args.amount, + label = args.label, ) } } @@ -123,7 +126,9 @@ internal class GooglePayLauncherViewModel( @VisibleForTesting internal fun createTransactionInfo( stripeIntent: StripeIntent, - currencyCode: String + currencyCode: String, + amount: Long? = null, + label: String? = null, ): GooglePayJsonFactory.TransactionInfo { return when (stripeIntent) { is PaymentIntent -> { @@ -134,7 +139,7 @@ internal class GooglePayLauncherViewModel( transactionId = stripeIntent.id, totalPrice = stripeIntent.amount, totalPriceLabel = null, - checkoutOption = GooglePayJsonFactory.TransactionInfo.CheckoutOption.CompleteImmediatePurchase + checkoutOption = GooglePayJsonFactory.TransactionInfo.CheckoutOption.CompleteImmediatePurchase, ) } is SetupIntent -> { @@ -143,9 +148,9 @@ internal class GooglePayLauncherViewModel( totalPriceStatus = GooglePayJsonFactory.TransactionInfo.TotalPriceStatus.Estimated, countryCode = args.config.merchantCountryCode, transactionId = stripeIntent.id, - totalPrice = 0L, - totalPriceLabel = null, - checkoutOption = GooglePayJsonFactory.TransactionInfo.CheckoutOption.Default + totalPrice = amount ?: 0L, + totalPriceLabel = label, + checkoutOption = GooglePayJsonFactory.TransactionInfo.CheckoutOption.Default, ) } } diff --git a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncher.kt b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncher.kt index e6070bbefed..fd3d019a6b4 100644 --- a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncher.kt +++ b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncher.kt @@ -247,12 +247,16 @@ class GooglePayPaymentMethodLauncher @AssistedInject internal constructor( * @param transactionId A unique ID that identifies a transaction attempt. Merchants may use an * existing ID or generate a specific one for Google Pay transaction attempts. * This field is required when you send callbacks to the Google Transaction Events API. + * @param label An optional label to display with the amount. Google Pay may or may not display + * this label depending on its own internal logic. Defaults to a generic label if none is + * provided. */ @JvmOverloads fun present( currencyCode: String, amount: Long = 0L, - transactionId: String? = null + transactionId: String? = null, + label: String? = null, ) { check(skipReadyCheck || isReady) { "present() may only be called when Google Pay is available on this device." @@ -263,6 +267,7 @@ class GooglePayPaymentMethodLauncher @AssistedInject internal constructor( config = config, currencyCode = currencyCode, amount = amount, + label = label, transactionId = transactionId, injectionParams = GooglePayPaymentMethodLauncherContractV2.Args.InjectionParams( injectorKey, diff --git a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherContractV2.kt b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherContractV2.kt index 771038b6184..0f86461ea40 100644 --- a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherContractV2.kt +++ b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherContractV2.kt @@ -46,16 +46,26 @@ class GooglePayPaymentMethodLauncherContractV2 : internal val config: GooglePayPaymentMethodLauncher.Config, internal val currencyCode: String, internal val amount: Long, + internal val label: String? = null, internal val transactionId: String? = null, - internal val injectionParams: InjectionParams? = null + internal val injectionParams: InjectionParams? = null, ) : Parcelable { + @JvmOverloads constructor( config: GooglePayPaymentMethodLauncher.Config, currencyCode: String, amount: Long, - transactionId: String? = null - ) : this(config, currencyCode, amount, transactionId, null) + transactionId: String? = null, + label: String? = null, + ) : this( + config = config, + currencyCode = currencyCode, + amount = amount, + label = label, + transactionId = transactionId, + injectionParams = null, + ) internal fun toBundle() = bundleOf(EXTRA_ARGS to this) diff --git a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherViewModel.kt b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherViewModel.kt index 457c2c21d36..1ae50d102e8 100644 --- a/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherViewModel.kt +++ b/payments-core/src/main/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherViewModel.kt @@ -83,7 +83,7 @@ internal class GooglePayPaymentMethodLauncherViewModel @Inject constructor( countryCode = args.config.merchantCountryCode, transactionId = args.transactionId, totalPrice = args.amount, - totalPriceLabel = null, + totalPriceLabel = args.label, checkoutOption = GooglePayJsonFactory.TransactionInfo.CheckoutOption.Default ) } diff --git a/payments-core/src/test/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherViewModelTest.kt b/payments-core/src/test/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherViewModelTest.kt index 3212b439938..8adef597ae9 100644 --- a/payments-core/src/test/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherViewModelTest.kt +++ b/payments-core/src/test/java/com/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherViewModelTest.kt @@ -164,11 +164,12 @@ class GooglePayPaymentMethodLauncherViewModelTest { val factory = GooglePayPaymentMethodLauncherViewModel.Factory( GooglePayPaymentMethodLauncherContractV2.Args( - mock(), - "usd", - 1099, - null, - GooglePayPaymentMethodLauncherContractV2.Args.InjectionParams( + config = mock(), + currencyCode = "usd", + amount = 1099, + label = null, + transactionId = null, + injectionParams = GooglePayPaymentMethodLauncherContractV2.Args.InjectionParams( injectorKey, emptySet(), false, @@ -201,15 +202,16 @@ class GooglePayPaymentMethodLauncherViewModelTest { val factory = GooglePayPaymentMethodLauncherViewModel.Factory( GooglePayPaymentMethodLauncherContractV2.Args( - GooglePayPaymentMethodLauncher.Config( + config = GooglePayPaymentMethodLauncher.Config( GooglePayEnvironment.Test, "US", "merchant" ), - "usd", - 1099, - null, - GooglePayPaymentMethodLauncherContractV2.Args.InjectionParams( + currencyCode = "usd", + amount = 1099, + label = null, + transactionId = null, + injectionParams = GooglePayPaymentMethodLauncherContractV2.Args.InjectionParams( DUMMY_INJECTOR_KEY, productUsage, false, diff --git a/paymentsheet/api/paymentsheet.api b/paymentsheet/api/paymentsheet.api index ef13da80f74..da4d0452e68 100644 --- a/paymentsheet/api/paymentsheet.api +++ b/paymentsheet/api/paymentsheet.api @@ -681,17 +681,23 @@ public final class com/stripe/android/paymentsheet/PaymentSheet$GooglePayConfigu public static final field CREATOR Landroid/os/Parcelable$Creator; public fun (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;)V public fun (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;)V + public fun (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;)V + public synthetic fun (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment; public final fun component2 ()Ljava/lang/String; public final fun component3 ()Ljava/lang/String; - public final fun copy (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;)Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration; - public static synthetic fun copy$default (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration;Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration; + public final fun component4 ()Ljava/lang/Long; + public final fun component5 ()Ljava/lang/String; + public final fun copy (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;)Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration; + public static synthetic fun copy$default (Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration;Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;ILjava/lang/Object;)Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration; public fun describeContents ()I public fun equals (Ljava/lang/Object;)Z + public final fun getAmount ()Ljava/lang/Long; public final fun getCountryCode ()Ljava/lang/String; public final fun getCurrencyCode ()Ljava/lang/String; public final fun getEnvironment ()Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment; + public final fun getLabel ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; public fun writeToParcel (Landroid/os/Parcel;I)V diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheet.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheet.kt index c5fe74af374..3cb08c97689 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheet.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheet.kt @@ -1037,33 +1037,32 @@ class PaymentSheet internal constructor( val ephemeralKeySecret: String ) : Parcelable + /** + * @param environment The Google Pay environment to use. See + * [Google's documentation](https://developers.google.com/android/reference/com/google/android/gms/wallet/Wallet.WalletOptions#environment) + * for more information. + * @param countryCode The two-letter ISO 3166 code of the country of your business, e.g. "US". + * See your account's country value [here](https://dashboard.stripe.com/settings/account). + * @param currencyCode The three-letter ISO 4217 alphabetic currency code, e.g. "USD" or "EUR". + * Required in order to support Google Pay when processing a Setup Intent. + * @param amount An optional amount to display for setup intents. Google Pay may or may not + * display this amount depending on its own internal logic. Defaults to 0 if none is provided. + * @param label An optional label to display with the amount. Google Pay may or may not display + * this label depending on its own internal logic. Defaults to a generic label if none is + * provided. + */ @Parcelize - data class GooglePayConfiguration( - /** - * The Google Pay environment to use. - * - * See [Google's documentation](https://developers.google.com/android/reference/com/google/android/gms/wallet/Wallet.WalletOptions#environment) for more information. - */ + data class GooglePayConfiguration @JvmOverloads constructor( val environment: Environment, - /** - * The two-letter ISO 3166 code of the country of your business, e.g. "US". - * See your account's country value [here](https://dashboard.stripe.com/settings/account). - */ val countryCode: String, - /** - * The three-letter ISO 4217 alphabetic currency code, e.g. "USD" or "EUR". - * Required in order to support Google Pay when processing a Setup Intent. - */ - val currencyCode: String? = null + val currencyCode: String? = null, + val amount: Long? = null, + val label: String? = null, ) : Parcelable { - constructor( - environment: Environment, - countryCode: String - ) : this(environment, countryCode, null) enum class Environment { Production, - Test + Test, } } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheetViewModel.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheetViewModel.kt index 580e2924b53..ae01221dc9a 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheetViewModel.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentSheetViewModel.kt @@ -374,8 +374,12 @@ internal class PaymentSheetViewModel @Inject internal constructor( googlePayPaymentMethodLauncher?.present( currencyCode = (stripeIntent as? PaymentIntent)?.currency ?: args.googlePayConfig?.currencyCode.orEmpty(), - amount = (stripeIntent as? PaymentIntent)?.amount ?: 0L, - transactionId = stripeIntent.id + amount = when (stripeIntent) { + is PaymentIntent -> stripeIntent.amount ?: 0L + is SetupIntent -> args.googlePayConfig?.amount ?: 0L + }, + transactionId = stripeIntent.id, + label = args.googlePayConfig?.label, ) } } else { diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/flowcontroller/DefaultFlowController.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/flowcontroller/DefaultFlowController.kt index 57606ae9b82..6554ec82240 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/flowcontroller/DefaultFlowController.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/flowcontroller/DefaultFlowController.kt @@ -551,7 +551,8 @@ internal class DefaultFlowController @Inject internal constructor( currencyCode = (state.stripeIntent as? PaymentIntent)?.currency ?: googlePayConfig.currencyCode.orEmpty(), amount = (state.stripeIntent as? PaymentIntent)?.amount ?: 0L, - transactionId = state.stripeIntent.id + transactionId = state.stripeIntent.id, + label = googlePayConfig.label, ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentSheetFixtures.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentSheetFixtures.kt index 455c9f7eb67..26c9f8c6f66 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentSheetFixtures.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentSheetFixtures.kt @@ -20,12 +20,10 @@ internal object PaymentSheetFixtures { internal const val MERCHANT_DISPLAY_NAME = "Merchant, Inc." internal const val CLIENT_SECRET = "pi_1234_secret_1234" internal const val DIFFERENT_CLIENT_SECRET = "pi_4321_secret_4321" + internal const val SETUP_CLIENT_SECRET = "seti_1234_secret_4321" - internal val PAYMENT_INTENT_CLIENT_SECRET = PaymentIntentClientSecret( - CLIENT_SECRET - ) - - internal val SETUP_INTENT_CLIENT_SECRET = PaymentIntentClientSecret("seti_1234_secret_4321") + internal val PAYMENT_INTENT_CLIENT_SECRET = PaymentIntentClientSecret(CLIENT_SECRET) + internal val SETUP_INTENT_CLIENT_SECRET = PaymentIntentClientSecret(SETUP_CLIENT_SECRET) internal val CONFIG_MINIMUM = PaymentSheet.Configuration( merchantDisplayName = MERCHANT_DISPLAY_NAME diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentSheetViewModelTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentSheetViewModelTest.kt index 03bdb5fc491..d8eca9c62c2 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentSheetViewModelTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentSheetViewModelTest.kt @@ -16,6 +16,7 @@ import com.stripe.android.core.StripeError import com.stripe.android.core.exception.APIException import com.stripe.android.core.networking.AnalyticsRequestFactory import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher +import com.stripe.android.googlepaylauncher.injection.GooglePayPaymentMethodLauncherFactory import com.stripe.android.link.LinkConfigurationCoordinator import com.stripe.android.link.model.AccountStatus import com.stripe.android.model.Address @@ -131,6 +132,10 @@ internal class PaymentSheetViewModelTest { private val paymentLauncherFactory = mock { on { create(any(), any(), anyOrNull(), any()) } doReturn paymentLauncher } + private val googlePayLauncher = mock() + private val googlePayLauncherFactory = mock { + on { create(any(), any(), any(), any(), any()) } doReturn googlePayLauncher + } private val fakeIntentConfirmationInterceptor = FakeIntentConfirmationInterceptor() private val linkConfigurationCoordinator = mock { @@ -1537,6 +1542,81 @@ internal class PaymentSheetViewModelTest { ) } + @Test + fun `Launches Google Pay with custom label if provided for payment intent`() { + val expectedLabel = "My custom label" + val expectedAmount = 1099L + + val args = ARGS_CUSTOMER_WITH_GOOGLEPAY.copy( + config = ARGS_CUSTOMER_WITH_GOOGLEPAY.config?.copy( + googlePay = PaymentSheet.GooglePayConfiguration( + environment = PaymentSheet.GooglePayConfiguration.Environment.Test, + countryCode = "CA", + currencyCode = "CAD", + amount = 12345, + label = expectedLabel, + ) + ) + ) + + val viewModel = createViewModel( + args = args, + isGooglePayReady = true, + ) + + viewModel.setupGooglePay( + lifecycleScope = mock(), + activityResultLauncher = mock(), + ) + + viewModel.checkoutWithGooglePay() + + verify(googlePayLauncher).present( + currencyCode = any(), + amount = eq(expectedAmount), + transactionId = anyOrNull(), + label = eq(expectedLabel), + ) + } + + @Test + fun `Launches Google Pay with custom label and amount if provided for setup intent`() { + val expectedLabel = "My custom label" + val expectedAmount = 1234L + + val args = ARGS_CUSTOMER_WITH_GOOGLEPAY_SETUP.copy( + config = ARGS_CUSTOMER_WITH_GOOGLEPAY_SETUP.config?.copy( + googlePay = PaymentSheet.GooglePayConfiguration( + environment = PaymentSheet.GooglePayConfiguration.Environment.Test, + countryCode = "CA", + currencyCode = "CAD", + amount = expectedAmount, + label = expectedLabel, + ) + ) + ) + + val viewModel = createViewModel( + args = args, + isGooglePayReady = true, + stripeIntent = SETUP_INTENT, + ) + + viewModel.setupGooglePay( + lifecycleScope = mock(), + activityResultLauncher = mock(), + ) + + viewModel.checkoutWithGooglePay() + + verify(googlePayLauncher).present( + currencyCode = any(), + amount = eq(expectedAmount), + transactionId = anyOrNull(), + label = eq(expectedLabel), + ) + } + private fun createViewModel( args: PaymentSheetContractV2.Args = ARGS_CUSTOMER_WITH_GOOGLEPAY, stripeIntent: StripeIntent = PAYMENT_INTENT, @@ -1553,11 +1633,11 @@ internal class PaymentSheetViewModelTest { linkConfigurationCoordinator = linkConfigurationCoordinator, ) { linkHandler, linkInteractor, savedStateHandle -> PaymentSheetViewModel( - application, - args, - eventReporter, - { paymentConfiguration }, - FakePaymentSheetLoader( + application = application, + args = args, + eventReporter = eventReporter, + lazyPaymentConfig = { paymentConfiguration }, + paymentSheetLoader = FakePaymentSheetLoader( stripeIntent = stripeIntent, shouldFail = shouldFailLoad, linkState = linkState, @@ -1565,13 +1645,13 @@ internal class PaymentSheetViewModelTest { delay = delay, isGooglePayAvailable = isGooglePayReady, ), - customerRepository, - prefsRepository, - lpmRepository, + customerRepository = customerRepository, + prefsRepository = prefsRepository, + lpmRepository = lpmRepository, paymentLauncherFactory = paymentLauncherFactory, - mock(), - Logger.noop(), - testDispatcher, + googlePayPaymentMethodLauncherFactory = googlePayLauncherFactory, + logger = Logger.noop(), + workContext = testDispatcher, savedStateHandle = savedStateHandle, linkHandler = linkHandler, linkConfigurationCoordinator = linkInteractor, @@ -1606,5 +1686,6 @@ internal class PaymentSheetViewModelTest { private val PAYMENT_METHODS = listOf(PaymentMethodFixtures.CARD_PAYMENT_METHOD) val PAYMENT_INTENT = PaymentIntentFixtures.PI_REQUIRES_PAYMENT_METHOD + val SETUP_INTENT = SetupIntentFixtures.SI_REQUIRES_PAYMENT_METHOD } } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/flowcontroller/DefaultFlowControllerTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/flowcontroller/DefaultFlowControllerTest.kt index ff2d89d4d17..82194a4f649 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/flowcontroller/DefaultFlowControllerTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/flowcontroller/DefaultFlowControllerTest.kt @@ -1337,6 +1337,76 @@ internal class DefaultFlowControllerTest { ) } + @Test + fun `Launches Google Pay with custom label if provided for payment intent`() = runTest { + val expectedLabel = "My custom label" + val expectedAmount = 1099L + + val flowController = createFlowController() + + flowController.configureExpectingSuccess( + clientSecret = PaymentSheetFixtures.CLIENT_SECRET, + configuration = PaymentSheet.Configuration( + merchantDisplayName = "My merchant", + googlePay = PaymentSheet.GooglePayConfiguration( + environment = PaymentSheet.GooglePayConfiguration.Environment.Test, + countryCode = "CA", + currencyCode = "CAD", + amount = 1234L, + label = expectedLabel, + ) + ) + ) + + flowController.onPaymentOptionResult( + PaymentOptionResult.Succeeded(PaymentSelection.GooglePay) + ) + + flowController.confirm() + + verify(googlePayPaymentMethodLauncher).present( + currencyCode = any(), + amount = eq(expectedAmount), + transactionId = anyOrNull(), + label = eq(expectedLabel), + ) + } + + @Test + fun `Launches Google Pay with custom label and amount if provided for setup intent`() = runTest { + val expectedLabel = "My custom label" + val expectedAmount = 1099L + + val flowController = createFlowController() + + flowController.configureExpectingSuccess( + clientSecret = PaymentSheetFixtures.SETUP_CLIENT_SECRET, + configuration = PaymentSheet.Configuration( + merchantDisplayName = "My merchant", + googlePay = PaymentSheet.GooglePayConfiguration( + environment = PaymentSheet.GooglePayConfiguration.Environment.Test, + countryCode = "CA", + currencyCode = "CAD", + amount = expectedAmount, + label = expectedLabel, + ) + ) + ) + + flowController.onPaymentOptionResult( + PaymentOptionResult.Succeeded(PaymentSelection.GooglePay) + ) + + flowController.confirm() + + verify(googlePayPaymentMethodLauncher).present( + currencyCode = any(), + amount = eq(expectedAmount), + transactionId = anyOrNull(), + label = eq(expectedLabel), + ) + } + private fun createAndConfigureFlowControllerForDeferredIntent( paymentIntent: PaymentIntent = PaymentIntentFixtures.PI_SUCCEEDED, ): DefaultFlowController {