@funnelsgrove/payments 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/shared/SharedStripeCheckoutV2Dialog.d.ts +1 -0
- package/dist/components/shared/SharedStripeCheckoutV2Dialog.js +55 -15
- package/dist/providers/stripe/WalletSubscriptionCheckoutSlot.d.ts +1 -1
- package/dist/providers/stripe/WalletSubscriptionCheckoutSlot.js +10 -1
- package/dist/providers/stripe/useStripeSubscriptionCheckoutSession.d.ts +3 -0
- package/dist/providers/stripe/useStripeSubscriptionCheckoutSession.js +45 -16
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ export type SharedStripeCheckoutV2DialogProps = {
|
|
|
21
21
|
onCustomerEmailChange?: (value: string) => void;
|
|
22
22
|
onCustomerEmailCommit?: (email: string) => Promise<string | null | void>;
|
|
23
23
|
onError?: (message: string | null) => void;
|
|
24
|
+
onInactiveCheckoutSession?: () => void;
|
|
24
25
|
onSuccess?: () => void;
|
|
25
26
|
paymentMethodLabels?: readonly string[];
|
|
26
27
|
paypalButtonLabel: string;
|
|
@@ -15,8 +15,41 @@ import { useEffect, useMemo, useState, } from 'react';
|
|
|
15
15
|
import { CheckoutProvider, PaymentElement, useCheckout, } from '@stripe/react-stripe-js/checkout';
|
|
16
16
|
import { PaymentBrandMark, SecurityLockIcon } from './CheckoutBrandAssets.js';
|
|
17
17
|
import { StripeCheckoutExpressCheckoutButton } from './StripeCheckoutExpressCheckoutButton.js';
|
|
18
|
+
import { isInactiveCheckoutSessionError } from '../../providers/stripe/useStripeSubscriptionCheckoutSession.js';
|
|
18
19
|
import { getStripeWalletPaymentMethodOrder, usePlatformWalletPaymentMethods, } from './walletPlatform.js';
|
|
19
20
|
const defaultPaymentMethodLabels = ['Visa', 'Mastercard', 'Maestro', 'Discover'];
|
|
21
|
+
const stripeCheckoutV2Appearance = {
|
|
22
|
+
labels: 'above',
|
|
23
|
+
inputs: 'spaced',
|
|
24
|
+
variables: {
|
|
25
|
+
borderRadius: '0px',
|
|
26
|
+
colorBackground: '#fff',
|
|
27
|
+
colorText: '#303136',
|
|
28
|
+
colorTextPlaceholder: '#8c909a',
|
|
29
|
+
focusBoxShadow: 'none',
|
|
30
|
+
focusOutline: 'none',
|
|
31
|
+
gridColumnSpacing: '12px',
|
|
32
|
+
gridRowSpacing: '14px',
|
|
33
|
+
spacingUnit: '5px',
|
|
34
|
+
},
|
|
35
|
+
rules: {
|
|
36
|
+
'.Input': {
|
|
37
|
+
backgroundColor: '#fff',
|
|
38
|
+
border: '0',
|
|
39
|
+
boxShadow: 'none',
|
|
40
|
+
paddingLeft: '14px',
|
|
41
|
+
paddingRight: '14px',
|
|
42
|
+
},
|
|
43
|
+
'.Input:focus': {
|
|
44
|
+
border: '0',
|
|
45
|
+
boxShadow: 'none',
|
|
46
|
+
outline: 'none',
|
|
47
|
+
},
|
|
48
|
+
'.Input--invalid': {
|
|
49
|
+
boxShadow: 'none',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
20
53
|
const isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
21
54
|
const formatCountdown = (remainingSeconds) => {
|
|
22
55
|
const normalizedSeconds = Number.isFinite(remainingSeconds)
|
|
@@ -31,7 +64,7 @@ function getFriendlyCardErrorMessage(error) {
|
|
|
31
64
|
? error.message
|
|
32
65
|
: 'Payment failed. Please review your card details and try again.';
|
|
33
66
|
}
|
|
34
|
-
function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel, closeAriaLabel, countdownLabel, customerEmail, customerEmailEditable = false, customerEmailLabel = 'Email', customerEmailPlaceholder = 'Enter your email', customerEmailInvalidMessage = 'Enter a valid email address.', customerName, discountAmountLabel, discountLabel, discountPercent, initialWalletAvailable, onClose, onCustomerEmailChange, onCustomerEmailCommit, onError, onSuccess, paymentMethodLabels = defaultPaymentMethodLabels, promoActive, processingLabel, promoCode, promoCodeLabel, remainingSeconds, returnUrl, savedLabel, secureLabel, satisfactionLabel, satisfactionPercent, summaryLabel, themeColor, title, totalLabel, totalValue, walletButtonLabel, originalPriceLabel, originalPriceValue, }) {
|
|
67
|
+
function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel, closeAriaLabel, countdownLabel, customerEmail, customerEmailEditable = false, customerEmailLabel = 'Email', customerEmailPlaceholder = 'Enter your email', customerEmailInvalidMessage = 'Enter a valid email address.', customerName, discountAmountLabel, discountLabel, discountPercent, initialWalletAvailable, onClose, onCustomerEmailChange, onCustomerEmailCommit, onError, onInactiveCheckoutSession, onSuccess, paymentMethodLabels = defaultPaymentMethodLabels, promoActive, processingLabel, promoCode, promoCodeLabel, remainingSeconds, returnUrl, savedLabel, secureLabel, satisfactionLabel, satisfactionPercent, summaryLabel, themeColor, title, totalLabel, totalValue, walletButtonLabel, originalPriceLabel, originalPriceValue, }) {
|
|
35
68
|
const checkoutState = useCheckout();
|
|
36
69
|
const walletPaymentMethods = usePlatformWalletPaymentMethods();
|
|
37
70
|
const [selectedMethod, setSelectedMethod] = useState('wallet');
|
|
@@ -112,7 +145,15 @@ function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel,
|
|
|
112
145
|
},
|
|
113
146
|
};
|
|
114
147
|
}, []);
|
|
148
|
+
const handleInactiveCheckoutSession = () => {
|
|
149
|
+
setError(null);
|
|
150
|
+
onInactiveCheckoutSession === null || onInactiveCheckoutSession === void 0 ? void 0 : onInactiveCheckoutSession();
|
|
151
|
+
};
|
|
115
152
|
const setSharedError = (message) => {
|
|
153
|
+
if (isInactiveCheckoutSessionError(message)) {
|
|
154
|
+
handleInactiveCheckoutSession();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
116
157
|
setError(message);
|
|
117
158
|
onError === null || onError === void 0 ? void 0 : onError(message);
|
|
118
159
|
};
|
|
@@ -128,11 +169,6 @@ function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel,
|
|
|
128
169
|
setSelectedMethod('card');
|
|
129
170
|
}
|
|
130
171
|
};
|
|
131
|
-
useEffect(() => {
|
|
132
|
-
if (!customerEmailEditable) {
|
|
133
|
-
setEmailDraft(initialCustomerEmail);
|
|
134
|
-
}
|
|
135
|
-
}, [customerEmailEditable, initialCustomerEmail]);
|
|
136
172
|
useEffect(() => {
|
|
137
173
|
if (effectiveSelectedMethod !== 'card' || typeof window === 'undefined') {
|
|
138
174
|
return;
|
|
@@ -184,7 +220,8 @@ function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel,
|
|
|
184
220
|
returnUrl,
|
|
185
221
|
});
|
|
186
222
|
if (result.type === 'error') {
|
|
187
|
-
|
|
223
|
+
const message = result.error.message || 'Payment failed.';
|
|
224
|
+
setSharedError(message);
|
|
188
225
|
setSubmitting(false);
|
|
189
226
|
return;
|
|
190
227
|
}
|
|
@@ -231,7 +268,7 @@ function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel,
|
|
|
231
268
|
effectiveSelectedMethod === 'card' ? 'is-visible' : '',
|
|
232
269
|
]
|
|
233
270
|
.filter(Boolean)
|
|
234
|
-
.join(' '), children: [_jsxs("div", { className: 'shared-checkout-v2-card-box', children: [_jsxs("label", { className: emailFieldClassName, children: [_jsx("span", { children: customerEmailLabel }), _jsx("input", { type: 'email', autoComplete: 'email', className: 'shared-checkout-v2-email-input', disabled: !customerEmailEditable, inputMode: 'email', readOnly: !customerEmailEditable, value: emailDraft, placeholder: customerEmailPlaceholder, onChange: (event) => {
|
|
271
|
+
.join(' '), children: [_jsxs("div", { className: 'shared-checkout-v2-card-box', children: [_jsxs("label", { className: emailFieldClassName, children: [_jsx("span", { children: customerEmailLabel }), _jsx("input", { type: 'email', autoComplete: 'email', className: 'shared-checkout-v2-email-input', disabled: !customerEmailEditable, inputMode: 'email', readOnly: !customerEmailEditable, value: customerEmailEditable ? emailDraft : initialCustomerEmail, placeholder: customerEmailPlaceholder, onChange: (event) => {
|
|
235
272
|
if (!customerEmailEditable) {
|
|
236
273
|
return;
|
|
237
274
|
}
|
|
@@ -241,6 +278,12 @@ function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel,
|
|
|
241
278
|
}
|
|
242
279
|
export function SharedStripeCheckoutV2Dialog(_a) {
|
|
243
280
|
var { clientSecret, onClose, stripePromise } = _a, props = __rest(_a, ["clientSecret", "onClose", "stripePromise"]);
|
|
281
|
+
const checkoutProviderOptions = useMemo(() => ({
|
|
282
|
+
clientSecret,
|
|
283
|
+
elementsOptions: {
|
|
284
|
+
appearance: stripeCheckoutV2Appearance,
|
|
285
|
+
},
|
|
286
|
+
}), [clientSecret]);
|
|
244
287
|
useEffect(() => {
|
|
245
288
|
const handleKeyDown = (event) => {
|
|
246
289
|
if (event.key === 'Escape') {
|
|
@@ -250,9 +293,7 @@ export function SharedStripeCheckoutV2Dialog(_a) {
|
|
|
250
293
|
window.addEventListener('keydown', handleKeyDown);
|
|
251
294
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
252
295
|
}, [onClose]);
|
|
253
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: 'shared-checkout-v2-overlay', children: _jsx("div", { className: 'shared-checkout-v2-dialog', role: 'dialog', "aria-modal": 'true', "aria-labelledby": 'shared-checkout-v2-title', children: _jsx(CheckoutProvider, { stripe: stripePromise, options: {
|
|
254
|
-
clientSecret,
|
|
255
|
-
}, children: _jsx(SharedStripeCheckoutV2Form, Object.assign({}, props, { clientSecret: clientSecret, onClose: onClose })) }) }) }), _jsx("style", { children: sharedStripeCheckoutV2Styles })] }));
|
|
296
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: 'shared-checkout-v2-overlay', children: _jsx("div", { className: 'shared-checkout-v2-dialog', role: 'dialog', "aria-modal": 'true', "aria-labelledby": 'shared-checkout-v2-title', children: _jsx(CheckoutProvider, { stripe: stripePromise, options: checkoutProviderOptions, children: _jsx(SharedStripeCheckoutV2Form, Object.assign({}, props, { clientSecret: clientSecret, onClose: onClose })) }, clientSecret) }) }), _jsx("style", { children: sharedStripeCheckoutV2Styles })] }));
|
|
256
297
|
}
|
|
257
298
|
function SharedCheckoutSpecialOfferGift({ discountLabel, imageAlt, imageSrc, }) {
|
|
258
299
|
if (imageSrc) {
|
|
@@ -648,9 +689,8 @@ const sharedStripeCheckoutV2Styles = `
|
|
|
648
689
|
.shared-checkout-v2-card-panel {
|
|
649
690
|
position: relative;
|
|
650
691
|
gap: 10px;
|
|
651
|
-
margin-bottom: 42px;
|
|
652
692
|
background: #f2f2f3;
|
|
653
|
-
padding: 16px 15px
|
|
693
|
+
padding: 16px 15px 92px;
|
|
654
694
|
}
|
|
655
695
|
|
|
656
696
|
.shared-checkout-v2-wallet-panel.is-visible,
|
|
@@ -674,9 +714,9 @@ const sharedStripeCheckoutV2Styles = `
|
|
|
674
714
|
flex-direction: column;
|
|
675
715
|
justify-content: center;
|
|
676
716
|
border: 0;
|
|
677
|
-
border-bottom: 1px solid #dadde4;
|
|
678
717
|
border-radius: 0;
|
|
679
718
|
background: #fff;
|
|
719
|
+
margin-bottom: 14px;
|
|
680
720
|
padding: 8px 14px;
|
|
681
721
|
color: #647087;
|
|
682
722
|
font-size: 14px;
|
|
@@ -773,7 +813,7 @@ const sharedStripeCheckoutV2Styles = `
|
|
|
773
813
|
.shared-checkout-v2-secure-pill--card {
|
|
774
814
|
position: absolute;
|
|
775
815
|
left: 50%;
|
|
776
|
-
bottom:
|
|
816
|
+
bottom: 16px;
|
|
777
817
|
transform: translateX(-50%);
|
|
778
818
|
white-space: nowrap;
|
|
779
819
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { AvailablePaymentMethods, StripeCheckoutExpressCheckoutElementOptions } from '@stripe/stripe-js';
|
|
3
|
-
import type
|
|
3
|
+
import { type StripeSubscriptionCheckoutSession } from './useStripeSubscriptionCheckoutSession.js';
|
|
4
4
|
type WalletPlaceholderButtonProps = {
|
|
5
5
|
className?: string;
|
|
6
6
|
disabled: boolean;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { StripeExpressCheckoutElement } from '../../components/shared/StripeExpressCheckoutElement.js';
|
|
5
|
+
import { isInactiveCheckoutSessionError, } from './useStripeSubscriptionCheckoutSession.js';
|
|
5
6
|
export function WalletSubscriptionCheckoutLoadingPlaceholder({ className, label, }) {
|
|
6
7
|
return (_jsxs("div", { className: [
|
|
7
8
|
'wallet-subscription-checkout-slot__loading',
|
|
@@ -65,6 +66,14 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
65
66
|
walletAvailable,
|
|
66
67
|
]);
|
|
67
68
|
const handleError = (message) => {
|
|
69
|
+
if (isInactiveCheckoutSessionError(message)) {
|
|
70
|
+
setWalletAvailability({
|
|
71
|
+
available: null,
|
|
72
|
+
intentKey: session.intentKey,
|
|
73
|
+
});
|
|
74
|
+
void session.restartWalletCheckout();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
68
77
|
session.setError(message);
|
|
69
78
|
onError === null || onError === void 0 ? void 0 : onError(message);
|
|
70
79
|
};
|
|
@@ -96,7 +105,7 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
96
105
|
.filter(Boolean)
|
|
97
106
|
.join(' '), "aria-busy": placeholderIsPreparing || undefined, children: [shouldRenderExpressCheckout &&
|
|
98
107
|
session.activeClientSecret &&
|
|
99
|
-
session.stripePromise ? (_jsx(StripeExpressCheckoutElement, { amountCents: amountCents, availabilityPaymentMethods: [availabilityPaymentMethod], beforeConfirm: beforeConfirm, className: className, clientSecret: session.activeClientSecret, customerEmail: customerEmail, customerName: customerName, onAvailabilityChange: handleAvailabilityChange, onError: handleError, onSuccess: onSuccess, options: options, returnUrl: returnUrl, stripePromise: session.stripePromise, summaryLabel: summaryLabel })) : null, shouldRenderPlaceholder ? (_jsx("div", { className: 'wallet-subscription-checkout-slot__placeholder', children: (renderPreparingPlaceholder !== null && renderPreparingPlaceholder !== void 0 ? renderPreparingPlaceholder : renderPlaceholder)({
|
|
108
|
+
session.stripePromise ? (_jsx(StripeExpressCheckoutElement, { amountCents: amountCents, availabilityPaymentMethods: [availabilityPaymentMethod], beforeConfirm: beforeConfirm, className: className, clientSecret: session.activeClientSecret, customerEmail: customerEmail, customerName: customerName, onAvailabilityChange: handleAvailabilityChange, onError: handleError, onSuccess: onSuccess, options: options, returnUrl: returnUrl, stripePromise: session.stripePromise, summaryLabel: summaryLabel }, session.activeClientSecret)) : null, shouldRenderPlaceholder ? (_jsx("div", { className: 'wallet-subscription-checkout-slot__placeholder', children: (renderPreparingPlaceholder !== null && renderPreparingPlaceholder !== void 0 ? renderPreparingPlaceholder : renderPlaceholder)({
|
|
100
109
|
className,
|
|
101
110
|
disabled: slotDisabled,
|
|
102
111
|
label: placeholderLabel,
|
|
@@ -25,7 +25,10 @@ export type StripeSubscriptionCheckoutSession = {
|
|
|
25
25
|
prepareWalletCheckout: () => Promise<string | null>;
|
|
26
26
|
provider: 'stripe';
|
|
27
27
|
reset: () => void;
|
|
28
|
+
restartCardCheckout: () => Promise<string | null>;
|
|
29
|
+
restartWalletCheckout: () => Promise<string | null>;
|
|
28
30
|
setError: (message: string | null) => void;
|
|
29
31
|
stripePromise: Promise<Stripe | null> | null;
|
|
30
32
|
};
|
|
33
|
+
export declare function isInactiveCheckoutSessionError(message?: string | null): boolean;
|
|
31
34
|
export declare function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, customerEmail, displayPlan, enabled, onError, plan, returnUrl, runtimeConfig, userId, }: StripeSubscriptionCheckoutSessionInput): StripeSubscriptionCheckoutSession;
|
|
@@ -9,6 +9,10 @@ const getFriendlyStripeCheckoutError = (error) => {
|
|
|
9
9
|
: message;
|
|
10
10
|
};
|
|
11
11
|
const normalizeRuntimeConfigValue = (value) => (value === null || value === void 0 ? void 0 : value.trim()) || '';
|
|
12
|
+
export function isInactiveCheckoutSessionError(message) {
|
|
13
|
+
var _a;
|
|
14
|
+
return /\bcheckout session\b.*\bno longer active\b/i.test((_a = message === null || message === void 0 ? void 0 : message.trim()) !== null && _a !== void 0 ? _a : '');
|
|
15
|
+
}
|
|
12
16
|
export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, customerEmail, displayPlan, enabled = true, onError, plan, returnUrl, runtimeConfig, userId, }) {
|
|
13
17
|
var _a, _b, _c, _d;
|
|
14
18
|
const [clientSecret, setClientSecret] = useState(null);
|
|
@@ -17,6 +21,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
17
21
|
const [loading, setLoading] = useState(createEmptyCheckoutPreparationLoading);
|
|
18
22
|
const [runtimeStripePublishableKey, setRuntimeStripePublishableKey] = useState(null);
|
|
19
23
|
const creatingIntentRef = useRef(null);
|
|
24
|
+
const requestIdRef = useRef(0);
|
|
20
25
|
const runtimeConfigSignature = [
|
|
21
26
|
normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.apiBaseUrl),
|
|
22
27
|
normalizeRuntimeConfigValue(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelId),
|
|
@@ -39,18 +44,28 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
39
44
|
].join('|');
|
|
40
45
|
const activeClientSecret = clientSecretIntentKey === intentKey ? clientSecret : null;
|
|
41
46
|
const stripePromise = useMemo(() => getStripePromise(checkoutMode, runtimeStripePublishableKey), [checkoutMode, runtimeStripePublishableKey]);
|
|
47
|
+
const clearActiveCheckoutSession = useCallback(() => {
|
|
48
|
+
requestIdRef.current += 1;
|
|
49
|
+
creatingIntentRef.current = null;
|
|
50
|
+
setClientSecret(null);
|
|
51
|
+
setClientSecretIntentKey(null);
|
|
52
|
+
}, []);
|
|
42
53
|
const setError = useCallback((message) => {
|
|
54
|
+
if (isInactiveCheckoutSessionError(message)) {
|
|
55
|
+
clearActiveCheckoutSession();
|
|
56
|
+
setErrorState(null);
|
|
57
|
+
onError === null || onError === void 0 ? void 0 : onError(null);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
43
60
|
setErrorState(message);
|
|
44
61
|
onError === null || onError === void 0 ? void 0 : onError(message);
|
|
45
|
-
}, [onError]);
|
|
62
|
+
}, [clearActiveCheckoutSession, onError]);
|
|
46
63
|
const reset = useCallback(() => {
|
|
47
|
-
|
|
48
|
-
setClientSecret(null);
|
|
49
|
-
setClientSecretIntentKey(null);
|
|
64
|
+
clearActiveCheckoutSession();
|
|
50
65
|
setLoading(createEmptyCheckoutPreparationLoading());
|
|
51
66
|
setRuntimeStripePublishableKey(null);
|
|
52
67
|
setError(null);
|
|
53
|
-
}, [setError]);
|
|
68
|
+
}, [clearActiveCheckoutSession, setError]);
|
|
54
69
|
useEffect(() => {
|
|
55
70
|
reset();
|
|
56
71
|
}, [intentKey, reset]);
|
|
@@ -59,20 +74,25 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
59
74
|
? current
|
|
60
75
|
: Object.assign(Object.assign({}, current), { [source]: value }));
|
|
61
76
|
}, []);
|
|
62
|
-
const createCheckoutSubscription = useCallback(async () => {
|
|
77
|
+
const createCheckoutSubscription = useCallback(async (forceNew = false) => {
|
|
63
78
|
var _a;
|
|
64
79
|
if (!configured || !plan || !displayPlan) {
|
|
65
80
|
return null;
|
|
66
81
|
}
|
|
67
|
-
if (activeClientSecret) {
|
|
82
|
+
if (!forceNew && activeClientSecret) {
|
|
68
83
|
return activeClientSecret;
|
|
69
84
|
}
|
|
70
|
-
if (((_a = creatingIntentRef.current) === null || _a === void 0 ? void 0 : _a.key) === intentKey) {
|
|
85
|
+
if (!forceNew && ((_a = creatingIntentRef.current) === null || _a === void 0 ? void 0 : _a.key) === intentKey) {
|
|
71
86
|
return creatingIntentRef.current.promise;
|
|
72
87
|
}
|
|
88
|
+
if (forceNew) {
|
|
89
|
+
clearActiveCheckoutSession();
|
|
90
|
+
}
|
|
73
91
|
const requestKey = intentKey;
|
|
92
|
+
const requestId = requestIdRef.current + 1;
|
|
93
|
+
requestIdRef.current = requestId;
|
|
74
94
|
const subscriptionRequest = (async () => {
|
|
75
|
-
var _a, _b, _c, _d;
|
|
95
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
76
96
|
try {
|
|
77
97
|
const response = await createStripeSubscriptionCheckout({
|
|
78
98
|
plan,
|
|
@@ -83,10 +103,11 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
83
103
|
environment: checkoutMode,
|
|
84
104
|
runtimeConfig,
|
|
85
105
|
});
|
|
86
|
-
if (((_a = creatingIntentRef.current) === null || _a === void 0 ? void 0 : _a.key) !== requestKey
|
|
106
|
+
if (((_a = creatingIntentRef.current) === null || _a === void 0 ? void 0 : _a.key) !== requestKey ||
|
|
107
|
+
((_b = creatingIntentRef.current) === null || _b === void 0 ? void 0 : _b.id) !== requestId) {
|
|
87
108
|
return response.clientSecret;
|
|
88
109
|
}
|
|
89
|
-
const publishableKey = (
|
|
110
|
+
const publishableKey = (_c = response.stripePublishableKey) === null || _c === void 0 ? void 0 : _c.trim();
|
|
90
111
|
if (publishableKey) {
|
|
91
112
|
setRuntimeStripePublishableKey(publishableKey);
|
|
92
113
|
}
|
|
@@ -95,18 +116,21 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
95
116
|
return response.clientSecret;
|
|
96
117
|
}
|
|
97
118
|
catch (subscriptionError) {
|
|
98
|
-
if (((
|
|
119
|
+
if (((_d = creatingIntentRef.current) === null || _d === void 0 ? void 0 : _d.key) === requestKey &&
|
|
120
|
+
((_e = creatingIntentRef.current) === null || _e === void 0 ? void 0 : _e.id) === requestId) {
|
|
99
121
|
setError(getFriendlyStripeCheckoutError(subscriptionError));
|
|
100
122
|
}
|
|
101
123
|
return null;
|
|
102
124
|
}
|
|
103
125
|
finally {
|
|
104
|
-
if (((
|
|
126
|
+
if (((_f = creatingIntentRef.current) === null || _f === void 0 ? void 0 : _f.key) === requestKey &&
|
|
127
|
+
((_g = creatingIntentRef.current) === null || _g === void 0 ? void 0 : _g.id) === requestId) {
|
|
105
128
|
creatingIntentRef.current = null;
|
|
106
129
|
}
|
|
107
130
|
}
|
|
108
131
|
})();
|
|
109
132
|
creatingIntentRef.current = {
|
|
133
|
+
id: requestId,
|
|
110
134
|
key: requestKey,
|
|
111
135
|
promise: subscriptionRequest,
|
|
112
136
|
};
|
|
@@ -114,6 +138,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
114
138
|
}, [
|
|
115
139
|
activeClientSecret,
|
|
116
140
|
checkoutMode,
|
|
141
|
+
clearActiveCheckoutSession,
|
|
117
142
|
configured,
|
|
118
143
|
couponId,
|
|
119
144
|
customerEmail,
|
|
@@ -125,17 +150,17 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
125
150
|
setError,
|
|
126
151
|
userId,
|
|
127
152
|
]);
|
|
128
|
-
const prepareCheckout = useCallback(async (source) => {
|
|
153
|
+
const prepareCheckout = useCallback(async (source, options = {}) => {
|
|
129
154
|
if (!configured || !plan || !displayPlan) {
|
|
130
155
|
return null;
|
|
131
156
|
}
|
|
132
|
-
if (activeClientSecret) {
|
|
157
|
+
if (!options.forceNew && activeClientSecret) {
|
|
133
158
|
return activeClientSecret;
|
|
134
159
|
}
|
|
135
160
|
setSourceLoading(source, true);
|
|
136
161
|
setError(null);
|
|
137
162
|
try {
|
|
138
|
-
return await createCheckoutSubscription();
|
|
163
|
+
return await createCheckoutSubscription(options.forceNew === true);
|
|
139
164
|
}
|
|
140
165
|
finally {
|
|
141
166
|
setSourceLoading(source, false);
|
|
@@ -151,6 +176,8 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
151
176
|
]);
|
|
152
177
|
const prepareCardCheckout = useCallback(() => prepareCheckout('card'), [prepareCheckout]);
|
|
153
178
|
const prepareWalletCheckout = useCallback(() => prepareCheckout('wallet'), [prepareCheckout]);
|
|
179
|
+
const restartCardCheckout = useCallback(() => prepareCheckout('card', { forceNew: true }), [prepareCheckout]);
|
|
180
|
+
const restartWalletCheckout = useCallback(() => prepareCheckout('wallet', { forceNew: true }), [prepareCheckout]);
|
|
154
181
|
return {
|
|
155
182
|
activeClientSecret,
|
|
156
183
|
configured,
|
|
@@ -161,6 +188,8 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
161
188
|
prepareWalletCheckout,
|
|
162
189
|
provider: 'stripe',
|
|
163
190
|
reset,
|
|
191
|
+
restartCardCheckout,
|
|
192
|
+
restartWalletCheckout,
|
|
164
193
|
setError,
|
|
165
194
|
stripePromise,
|
|
166
195
|
};
|