Skip to content

Commit 9d77555

Browse files
committed
fix(payments-next): Coupon updates cause Stripe Element state loss
Because: * Updating a coupon would cause rerenders of the stripe PaymentElement in the case of the PaymentElement representing an existing payment method with expired card data * We create a new client session each time a cart is fetched, and when we apply a coupon, the route is revalidated. This causes the cart to be refetched. * The front end passes this updated client session secret key to the Elements wrapper, which triggers a refresh of the PaymentElement this commit: * Adds in an explicit key to ensure that changing carts in-browser always changes the stripe session * Preserves the initial client session secret key on the front end for use in the Stripe Elements component, preventing unnecessary rerenders * Uses a minimally-invasive approach to resolving this issue, as the issue could not be replicated locally. Stripe tooling around expired cards is not working as intended. Closes #PAY-3157
1 parent 898f8cc commit 9d77555

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

libs/payments/ui/src/lib/client/components/StripeWrapper.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ interface StripeWrapperProps {
106106
amount: number;
107107
currency: string;
108108
cart: {
109+
id: string;
109110
paymentInfo?: {
110111
type:
111112
| Stripe.PaymentMethod.Type
@@ -133,6 +134,11 @@ export function StripeWrapper({
133134
const config = useContext(ConfigContext);
134135
const [stripePromise] = useState(() => loadStripe(config.stripePublicApiKey));
135136

137+
// Re-use initial session secret to prevent unnecessary Stripe Elements remounts
138+
const [initialSessionSecret] = useState(
139+
cart.paymentInfo?.customerSessionClientSecret
140+
);
141+
136142
const normalizedCurrency = currency.toLowerCase();
137143
const minCharge = STRIPE_MINIMUM_CHARGE_AMOUNTS[normalizedCurrency];
138144
const isBelowMin = amount < minCharge;
@@ -144,7 +150,7 @@ export function StripeWrapper({
144150
amount: isBelowMin ? undefined : amount,
145151
currency: normalizedCurrency,
146152
externalPaymentMethodTypes: ['external_paypal'],
147-
customerSessionClientSecret: cart.paymentInfo?.customerSessionClientSecret,
153+
customerSessionClientSecret: initialSessionSecret,
148154
};
149155

150156
// Remove external_paypal if the customer has an active subscription
@@ -158,7 +164,7 @@ export function StripeWrapper({
158164
}
159165

160166
return (
161-
<Elements stripe={stripePromise} options={options}>
167+
<Elements stripe={stripePromise} options={options} key={cart.id}>
162168
{children}
163169
</Elements>
164170
);

0 commit comments

Comments
 (0)