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 support for shipping in PaymentIntent confirmation #2238

Merged
merged 1 commit into from
Mar 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.stripe.android.PaymentAuthConfig
import com.stripe.android.PaymentIntentResult
import com.stripe.android.SetupIntentResult
import com.stripe.android.Stripe
import com.stripe.android.model.Address
import com.stripe.android.model.ConfirmPaymentIntentParams
import com.stripe.android.model.ConfirmSetupIntentParams
import com.stripe.android.model.PaymentMethodCreateParams
Expand Down Expand Up @@ -284,8 +285,21 @@ class PaymentAuthActivity : AppCompatActivity() {
.setCvc("123")
.build()
),
paymentIntentClientSecret,
RETURN_URL
clientSecret = paymentIntentClientSecret,
returnUrl = RETURN_URL,
shipping = ConfirmPaymentIntentParams.Shipping(
address = Address.Builder()
.setCity("San Francisco")
.setCountry("US")
.setLine1("123 Market St")
.setLine2("#345")
.setPostalCode("94107")
.setState("CA")
.build(),
name = "Jenny Rosen",
carrier = "Fedex",
trackingNumber = "12345"
)
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.stripe.android.model

import android.os.Parcelable
import com.stripe.android.model.ConfirmPaymentIntentParams.SetupFutureUsage
import com.stripe.android.model.ConfirmPaymentIntentParams.Shipping
import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_CLIENT_SECRET
import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_MANDATE_ID
import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_PAYMENT_METHOD_DATA
import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_PAYMENT_METHOD_ID
import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_RETURN_URL
import com.stripe.android.model.ConfirmStripeIntentParams.Companion.PARAM_USE_STRIPE_SDK
import kotlinx.android.parcel.Parcelize

data class ConfirmPaymentIntentParams internal constructor(
val paymentMethodCreateParams: PaymentMethodCreateParams? = null,
Expand Down Expand Up @@ -94,7 +97,14 @@ data class ConfirmPaymentIntentParams internal constructor(
*
* [setup_future_usage](https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-setup_future_usage)
*/
private val setupFutureUsage: SetupFutureUsage? = null
private val setupFutureUsage: SetupFutureUsage? = null,

/**
* See [Shipping]
*
* [shipping](https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-shipping)
*/
private val shipping: Shipping? = null
) : ConfirmStripeIntentParams {

fun shouldSavePaymentMethod(): Boolean {
Expand Down Expand Up @@ -133,6 +143,10 @@ data class ConfirmPaymentIntentParams internal constructor(
setupFutureUsage?.let {
mapOf(PARAM_SETUP_FUTURE_USAGE to it.code)
}.orEmpty()
).plus(
shipping?.let {
mapOf(PARAM_SHIPPING to shipping.toParamMap())
}.orEmpty()
).plus(
paymentMethodParamMap
).plus(
Expand Down Expand Up @@ -206,13 +220,81 @@ data class ConfirmPaymentIntentParams internal constructor(
OffSession("off_session")
}

/**
* Shipping information for this PaymentIntent.
*
* [shipping](https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-shipping)
*/
@Parcelize
data class Shipping @JvmOverloads constructor(
/**
* [shipping.address](https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-shipping-address)
*
* Shipping address.
*/
internal val address: Address,

/**
* [shipping.name](https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-shipping-name)
*
* Recipient name.
*/
internal val name: String,

/**
* [shipping.carrier](https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-shipping-carrier)
*
* The delivery service that shipped a physical product, such as Fedex, UPS, USPS, etc.
*/
internal val carrier: String? = null,

/**
* [shipping.phone](https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-shipping-phone)
*
* Recipient phone (including extension).
*/
internal val phone: String? = null,

/**
* [shipping.tracking_number](https://stripe.com/docs/api/payment_intents/confirm#confirm_payment_intent-shipping-tracking_number)
*
* The tracking number for a physical product, obtained from the delivery service.
* If multiple tracking numbers were generated for this purchase, please separate
* them with commas.
*/
internal val trackingNumber: String? = null
) : StripeParamsModel, Parcelable {
override fun toParamMap(): Map<String, Any> {
return listOf(
PARAM_ADDRESS to address.toParamMap(),
PARAM_NAME to name,
PARAM_CARRIER to carrier,
PARAM_PHONE to phone,
PARAM_TRACKING_NUMBER to trackingNumber
).fold(emptyMap()) { acc, (key, value) ->
acc.plus(
value?.let { mapOf(key to it) }.orEmpty()
)
}
}

private companion object {
private const val PARAM_ADDRESS = "address"
private const val PARAM_NAME = "name"
private const val PARAM_CARRIER = "carrier"
private const val PARAM_PHONE = "phone"
private const val PARAM_TRACKING_NUMBER = "tracking_number"
}
}

companion object {
const val PARAM_SOURCE_DATA: String = "source_data"

internal const val PARAM_SOURCE_ID = "source"
internal const val PARAM_SAVE_PAYMENT_METHOD = "save_payment_method"
internal const val PARAM_PAYMENT_METHOD_OPTIONS = "payment_method_options"
private const val PARAM_SETUP_FUTURE_USAGE = "setup_future_usage"
private const val PARAM_SHIPPING = "shipping"

/**
* Create a [ConfirmPaymentIntentParams] without a payment method.
Expand All @@ -222,12 +304,14 @@ data class ConfirmPaymentIntentParams internal constructor(
fun create(
clientSecret: String,
returnUrl: String? = null,
extraParams: Map<String, Any>? = null
extraParams: Map<String, Any>? = null,
shipping: Shipping? = null
): ConfirmPaymentIntentParams {
return ConfirmPaymentIntentParams(
clientSecret = clientSecret,
returnUrl = returnUrl,
extraParams = extraParams
extraParams = extraParams,
shipping = shipping
)
}

Expand All @@ -250,6 +334,7 @@ data class ConfirmPaymentIntentParams internal constructor(
* @param mandateId Optional ID of the Mandate to be used for this payment.
* @param mandateData Optional details about the Mandate to create.
* @param setupFutureUsage Optional. See [SetupFutureUsage].
* @param shipping Optional. See [Shipping].
*/
@JvmOverloads
@JvmStatic
Expand All @@ -262,7 +347,8 @@ data class ConfirmPaymentIntentParams internal constructor(
paymentMethodOptions: PaymentMethodOptionsParams? = null,
mandateId: String? = null,
mandateData: MandateDataParams? = null,
setupFutureUsage: SetupFutureUsage? = null
setupFutureUsage: SetupFutureUsage? = null,
shipping: Shipping? = null
): ConfirmPaymentIntentParams {
return ConfirmPaymentIntentParams(
clientSecret = clientSecret,
Expand All @@ -273,7 +359,8 @@ data class ConfirmPaymentIntentParams internal constructor(
paymentMethodOptions = paymentMethodOptions,
mandateId = mandateId,
mandateData = mandateData,
setupFutureUsage = setupFutureUsage
setupFutureUsage = setupFutureUsage,
shipping = shipping
)
}

Expand All @@ -295,6 +382,7 @@ data class ConfirmPaymentIntentParams internal constructor(
* @param mandateId optional ID of the Mandate to be used for this payment.
* @param mandateData optional details about the Mandate to create.
* @param setupFutureUsage Optional. See [SetupFutureUsage].
* @param shipping Optional. See [Shipping].
*/
@JvmOverloads
@JvmStatic
Expand All @@ -306,7 +394,8 @@ data class ConfirmPaymentIntentParams internal constructor(
extraParams: Map<String, Any>? = null,
mandateId: String? = null,
mandateData: MandateDataParams? = null,
setupFutureUsage: SetupFutureUsage? = null
setupFutureUsage: SetupFutureUsage? = null,
shipping: Shipping? = null
): ConfirmPaymentIntentParams {
return ConfirmPaymentIntentParams(
clientSecret = clientSecret,
Expand All @@ -316,7 +405,8 @@ data class ConfirmPaymentIntentParams internal constructor(
extraParams = extraParams,
mandateId = mandateId,
mandateData = mandateData,
setupFutureUsage = setupFutureUsage
setupFutureUsage = setupFutureUsage,
shipping = shipping
)
}

Expand All @@ -334,6 +424,7 @@ data class ConfirmPaymentIntentParams internal constructor(
* This parameter only applies to the source passed in the same request
* or the current source attached to the PaymentIntent and must be
* specified again if a new source is added.
* @param shipping Optional. See [Shipping].
*/
@JvmOverloads
@JvmStatic
Expand All @@ -342,14 +433,16 @@ data class ConfirmPaymentIntentParams internal constructor(
clientSecret: String,
returnUrl: String,
savePaymentMethod: Boolean = false,
extraParams: Map<String, Any>? = null
extraParams: Map<String, Any>? = null,
shipping: Shipping? = null
): ConfirmPaymentIntentParams {
return ConfirmPaymentIntentParams(
clientSecret = clientSecret,
sourceId = sourceId,
returnUrl = returnUrl,
savePaymentMethod = savePaymentMethod,
extraParams = extraParams
extraParams = extraParams,
shipping = shipping
)
}

Expand All @@ -365,6 +458,7 @@ data class ConfirmPaymentIntentParams internal constructor(
* This parameter only applies to the source passed in the same request
* or the current source attached to the PaymentIntent and must be
* specified again if a new source is added.
* @param shipping Optional. See [Shipping].
*/
@JvmOverloads
@JvmStatic
Expand All @@ -373,14 +467,16 @@ data class ConfirmPaymentIntentParams internal constructor(
clientSecret: String,
returnUrl: String,
savePaymentMethod: Boolean = false,
extraParams: Map<String, Any>? = null
extraParams: Map<String, Any>? = null,
shipping: Shipping? = null
): ConfirmPaymentIntentParams {
return ConfirmPaymentIntentParams(
clientSecret = clientSecret,
sourceParams = sourceParams,
returnUrl = returnUrl,
savePaymentMethod = savePaymentMethod,
extraParams = extraParams
extraParams = extraParams,
shipping = shipping
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.stripe.android.model

import com.google.common.truth.Truth.assertThat
import com.stripe.android.CardNumberFixtures.VISA_NO_SPACES
import com.stripe.android.model.ConfirmPaymentIntentParams.Companion.PARAM_PAYMENT_METHOD_OPTIONS
import com.stripe.android.model.ConfirmPaymentIntentParams.Companion.PARAM_SAVE_PAYMENT_METHOD
Expand Down Expand Up @@ -310,6 +311,39 @@ class ConfirmPaymentIntentParamsTest {
)
}

@Test
fun shipping_toParamMap_shouldReturnExpectedMap() {
val shipping = ConfirmPaymentIntentParams.Shipping(
address = Address.Builder()
.setCity("San Francisco")
.setCountry("US")
.setLine1("123 Market St")
.setLine2("#345")
.setPostalCode("94107")
.setState("CA")
.build(),
name = "Jenny Rosen",
carrier = "Fedex",
trackingNumber = "12345"
)
assertThat(shipping.toParamMap())
.isEqualTo(
mapOf(
"address" to mapOf(
"line1" to "123 Market St",
"line2" to "#345",
"city" to "San Francisco",
"state" to "CA",
"postal_code" to "94107",
"country" to "US"
),
"name" to "Jenny Rosen",
"carrier" to "Fedex",
"tracking_number" to "12345"
)
)
}

private companion object {
private val FULL_FIELDS_VISA_CARD =
Card.Builder(VISA_NO_SPACES, 12, 2050, "123")
Expand Down