From 4fb074536ca7b3e2d022d60c96135310668b4c49 Mon Sep 17 00:00:00 2001 From: Michael Shafrir Date: Tue, 28 Jan 2020 15:25:04 -0500 Subject: [PATCH] Enable adding mandate information to confirm params Summary - Update confirm params creation methods to take an optional mandate id or mandate data - Remove `ConfirmPaymentIntentParams.Builder` - Remove `ConfirmSetupIntentParams.Builder` Motivation Fixes #2103 Testing Add unit tests --- .../model/ConfirmPaymentIntentParams.kt | 157 ++---------------- .../android/model/ConfirmSetupIntentParams.kt | 94 +++-------- .../stripe/android/model/MandateDataParams.kt | 2 +- .../model/ConfirmPaymentIntentParamsTest.kt | 96 ++++++++--- .../model/ConfirmSetupIntentParamsTest.kt | 98 +++++++---- 5 files changed, 182 insertions(+), 265 deletions(-) diff --git a/stripe/src/main/java/com/stripe/android/model/ConfirmPaymentIntentParams.kt b/stripe/src/main/java/com/stripe/android/model/ConfirmPaymentIntentParams.kt index 7b91223c940..d4e990fad55 100644 --- a/stripe/src/main/java/com/stripe/android/model/ConfirmPaymentIntentParams.kt +++ b/stripe/src/main/java/com/stripe/android/model/ConfirmPaymentIntentParams.kt @@ -1,7 +1,5 @@ package com.stripe.android.model -import androidx.annotation.VisibleForTesting -import com.stripe.android.ObjectBuilder import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_CLIENT_SECRET import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_MANDATE_DATA import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_MANDATE_ID @@ -101,9 +99,7 @@ data class ConfirmPaymentIntentParams internal constructor( } override fun withShouldUseStripeSdk(shouldUseStripeSdk: Boolean): ConfirmPaymentIntentParams { - return toBuilder() - .setShouldUseSdk(shouldUseStripeSdk) - .build() + return copy(useStripeSdk = shouldUseStripeSdk) } /** @@ -169,132 +165,6 @@ data class ConfirmPaymentIntentParams internal constructor( } } - @VisibleForTesting - internal fun toBuilder(): Builder { - return Builder(clientSecret) - .setReturnUrl(returnUrl) - .setSourceId(sourceId) - .setSavePaymentMethod(savePaymentMethod) - .setExtraParams(extraParams) - .setPaymentMethodOptions(paymentMethodOptions) - .also { builder -> - paymentMethodId?.let { builder.setPaymentMethodId(it) } - paymentMethodCreateParams?.let { builder.setPaymentMethodCreateParams(it) } - sourceParams?.let { builder.setSourceParams(sourceParams) } - } - } - - /** - * Sets the client secret that is used to authenticate actions on this PaymentIntent - * @param clientSecret client secret associated with this PaymentIntent - */ - @VisibleForTesting - internal class Builder internal constructor( - internal val clientSecret: String - ) : ObjectBuilder { - private var paymentMethodCreateParams: PaymentMethodCreateParams? = null - private var paymentMethodId: String? = null - private var sourceParams: SourceParams? = null - private var sourceId: String? = null - - private var extraParams: Map? = null - private var returnUrl: String? = null - - private var savePaymentMethod: Boolean = false - private var shouldUseSdk: Boolean = false - private var paymentMethodOptions: PaymentMethodOptionsParams? = null - - /** - * Sets the PaymentMethod data that will be included with this PaymentIntent - * - * @param paymentMethodCreateParams Params for the PaymentMethod that will be attached to - * this PaymentIntent. Only one of PaymentMethodParam, - * PaymentMethodId, SourceParam, SourceId should be used - * at a time. - */ - internal fun setPaymentMethodCreateParams( - paymentMethodCreateParams: PaymentMethodCreateParams - ): Builder = apply { - this.paymentMethodCreateParams = paymentMethodCreateParams - } - - /** - * Sets a pre-existing PaymentMethod that will be attached to this PaymentIntent - * - * @param paymentMethodId The ID of the PaymentMethod that is being attached to this - * PaymentIntent. Only one of PaymentMethodParam, PaymentMethodId, - * SourceParam, SourceId should be used at a time. - */ - internal fun setPaymentMethodId(paymentMethodId: String): Builder = apply { - this.paymentMethodId = paymentMethodId - } - - /** - * Sets the source data that will be included with this PaymentIntent - * - * @param sourceParams params for the source that will be attached to this PaymentIntent. - * Only one of SourceParam and SourceId should be used at at time. - */ - internal fun setSourceParams(sourceParams: SourceParams): Builder = apply { - this.sourceParams = sourceParams - } - - /** - * Sets a pre-existing source that will be attached to this PaymentIntent - * @param sourceId the ID of an existing Source that is being attached to this - * PaymentIntent. Only one of SourceParam and SourceId should be used at a - * time. - */ - internal fun setSourceId(sourceId: String?): Builder = apply { - this.sourceId = sourceId - } - - /** - * @param returnUrl the URL the customer should be redirected to after the authentication - * process - */ - internal fun setReturnUrl(returnUrl: String?): Builder = apply { - this.returnUrl = returnUrl - } - - /** - * @param extraParams params that will be included in the request. Incorrect params may - * result in errors when connecting to Stripe's API. - */ - internal fun setExtraParams(extraParams: Map?): Builder = apply { - this.extraParams = extraParams - } - - internal fun setSavePaymentMethod(savePaymentMethod: Boolean): Builder = apply { - this.savePaymentMethod = savePaymentMethod - } - - internal fun setShouldUseSdk(shouldUseSdk: Boolean): Builder = apply { - this.shouldUseSdk = shouldUseSdk - } - - internal fun setPaymentMethodOptions( - paymentMethodOptions: PaymentMethodOptionsParams? - ): Builder = apply { - this.paymentMethodOptions = paymentMethodOptions - } - - override fun build(): ConfirmPaymentIntentParams { - return ConfirmPaymentIntentParams( - clientSecret = clientSecret, - returnUrl = returnUrl, - paymentMethodId = paymentMethodId, - paymentMethodCreateParams = paymentMethodCreateParams, - sourceId = sourceId, - sourceParams = sourceParams, - savePaymentMethod = savePaymentMethod, - extraParams = extraParams, - useStripeSdk = shouldUseSdk, - paymentMethodOptions = paymentMethodOptions - ) - } - } - companion object { const val PARAM_SOURCE_DATA: String = "source_data" @@ -312,10 +182,11 @@ data class ConfirmPaymentIntentParams internal constructor( returnUrl: String? = null, extraParams: Map? = null ): ConfirmPaymentIntentParams { - return Builder(clientSecret) - .setReturnUrl(returnUrl) - .setExtraParams(extraParams) - .build() + return ConfirmPaymentIntentParams( + clientSecret = clientSecret, + returnUrl = returnUrl, + extraParams = extraParams + ) } /** @@ -343,7 +214,9 @@ data class ConfirmPaymentIntentParams internal constructor( returnUrl: String? = null, savePaymentMethod: Boolean = false, extraParams: Map? = null, - paymentMethodOptions: PaymentMethodOptionsParams? = null + paymentMethodOptions: PaymentMethodOptionsParams? = null, + mandateId: String? = null, + mandateData: MandateDataParams? = null ): ConfirmPaymentIntentParams { return ConfirmPaymentIntentParams( clientSecret = clientSecret, @@ -351,7 +224,9 @@ data class ConfirmPaymentIntentParams internal constructor( returnUrl = returnUrl, savePaymentMethod = savePaymentMethod, extraParams = extraParams, - paymentMethodOptions = paymentMethodOptions + paymentMethodOptions = paymentMethodOptions, + mandateId = mandateId, + mandateData = mandateData ) } @@ -378,14 +253,18 @@ data class ConfirmPaymentIntentParams internal constructor( clientSecret: String, returnUrl: String? = null, savePaymentMethod: Boolean = false, - extraParams: Map? = null + extraParams: Map? = null, + mandateId: String? = null, + mandateData: MandateDataParams? = null ): ConfirmPaymentIntentParams { return ConfirmPaymentIntentParams( clientSecret = clientSecret, paymentMethodCreateParams = paymentMethodCreateParams, returnUrl = returnUrl, savePaymentMethod = savePaymentMethod, - extraParams = extraParams + extraParams = extraParams, + mandateId = mandateId, + mandateData = mandateData ) } diff --git a/stripe/src/main/java/com/stripe/android/model/ConfirmSetupIntentParams.kt b/stripe/src/main/java/com/stripe/android/model/ConfirmSetupIntentParams.kt index f8438ed7f26..0f1853b57b9 100644 --- a/stripe/src/main/java/com/stripe/android/model/ConfirmSetupIntentParams.kt +++ b/stripe/src/main/java/com/stripe/android/model/ConfirmSetupIntentParams.kt @@ -1,8 +1,6 @@ package com.stripe.android.model import android.os.Parcelable -import androidx.annotation.VisibleForTesting -import com.stripe.android.ObjectBuilder import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_CLIENT_SECRET import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_MANDATE_DATA import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_MANDATE_ID @@ -18,7 +16,7 @@ data class ConfirmSetupIntentParams internal constructor( @get:JvmSynthetic internal val paymentMethodId: String? = null, @get:JvmSynthetic internal val paymentMethodCreateParams: PaymentMethodCreateParams? = null, private val returnUrl: String? = null, - private val useStripeSdk: Boolean, + private val useStripeSdk: Boolean = false, /** * ID of the mandate to be used for this payment. @@ -38,9 +36,7 @@ data class ConfirmSetupIntentParams internal constructor( } override fun withShouldUseStripeSdk(shouldUseStripeSdk: Boolean): ConfirmSetupIntentParams { - return toBuilder() - .setShouldUseSdk(shouldUseStripeSdk) - .build() + return copy(useStripeSdk = shouldUseStripeSdk) } /** @@ -96,55 +92,6 @@ data class ConfirmSetupIntentParams internal constructor( } } - @VisibleForTesting - internal fun toBuilder(): Builder { - val builder = Builder(clientSecret) - .setReturnUrl(returnUrl) - .setShouldUseSdk(useStripeSdk) - - paymentMethodId?.let { builder.setPaymentMethodId(it) } - paymentMethodCreateParams?.let { builder.setPaymentMethodCreateParams(it) } - - return builder - } - - internal class Builder internal constructor( - private val clientSecret: String - ) : ObjectBuilder { - private var paymentMethodId: String? = null - private var paymentMethodCreateParams: PaymentMethodCreateParams? = null - private var returnUrl: String? = null - private var useStripeSdk: Boolean = false - - internal fun setPaymentMethodId(paymentMethodId: String): Builder = apply { - this.paymentMethodId = paymentMethodId - } - - internal fun setPaymentMethodCreateParams( - paymentMethodCreateParams: PaymentMethodCreateParams - ): Builder = apply { - this.paymentMethodCreateParams = paymentMethodCreateParams - } - - internal fun setReturnUrl(returnUrl: String?): Builder = apply { - this.returnUrl = returnUrl - } - - internal fun setShouldUseSdk(useStripeSdk: Boolean): Builder = apply { - this.useStripeSdk = useStripeSdk - } - - override fun build(): ConfirmSetupIntentParams { - return ConfirmSetupIntentParams( - clientSecret = clientSecret, - returnUrl = returnUrl, - paymentMethodId = paymentMethodId, - paymentMethodCreateParams = paymentMethodCreateParams, - useStripeSdk = useStripeSdk - ) - } - } - companion object { /** * Create the parameters necessary for confirming a SetupIntent, without specifying a payment method @@ -164,9 +111,10 @@ data class ConfirmSetupIntentParams internal constructor( clientSecret: String, returnUrl: String? = null ): ConfirmSetupIntentParams { - return Builder(clientSecret) - .setReturnUrl(returnUrl) - .build() + return ConfirmSetupIntentParams( + clientSecret = clientSecret, + returnUrl = returnUrl + ) } /** @@ -187,12 +135,17 @@ data class ConfirmSetupIntentParams internal constructor( fun create( paymentMethodId: String, clientSecret: String, - returnUrl: String? = null + returnUrl: String? = null, + mandateId: String? = null, + mandateData: MandateDataParams? = null ): ConfirmSetupIntentParams { - return Builder(clientSecret) - .setReturnUrl(returnUrl) - .setPaymentMethodId(paymentMethodId) - .build() + return ConfirmSetupIntentParams( + clientSecret = clientSecret, + paymentMethodId = paymentMethodId, + returnUrl = returnUrl, + mandateId = mandateId, + mandateData = mandateData + ) } /** @@ -212,12 +165,17 @@ data class ConfirmSetupIntentParams internal constructor( fun create( paymentMethodCreateParams: PaymentMethodCreateParams, clientSecret: String, - returnUrl: String? = null + returnUrl: String? = null, + mandateId: String? = null, + mandateData: MandateDataParams? = null ): ConfirmSetupIntentParams { - return Builder(clientSecret) - .setPaymentMethodCreateParams(paymentMethodCreateParams) - .setReturnUrl(returnUrl) - .build() + return ConfirmSetupIntentParams( + clientSecret = clientSecret, + paymentMethodCreateParams = paymentMethodCreateParams, + returnUrl = returnUrl, + mandateId = mandateId, + mandateData = mandateData + ) } } } diff --git a/stripe/src/main/java/com/stripe/android/model/MandateDataParams.kt b/stripe/src/main/java/com/stripe/android/model/MandateDataParams.kt index 59015e421cd..7526d08fc94 100644 --- a/stripe/src/main/java/com/stripe/android/model/MandateDataParams.kt +++ b/stripe/src/main/java/com/stripe/android/model/MandateDataParams.kt @@ -9,7 +9,7 @@ import kotlinx.android.parcel.Parcelize * or [confirming a SetupIntent](https://stripe.com/docs/api/setup_intents/confirm#confirm_setup_intent-mandate_data) */ @Parcelize -internal data class MandateDataParams internal constructor( +data class MandateDataParams internal constructor( private val type: Type = Type.Online, private val typeData: TypeData? = null ) : StripeParamsModel, Parcelable { diff --git a/stripe/src/test/java/com/stripe/android/model/ConfirmPaymentIntentParamsTest.kt b/stripe/src/test/java/com/stripe/android/model/ConfirmPaymentIntentParamsTest.kt index 7565970bdea..43840a96094 100644 --- a/stripe/src/test/java/com/stripe/android/model/ConfirmPaymentIntentParamsTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/ConfirmPaymentIntentParamsTest.kt @@ -180,40 +180,86 @@ class ConfirmPaymentIntentParamsTest { } @Test - fun toBuilder_withPaymentMethodCreateParams_shouldCreateEqualObject() { - val extraParams = mapOf("key" to "value") - val params = ConfirmPaymentIntentParams.createWithPaymentMethodCreateParams( - PaymentMethodCreateParamsFixtures.DEFAULT_CARD, CLIENT_SECRET, RETURN_URL, true, extraParams + fun create_withSepaDebitPaymentMethodParams_shouldUseDefaultMandateDataIfNotSpecified() { + val expectedParams = mapOf( + "client_secret" to CLIENT_SECRET, + "save_payment_method" to false, + "use_stripe_sdk" to false, + "mandate_data" to mapOf( + "customer_acceptance" to mapOf( + "type" to "online", + "online" to mapOf( + "infer_from_client" to true + ) + ) + ), + "payment_method_data" to mapOf( + "type" to "sepa_debit", + "sepa_debit" to mapOf( + "iban" to "my_iban" + ) + ) ) - - assertEquals(params, params.toBuilder().build()) + val actualParams = + ConfirmPaymentIntentParams.createWithPaymentMethodCreateParams( + clientSecret = CLIENT_SECRET, + paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT + ).toParamMap() + assertEquals(expectedParams, actualParams) } @Test - fun create_withSepaDebitPaymentMethodParams_shouldUseDefaultMandateDataIfNotSpecified() { - val params = ConfirmPaymentIntentParams( - clientSecret = CLIENT_SECRET, - paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT - ).toParamMap() - assertEquals( - MandateDataParams(MandateDataParams.TypeData.Online( - inferFromClient = true - )).toParamMap(), - params[ConfirmStripeIntentParams.PARAM_MANDATE_DATA] + fun create_withSepaDebitPaymentMethodParams_shouldUseMandateDataIfSpecified() { + val expectedParams = mapOf( + "client_secret" to CLIENT_SECRET, + "save_payment_method" to false, + "use_stripe_sdk" to false, + "mandate_data" to mapOf( + "customer_acceptance" to mapOf( + "type" to "online", + "online" to mapOf( + "ip_address" to "127.0.0.1", + "user_agent" to "my_user_agent" + ) + ) + ), + "payment_method_data" to mapOf( + "type" to "sepa_debit", + "sepa_debit" to mapOf( + "iban" to "my_iban" + ) + ) ) + val actualParams = + ConfirmPaymentIntentParams.createWithPaymentMethodCreateParams( + clientSecret = CLIENT_SECRET, + paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT, + mandateData = MandateDataParamsFixtures.DEFAULT + ).toParamMap() + assertEquals(expectedParams, actualParams) } @Test - fun create_withSepaDebitPaymentMethodParams_shouldUseMandateDataIfSpecified() { - val params = ConfirmPaymentIntentParams( - clientSecret = CLIENT_SECRET, - paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT, - mandateData = MandateDataParamsFixtures.DEFAULT - ).toParamMap() - assertEquals( - MandateDataParamsFixtures.DEFAULT.toParamMap(), - params[ConfirmStripeIntentParams.PARAM_MANDATE_DATA] + fun create_withSepaDebitPaymentMethodParams_shouldUseMandateIdIfSpecified() { + val expectedParams = mapOf( + "client_secret" to CLIENT_SECRET, + "save_payment_method" to false, + "use_stripe_sdk" to false, + "mandate" to "mandate_123456789", + "payment_method_data" to mapOf( + "type" to "sepa_debit", + "sepa_debit" to mapOf( + "iban" to "my_iban" + ) + ) ) + val actualParams = + ConfirmPaymentIntentParams.createWithPaymentMethodCreateParams( + clientSecret = CLIENT_SECRET, + paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT, + mandateId = "mandate_123456789" + ).toParamMap() + assertEquals(expectedParams, actualParams) } @Test diff --git a/stripe/src/test/java/com/stripe/android/model/ConfirmSetupIntentParamsTest.kt b/stripe/src/test/java/com/stripe/android/model/ConfirmSetupIntentParamsTest.kt index 02369594606..9ff15488e86 100644 --- a/stripe/src/test/java/com/stripe/android/model/ConfirmSetupIntentParamsTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/ConfirmSetupIntentParamsTest.kt @@ -34,23 +34,6 @@ class ConfirmSetupIntentParamsTest { .shouldUseStripeSdk()) } - @Test - fun toBuilder_withPaymentMethodId_shouldCreateEqualObject() { - val confirmSetupIntentParams = ConfirmSetupIntentParams.create( - "pm_123", "client_secret", "return_url") - assertEquals(confirmSetupIntentParams, - confirmSetupIntentParams.toBuilder().build()) - } - - @Test - fun toBuilder_withPaymentMethodCreateParams_shouldCreateEqualObject() { - val confirmSetupIntentParams = ConfirmSetupIntentParams.create( - PaymentMethodCreateParamsFixtures.DEFAULT_CARD, - "client_secret", "return_url") - assertEquals(confirmSetupIntentParams, - confirmSetupIntentParams.toBuilder().build()) - } - @Test fun create_withPaymentMethodId_shouldPopulateParamMapCorrectly() { val confirmSetupIntentParams = ConfirmSetupIntentParams.create( @@ -87,31 +70,82 @@ class ConfirmSetupIntentParamsTest { @Test fun create_withSepaDebitPaymentMethodParams_shouldUseDefaultMandateDataIfNotSpecified() { - val params = ConfirmSetupIntentParams( + val expectedParams = mapOf( + "client_secret" to CLIENT_SECRET, + "use_stripe_sdk" to false, + "mandate_data" to mapOf( + "customer_acceptance" to mapOf( + "type" to "online", + "online" to mapOf( + "infer_from_client" to true + ) + ) + ), + "payment_method_data" to mapOf( + "type" to "sepa_debit", + "sepa_debit" to mapOf( + "iban" to "my_iban" + ) + ) + ) + + val actualParams = ConfirmSetupIntentParams.create( clientSecret = CLIENT_SECRET, - paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT, - useStripeSdk = true + paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT ).toParamMap() - assertEquals( - MandateDataParams(MandateDataParams.TypeData.Online( - inferFromClient = true - )).toParamMap(), - params[ConfirmStripeIntentParams.PARAM_MANDATE_DATA] - ) + assertEquals(expectedParams, actualParams) } @Test fun create_withSepaDebitPaymentMethodParams_shouldUseMandateDataIfSpecified() { - val params = ConfirmSetupIntentParams( + val expectedParams = mapOf( + "client_secret" to CLIENT_SECRET, + "use_stripe_sdk" to false, + "mandate_data" to mapOf( + "customer_acceptance" to mapOf( + "type" to "online", + "online" to mapOf( + "ip_address" to "127.0.0.1", + "user_agent" to "my_user_agent" + ) + ) + ), + "payment_method_data" to mapOf( + "type" to "sepa_debit", + "sepa_debit" to mapOf( + "iban" to "my_iban" + ) + ) + ) + + val actualParams = ConfirmSetupIntentParams.create( clientSecret = CLIENT_SECRET, paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT, - mandateData = MandateDataParamsFixtures.DEFAULT, - useStripeSdk = true + mandateData = MandateDataParamsFixtures.DEFAULT ).toParamMap() - assertEquals( - MandateDataParamsFixtures.DEFAULT.toParamMap(), - params[ConfirmStripeIntentParams.PARAM_MANDATE_DATA] + assertEquals(expectedParams, actualParams) + } + + @Test + fun create_withSepaDebitPaymentMethodParams_shouldUseMandateIdIfSpecified() { + val expectedParams = mapOf( + "client_secret" to CLIENT_SECRET, + "use_stripe_sdk" to false, + "mandate" to "mandate_123456789", + "payment_method_data" to mapOf( + "type" to "sepa_debit", + "sepa_debit" to mapOf( + "iban" to "my_iban" + ) + ) ) + val actualParams = + ConfirmSetupIntentParams.create( + clientSecret = CLIENT_SECRET, + paymentMethodCreateParams = PaymentMethodCreateParamsFixtures.DEFAULT_SEPA_DEBIT, + mandateId = "mandate_123456789" + ).toParamMap() + assertEquals(expectedParams, actualParams) } private companion object {