Skip to content

Commit 5856963

Browse files
authored
feat: Normalize payment method data and options when passed to Stripe (medusajs#12757)
1 parent 9bdd542 commit 5856963

File tree

1 file changed

+38
-27
lines changed

1 file changed

+38
-27
lines changed

packages/modules/providers/payment-stripe/src/core/stripe-base.ts

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ import {
5151
} from "../utils/get-smallest-unit"
5252

5353
type StripeIndeterminateState = {
54-
indeterminate_due_to: string,
54+
indeterminate_due_to: string
5555
}
5656
type StripeErrorData = Stripe.PaymentIntent | StripeIndeterminateState
5757
type HandledErrorType =
58-
| { retry: true; }
59-
| { retry: false; data: StripeErrorData };
58+
| { retry: true }
59+
| { retry: false; data: StripeErrorData }
6060

6161
abstract class StripeBase extends AbstractPaymentProvider<StripeOptions> {
6262
protected readonly options_: StripeOptions
@@ -105,8 +105,15 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeOptions> {
105105
(extra?.setup_future_usage as "off_session" | "on_session" | undefined) ??
106106
this.paymentIntentOptions.setup_future_usage
107107

108-
res.payment_method_types = this.paymentIntentOptions
109-
.payment_method_types as string[]
108+
res.payment_method_types =
109+
(extra?.payment_method_types as string[]) ??
110+
(this.paymentIntentOptions.payment_method_types as string[])
111+
112+
res.payment_method_data =
113+
extra?.payment_method_data as Stripe.PaymentIntentCreateParams.PaymentMethodData
114+
115+
res.payment_method_options =
116+
extra?.payment_method_options as Stripe.PaymentIntentCreateParams.PaymentMethodOptions
110117

111118
res.automatic_payment_methods =
112119
(extra?.automatic_payment_methods as { enabled: true } | undefined) ??
@@ -125,15 +132,15 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeOptions> {
125132

126133
handleStripeError(error: any): HandledErrorType {
127134
switch (error.type) {
128-
case 'StripeCardError':
135+
case "StripeCardError":
129136
// Stripe has created a payment intent but it failed
130137
// Extract and return paymentIntent object to be stored in payment_session
131138
// Allows for reference to the failed intent and potential webhook reconciliation
132139
const stripeError = error.raw as Stripe.errors.StripeCardError
133140
if (stripeError.payment_intent) {
134141
return {
135142
retry: false,
136-
data: stripeError.payment_intent
143+
data: stripeError.payment_intent,
137144
}
138145
} else {
139146
throw this.buildError(
@@ -142,21 +149,21 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeOptions> {
142149
)
143150
}
144151

145-
case 'StripeConnectionError':
146-
case 'StripeRateLimitError':
152+
case "StripeConnectionError":
153+
case "StripeRateLimitError":
147154
// Connection or rate limit errors indicate an uncertain result
148155
// Retry the operation
149156
return {
150157
retry: true,
151158
}
152-
case 'StripeAPIError': {
159+
case "StripeAPIError": {
153160
// API errors should be treated as indeterminate per Stripe documentation
154161
// Rely on webhooks rather than assuming failure
155162
return {
156163
retry: false,
157164
data: {
158-
indeterminate_due_to: "stripe_api_error"
159-
}
165+
indeterminate_due_to: "stripe_api_error",
166+
},
160167
}
161168
}
162169
default:
@@ -177,33 +184,37 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeOptions> {
177184
currentAttempt: number = 1
178185
): Promise<T | StripeErrorData> {
179186
try {
180-
return await apiCall();
187+
return await apiCall()
181188
} catch (error) {
182189
const handledError = this.handleStripeError(error)
183190

184191
if (!handledError.retry) {
185192
// If retry is false, we know data exists per the type definition
186-
return handledError.data;
193+
return handledError.data
187194
}
188195

189-
if (
190-
handledError.retry &&
191-
currentAttempt <= maxRetries
192-
) {
196+
if (handledError.retry && currentAttempt <= maxRetries) {
193197
// Logic for retrying
194-
const delay = baseDelay * Math.pow(2, currentAttempt - 1) * (0.5 + Math.random() * 0.5);
195-
await setTimeout(delay);
196-
return this.executeWithRetry(apiCall, maxRetries, baseDelay, currentAttempt + 1);
198+
const delay =
199+
baseDelay *
200+
Math.pow(2, currentAttempt - 1) *
201+
(0.5 + Math.random() * 0.5)
202+
await setTimeout(delay)
203+
return this.executeWithRetry(
204+
apiCall,
205+
maxRetries,
206+
baseDelay,
207+
currentAttempt + 1
208+
)
197209
}
198-
// Retries are exhausted
210+
// Retries are exhausted
199211
throw this.buildError(
200212
"An error occurred in InitiatePayment during creation of stripe payment intent",
201213
error
202-
)
214+
)
203215
}
204216
}
205217

206-
207218
async getPaymentStatus({
208219
data,
209220
}: GetPaymentStatusInput): Promise<GetPaymentStatusOutput> {
@@ -262,12 +273,12 @@ abstract class StripeBase extends AbstractPaymentProvider<StripeOptions> {
262273
| string
263274
| undefined
264275

265-
const sessionData = await this.executeWithRetry<Stripe.PaymentIntent>(
266-
() => this.stripe_.paymentIntents.create(intentRequest, {
276+
const sessionData = await this.executeWithRetry<Stripe.PaymentIntent>(() =>
277+
this.stripe_.paymentIntents.create(intentRequest, {
267278
idempotencyKey: context?.idempotency_key,
268279
})
269280
)
270-
const isPaymentIntent = 'id' in sessionData;
281+
const isPaymentIntent = "id" in sessionData
271282
return {
272283
id: isPaymentIntent ? sessionData.id : (data?.session_id as string),
273284
data: sessionData as unknown as Record<string, unknown>,

0 commit comments

Comments
 (0)