Skip to content

Commit

Permalink
Add check to make sure both customerEphemeralKey and customerSessionC…
Browse files Browse the repository at this point in the history
…lientSecret are not set
  • Loading branch information
tjclawson-stripe committed Oct 3, 2024
1 parent 361df5b commit 7987b24
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class PaymentSheetFragment(
}
}

@OptIn(ExperimentalCustomerSessionApi::class)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val merchantDisplayName = arguments?.getString("merchantDisplayName").orEmpty()
Expand All @@ -64,9 +63,6 @@ class PaymentSheetFragment(
return
}
val primaryButtonLabel = arguments?.getString("primaryButtonLabel")
val customerId = arguments?.getString("customerId").orEmpty()
val customerEphemeralKeySecret = arguments?.getString("customerEphemeralKeySecret").orEmpty()
val customerSessionClientSecret = arguments?.getString("customerSessionClientSecret").orEmpty()
val googlePayConfig = buildGooglePayConfig(arguments?.getBundle("googlePay"))
val allowsDelayedPaymentMethods = arguments?.getBoolean("allowsDelayedPaymentMethods")
val billingDetailsBundle = arguments?.getBundle("defaultBillingDetails")
Expand All @@ -88,6 +84,13 @@ class PaymentSheetFragment(
return
}

val customerConfiguration = try {
buildCustomerConfiguration(arguments)
} catch (error: PaymentSheetException) {
initPromise.resolve(createError(ErrorType.Failed.toString(), error))
return
}

val shippingDetails = arguments?.getBundle("defaultShippingDetails")?.let {
AddressSheetView.buildAddressDetails(it)
}
Expand Down Expand Up @@ -192,16 +195,7 @@ class PaymentSheetFragment(
val configurationBuilder = PaymentSheet.Configuration.Builder(merchantDisplayName)
.allowsDelayedPaymentMethods(allowsDelayedPaymentMethods ?: false)
.defaultBillingDetails(defaultBillingDetails)
.customer(
if (customerId.isNotEmpty() && customerSessionClientSecret.isNotEmpty()) PaymentSheet.CustomerConfiguration.createWithCustomerSession(
id = customerId,
clientSecret = customerSessionClientSecret
)
else if (customerId.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) PaymentSheet.CustomerConfiguration(
id = customerId,
ephemeralKeySecret = customerEphemeralKeySecret
) else null
)
.customer(customerConfiguration)
.googlePay(googlePayConfig)
.appearance(appearance)
.shippingDetails(shippingDetails)
Expand Down Expand Up @@ -434,6 +428,28 @@ class PaymentSheetFragment(
)
}
}

@OptIn(ExperimentalCustomerSessionApi::class)
@Throws(PaymentSheetException::class)
private fun buildCustomerConfiguration(bundle: Bundle?): PaymentSheet.CustomerConfiguration? {
val customerId = bundle?.getString("customerId").orEmpty()
val customerEphemeralKeySecret = bundle?.getString("customerEphemeralKeySecret").orEmpty()
val customerSessionClientSecret = bundle?.getString("customerSessionClientSecret").orEmpty()
return if (customerSessionClientSecret.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) {
throw PaymentSheetException("`customerEphemeralKeySecret` and `customerSessionClientSecret` cannot both be set")
} else if (customerId.isNotEmpty() && customerSessionClientSecret.isNotEmpty()) {
PaymentSheet.CustomerConfiguration.createWithCustomerSession(
id = customerId,
clientSecret = customerSessionClientSecret
)
}
else if (customerId.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) {
PaymentSheet.CustomerConfiguration(
id = customerId,
ephemeralKeySecret = customerEphemeralKeySecret
)
} else null
}
}
}

Expand Down
11 changes: 7 additions & 4 deletions ios/StripeSdk+PaymentSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,17 @@ extension StripeSdk {
}

if let customerId = params["customerId"] as? String {
if let customerEphemeralKeySecret = params["customerEphemeralKeySecret"] as? String {
var customerEphemeralKeySecret = params["customerEphemeralKeySecret"] as? String
var customerClientSecret = params["customerSessionClientSecret"] as? String
if let customerEphemeralKeySecret, let customerClientSecret {
return(error: Errors.createError(ErrorType.Failed, "`customerEphemeralKeySecret` and `customerSessionClientSecret cannot both be set"), configuration: nil)
} else if let customerEphemeralKeySecret {
if (!Errors.isEKClientSecretValid(clientSecret: customerEphemeralKeySecret)) {
return(error: Errors.createError(ErrorType.Failed, "`customerEphemeralKeySecret` format does not match expected client secret formatting."), configuration: nil)
}
configuration.customer = .init(id: customerId, ephemeralKeySecret: customerEphemeralKeySecret)
}
else if let customerClientSecret = params["customerSessionClientSecret"] as? String {
configuration.customer = .init(id: customerId, customerSessionClientSecret: customerClientSecret)
} else if let customerClientSecret {
configuration.customer = .init(id: customerId, customerSessionClientSecret: customerClientSecret)
}
}

Expand Down
17 changes: 14 additions & 3 deletions src/types/PaymentSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ import type { FutureUsage } from './PaymentIntent';
import type { Result } from './PaymentMethod';
import type { StripeError } from './Errors';

export type SetupParams = IntentParams & {
type SetupParamsBase = IntentParams & {
/** Your customer-facing business name. On Android, this is required and cannot be an empty string. */
merchantDisplayName: string;
/** The identifier of the Stripe Customer object. See https://stripe.com/docs/api/customers/object#customer_object-id */
customerId?: string;
/** A short-lived token that allows the SDK to access a Customer’s payment methods. */
customerEphemeralKeySecret?: string;
/** When set to true, separates out the payment method selection & confirmation steps.
* If true, you must call `confirmPaymentSheetPayment` on your own. Defaults to false. */
customFlow?: boolean;
Expand Down Expand Up @@ -69,6 +67,19 @@ export type SetupParams = IntentParams & {
allowsRemovalOfLastSavedPaymentMethod?: boolean;
};

export type SetupParams =
| (SetupParamsBase & {
/** A short-lived token that allows the SDK to access a Customer’s payment methods. */
customerEphemeralKeySecret: string;
customerSessionClientSecret?: never;
})
| (SetupParamsBase & {
customerEphemeralKeySecret?: never;
/** The client secret of this Customer Session. Used on the client to set up secure access to the given customer. */
customerSessionClientSecret: string;
})
| SetupParamsBase;

export type IntentParams =
| {
paymentIntentClientSecret: string;
Expand Down

0 comments on commit 7987b24

Please sign in to comment.