@funnelsgrove/payments 0.1.17 → 0.1.19
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/ManageSubscriptionScreen.d.ts +2 -0
- package/dist/components/ManageSubscriptionScreen.js +75 -9
- package/dist/components/shared/StripeCheckoutExpressCheckoutButton.d.ts +3 -1
- package/dist/components/shared/StripeCheckoutExpressCheckoutButton.js +58 -2
- package/dist/providers/stripe/WalletSubscriptionCheckoutSlot.js +6 -1
- package/dist/providers/stripe/useStripeSubscriptionCheckoutSession.d.ts +4 -0
- package/dist/providers/stripe/useStripeSubscriptionCheckoutSession.js +67 -11
- package/dist/services/stripe.service.d.ts +14 -0
- package/dist/services/stripe.service.js +36 -0
- package/package.json +1 -1
|
@@ -22,6 +22,8 @@ type ManageSubscription = RuntimeSubscription & {
|
|
|
22
22
|
export declare function ManageSubscriptionScreen({ stepId, content, homeStepId, nodeId, plans, }: ManageSubscriptionScreenProps): import("react/jsx-runtime").JSX.Element;
|
|
23
23
|
export declare const __manageSubscriptionScreenTestables: {
|
|
24
24
|
resolveBillingDateLabel: (subscription: Pick<ManageSubscription, "cancelAtPeriodEnd" | "currentPeriodEnd" | "status">, options?: {
|
|
25
|
+
cancelled?: boolean;
|
|
25
26
|
past?: boolean;
|
|
26
27
|
}) => string;
|
|
28
|
+
resolveSubscriptionStatusLabel: (subscription: ManageSubscription) => string;
|
|
27
29
|
};
|
|
@@ -4,9 +4,13 @@ import { useEffect, useMemo, useState } from 'react';
|
|
|
4
4
|
import { apiService, buildPreviewManageSubscriptionsFallback, isPreviewFrameRuntime, runtimePublicConfig, useFunnel, } from '@funnelsgrove/runtime';
|
|
5
5
|
import { getFallbackBillingPlans } from '../services/planCatalog.service.js';
|
|
6
6
|
const pastSubscriptionsNote = 'Past subscriptions are already canceled or expired. Dates below are historical, not upcoming charges.';
|
|
7
|
+
const cancelledSubscriptionsNote = 'These subscriptions are cancelled and remain active until the date shown below.';
|
|
8
|
+
const getNormalizedStatus = (subscription) => subscription.status.trim().toLowerCase();
|
|
9
|
+
const isCancelledActiveSubscription = (subscription) => {
|
|
10
|
+
return subscription.cancelAtPeriodEnd && getNormalizedStatus(subscription) !== 'canceled';
|
|
11
|
+
};
|
|
7
12
|
const isCancellableSubscription = (subscription) => {
|
|
8
|
-
|
|
9
|
-
return normalizedStatus !== 'canceled' && !subscription.cancelAtPeriodEnd;
|
|
13
|
+
return getNormalizedStatus(subscription) !== 'canceled' && !subscription.cancelAtPeriodEnd;
|
|
10
14
|
};
|
|
11
15
|
const formatDate = (value) => {
|
|
12
16
|
if (!value) {
|
|
@@ -51,8 +55,8 @@ const resolveCreatedDate = (subscription) => {
|
|
|
51
55
|
return formatDate(subscription.createdAt || subscription.currentPeriodStart);
|
|
52
56
|
};
|
|
53
57
|
const resolveBillingDateLabel = (subscription, options = {}) => {
|
|
54
|
-
const normalizedStatus = subscription
|
|
55
|
-
if (subscription.cancelAtPeriodEnd) {
|
|
58
|
+
const normalizedStatus = getNormalizedStatus(subscription);
|
|
59
|
+
if (options.cancelled || subscription.cancelAtPeriodEnd) {
|
|
56
60
|
return `Active until: ${formatDate(subscription.currentPeriodEnd)}`;
|
|
57
61
|
}
|
|
58
62
|
if (options.past && normalizedStatus === 'canceled') {
|
|
@@ -64,6 +68,16 @@ const resolveBillingDateLabel = (subscription, options = {}) => {
|
|
|
64
68
|
return `Next charge: ${formatDate(subscription.currentPeriodEnd)}`;
|
|
65
69
|
};
|
|
66
70
|
const toManageSubscriptions = (subscriptions) => subscriptions;
|
|
71
|
+
const resolveSubscriptionStatusLabel = (subscription) => {
|
|
72
|
+
if (isCancelledActiveSubscription(subscription)) {
|
|
73
|
+
return 'Cancelled';
|
|
74
|
+
}
|
|
75
|
+
const normalizedStatus = getNormalizedStatus(subscription);
|
|
76
|
+
if (!normalizedStatus) {
|
|
77
|
+
return 'Active';
|
|
78
|
+
}
|
|
79
|
+
return `${normalizedStatus.charAt(0).toUpperCase()}${normalizedStatus.slice(1)}`;
|
|
80
|
+
};
|
|
67
81
|
export function ManageSubscriptionScreen({ stepId, content, homeStepId, nodeId, plans, }) {
|
|
68
82
|
var _a, _b;
|
|
69
83
|
const { attributes, completeStep, goToStep, setAnswer, setUser, user } = useFunnel();
|
|
@@ -114,7 +128,8 @@ export function ManageSubscriptionScreen({ stepId, content, homeStepId, nodeId,
|
|
|
114
128
|
}, [content.errorMessages.load]);
|
|
115
129
|
const subscriptions = useMemo(() => { var _a; return toManageSubscriptions((_a = data === null || data === void 0 ? void 0 : data.subscriptions) !== null && _a !== void 0 ? _a : []); }, [data]);
|
|
116
130
|
const activeSubscriptions = useMemo(() => subscriptions.filter(isCancellableSubscription), [subscriptions]);
|
|
117
|
-
const
|
|
131
|
+
const cancelledSubscriptions = useMemo(() => subscriptions.filter(isCancelledActiveSubscription), [subscriptions]);
|
|
132
|
+
const pastSubscriptions = useMemo(() => subscriptions.filter((subscription) => !isCancellableSubscription(subscription) && !isCancelledActiveSubscription(subscription)), [subscriptions]);
|
|
118
133
|
const selectedSubscription = (_a = activeSubscriptions.find((subscription) => subscription.id === selectedSubscriptionId)) !== null && _a !== void 0 ? _a : null;
|
|
119
134
|
const selectedReason = (_b = content.whyStage.reasons.find((reason) => reason.id === selectedReasonId)) !== null && _b !== void 0 ? _b : null;
|
|
120
135
|
const handleSubscriptionSelected = (subscription) => {
|
|
@@ -192,11 +207,11 @@ export function ManageSubscriptionScreen({ stepId, content, homeStepId, nodeId,
|
|
|
192
207
|
setCancelInFlight(false);
|
|
193
208
|
}
|
|
194
209
|
};
|
|
195
|
-
return (_jsxs(_Fragment, { children: [_jsxs("section", { className: 'manage-subscription', "data-node-id": nodeId || stepId, children: [stage === 'subscriptions' ? (_jsxs("div", { className: 'manage-subscription-inner', children: [_jsx("h1", { className: 'manage-subscription-title', children: content.subscriptionsStage.title }), loading ? (_jsx("p", { className: 'manage-subscription-muted', children: content.subscriptionsStage.loadingLabel })) : null, error ? _jsx("p", { className: 'manage-subscription-error', children: error }) : null, !loading && !error && subscriptions.length === 0 ? (_jsx("p", { className: 'manage-subscription-empty', children: content.subscriptionsStage.emptyLabel })) : null, !loading && activeSubscriptions.length > 0 ? (_jsx(SubscriptionSection, { title: 'Active Subscriptions', subscriptions: activeSubscriptions, plans: planList, onSelect: handleSubscriptionSelected })) : null, !loading && pastSubscriptions.length > 0 ? (_jsx(SubscriptionSection, { title: 'Past Subscriptions', subscriptions: pastSubscriptions, plans: planList, onSelect: handleSubscriptionSelected, description: pastSubscriptionsNote, past: true })) : null, _jsxs("p", { className: 'manage-subscription-support', children: [content.subscriptionsStage.supportPrefix, ' ', _jsx("a", { href: `mailto:${supportEmail}`, children: supportEmail })] })] })) : null, stage === 'why' ? (_jsxs("div", { className: 'manage-subscription-inner', children: [_jsx("h1", { className: 'manage-subscription-title is-reason', children: content.whyStage.title }), _jsx("ul", { className: 'manage-subscription-reasons', role: 'list', "aria-label": content.whyStage.reasonsAriaLabel, children: content.whyStage.reasons.map((reason) => (_jsx("li", { children: _jsxs("button", { type: 'button', className: 'manage-subscription-reason', onClick: () => handleReasonSelected(reason.id), children: [_jsx("span", { className: 'manage-subscription-reason-icon', "aria-hidden": true, children: reason.icon }), _jsx("span", { children: reason.label }), _jsx("span", { className: 'manage-subscription-reason-arrow', "aria-hidden": true, children: ">" })] }) }, reason.id))) })] })) : null, stage === 'confirm' ? (_jsxs("div", { className: 'manage-subscription-inner is-short', children: [_jsx("h1", { className: 'manage-subscription-title', children: content.confirmStage.title }), error ? _jsx("p", { className: 'manage-subscription-error', children: error }) : null, _jsx("button", { type: 'button', className: 'manage-subscription-primary', disabled: !selectedSubscription || !selectedReason || cancelInFlight, onClick: () => {
|
|
210
|
+
return (_jsxs(_Fragment, { children: [_jsxs("section", { className: 'manage-subscription', "data-node-id": nodeId || stepId, children: [stage === 'subscriptions' ? (_jsxs("div", { className: 'manage-subscription-inner', children: [_jsx("h1", { className: 'manage-subscription-title', children: content.subscriptionsStage.title }), loading ? (_jsx("p", { className: 'manage-subscription-muted', children: content.subscriptionsStage.loadingLabel })) : null, error ? _jsx("p", { className: 'manage-subscription-error', children: error }) : null, !loading && !error && subscriptions.length === 0 ? (_jsx("p", { className: 'manage-subscription-empty', children: content.subscriptionsStage.emptyLabel })) : null, !loading && activeSubscriptions.length > 0 ? (_jsx(SubscriptionSection, { title: 'Active Subscriptions', subscriptions: activeSubscriptions, plans: planList, onSelect: handleSubscriptionSelected })) : null, !loading && cancelledSubscriptions.length > 0 ? (_jsx(SubscriptionSection, { title: 'Cancelled Subscriptions', subscriptions: cancelledSubscriptions, plans: planList, onSelect: handleSubscriptionSelected, description: cancelledSubscriptionsNote, cancelled: true })) : null, !loading && pastSubscriptions.length > 0 ? (_jsx(SubscriptionSection, { title: 'Past Subscriptions', subscriptions: pastSubscriptions, plans: planList, onSelect: handleSubscriptionSelected, description: pastSubscriptionsNote, past: true })) : null, _jsxs("p", { className: 'manage-subscription-support', children: [content.subscriptionsStage.supportPrefix, ' ', _jsx("a", { href: `mailto:${supportEmail}`, children: supportEmail })] })] })) : null, stage === 'why' ? (_jsxs("div", { className: 'manage-subscription-inner', children: [_jsx("h1", { className: 'manage-subscription-title is-reason', children: content.whyStage.title }), _jsx("ul", { className: 'manage-subscription-reasons', role: 'list', "aria-label": content.whyStage.reasonsAriaLabel, children: content.whyStage.reasons.map((reason) => (_jsx("li", { children: _jsxs("button", { type: 'button', className: 'manage-subscription-reason', onClick: () => handleReasonSelected(reason.id), children: [_jsx("span", { className: 'manage-subscription-reason-icon', "aria-hidden": true, children: reason.icon }), _jsx("span", { children: reason.label }), _jsx("span", { className: 'manage-subscription-reason-arrow', "aria-hidden": true, children: ">" })] }) }, reason.id))) })] })) : null, stage === 'confirm' ? (_jsxs("div", { className: 'manage-subscription-inner is-short', children: [_jsx("h1", { className: 'manage-subscription-title', children: content.confirmStage.title }), error ? _jsx("p", { className: 'manage-subscription-error', children: error }) : null, _jsx("button", { type: 'button', className: 'manage-subscription-primary', disabled: !selectedSubscription || !selectedReason || cancelInFlight, onClick: () => {
|
|
196
211
|
void handleCancelSubscription();
|
|
197
212
|
}, children: cancelInFlight
|
|
198
213
|
? content.confirmStage.cancellingLabel
|
|
199
|
-
: content.confirmStage.cancelLabel })] })) : null, stage === 'done' ? (_jsxs("div", { className: 'manage-subscription-inner is-short', children: [_jsx("h1", { className: 'manage-subscription-title', children: content.doneStage.title }), _jsx("p", { className: 'manage-subscription-done-copy', children: content.doneStage.cancelledMessage }), cancelledActiveUntilDate ? (_jsxs("p", { className: 'manage-subscription-done-copy is-active-until', children: ["Active until: ", cancelledActiveUntilDate] })) : null, _jsx("button", { type: 'button', className: 'manage-subscription-primary', onClick: () => {
|
|
214
|
+
: content.confirmStage.cancelLabel })] })) : null, stage === 'done' ? (_jsxs("div", { className: 'manage-subscription-inner is-short', children: [_jsx("h1", { className: 'manage-subscription-title', children: content.doneStage.title }), _jsx("p", { className: 'manage-subscription-done-status', children: "Cancelled" }), _jsx("p", { className: 'manage-subscription-done-copy', children: content.doneStage.cancelledMessage }), cancelledActiveUntilDate ? (_jsxs("p", { className: 'manage-subscription-done-copy is-active-until', children: ["Active until: ", cancelledActiveUntilDate] })) : null, _jsx("button", { type: 'button', className: 'manage-subscription-primary', onClick: () => {
|
|
200
215
|
if (homeStepId) {
|
|
201
216
|
goToStep(homeStepId);
|
|
202
217
|
return;
|
|
@@ -204,8 +219,16 @@ export function ManageSubscriptionScreen({ stepId, content, homeStepId, nodeId,
|
|
|
204
219
|
setStage('subscriptions');
|
|
205
220
|
}, children: content.doneStage.returnHomeLabel })] })) : null] }), _jsx("style", { children: manageSubscriptionStyles })] }));
|
|
206
221
|
}
|
|
207
|
-
function SubscriptionSection({ title, subscriptions, plans, onSelect, description, past = false, }) {
|
|
208
|
-
|
|
222
|
+
function SubscriptionSection({ title, subscriptions, plans, onSelect, description, cancelled = false, past = false, }) {
|
|
223
|
+
const isDisabled = cancelled || past;
|
|
224
|
+
const rowClassName = cancelled
|
|
225
|
+
? 'manage-subscription-row is-cancelled'
|
|
226
|
+
: past
|
|
227
|
+
? 'manage-subscription-row is-past'
|
|
228
|
+
: 'manage-subscription-row';
|
|
229
|
+
return (_jsxs("section", { className: 'manage-subscription-section', "aria-label": title, children: [_jsx("h2", { children: title }), description ? _jsx("p", { className: 'manage-subscription-section-note', children: description }) : null, _jsx("ul", { className: 'manage-subscription-list', role: 'list', children: subscriptions.map((subscription) => (_jsx("li", { children: _jsxs("button", { type: 'button', className: rowClassName, disabled: isDisabled, onClick: () => onSelect(subscription), children: [_jsx("span", { className: 'manage-subscription-radio', "aria-hidden": true }), _jsxs("span", { className: 'manage-subscription-row-heading', children: [_jsxs("span", { className: 'manage-subscription-row-title', children: ["Subscription #", formatSubscriptionNumber(subscription)] }), _jsx("span", { className: 'manage-subscription-row-status', children: resolveSubscriptionStatusLabel(subscription) })] }), _jsx("span", { className: 'manage-subscription-row-plan', children: resolvePlanLine(subscription, plans) }), _jsxs("span", { className: 'manage-subscription-row-meta', children: [_jsx("span", { className: cancelled ? 'is-active-until' : undefined, children: cancelled
|
|
230
|
+
? resolveBillingDateLabel(subscription, { cancelled })
|
|
231
|
+
: resolveBillingDateLabel(subscription, { past }) }), _jsxs("span", { children: ["Created at: ", resolveCreatedDate(subscription)] })] })] }) }, subscription.id))) })] }));
|
|
209
232
|
}
|
|
210
233
|
const manageSubscriptionStyles = `
|
|
211
234
|
.manage-subscription {
|
|
@@ -295,6 +318,11 @@ const manageSubscriptionStyles = `
|
|
|
295
318
|
opacity: 0.82;
|
|
296
319
|
}
|
|
297
320
|
|
|
321
|
+
.manage-subscription-row.is-cancelled {
|
|
322
|
+
border-left-color: var(--color-warning, #f28100);
|
|
323
|
+
cursor: default;
|
|
324
|
+
}
|
|
325
|
+
|
|
298
326
|
.manage-subscription-radio {
|
|
299
327
|
width: 14px;
|
|
300
328
|
height: 14px;
|
|
@@ -303,12 +331,31 @@ const manageSubscriptionStyles = `
|
|
|
303
331
|
display: block;
|
|
304
332
|
}
|
|
305
333
|
|
|
334
|
+
.manage-subscription-row-heading {
|
|
335
|
+
width: 100%;
|
|
336
|
+
display: flex;
|
|
337
|
+
align-items: center;
|
|
338
|
+
justify-content: space-between;
|
|
339
|
+
gap: 8px;
|
|
340
|
+
}
|
|
341
|
+
|
|
306
342
|
.manage-subscription-row-title {
|
|
307
343
|
font-size: 15px;
|
|
308
344
|
line-height: 1.25;
|
|
309
345
|
font-weight: 800;
|
|
310
346
|
}
|
|
311
347
|
|
|
348
|
+
.manage-subscription-row-status {
|
|
349
|
+
border-radius: 999px;
|
|
350
|
+
background: color-mix(in srgb, var(--color-warning, #f28100) 16%, var(--color-surface, #fff) 84%);
|
|
351
|
+
color: var(--color-warning, #f28100);
|
|
352
|
+
padding: 3px 8px;
|
|
353
|
+
font-size: 10px;
|
|
354
|
+
line-height: 1.2;
|
|
355
|
+
font-weight: 800;
|
|
356
|
+
text-transform: uppercase;
|
|
357
|
+
}
|
|
358
|
+
|
|
312
359
|
.manage-subscription-row-plan {
|
|
313
360
|
font-size: 13px;
|
|
314
361
|
line-height: 1.2;
|
|
@@ -326,6 +373,11 @@ const manageSubscriptionStyles = `
|
|
|
326
373
|
line-height: 1.3;
|
|
327
374
|
}
|
|
328
375
|
|
|
376
|
+
.manage-subscription-row-meta .is-active-until {
|
|
377
|
+
color: var(--color-text, #262729);
|
|
378
|
+
font-weight: 800;
|
|
379
|
+
}
|
|
380
|
+
|
|
329
381
|
.manage-subscription-support {
|
|
330
382
|
margin: 30px 0 0;
|
|
331
383
|
color: var(--color-text, #262729);
|
|
@@ -371,6 +423,19 @@ const manageSubscriptionStyles = `
|
|
|
371
423
|
font-weight: 800;
|
|
372
424
|
}
|
|
373
425
|
|
|
426
|
+
.manage-subscription-done-status {
|
|
427
|
+
width: fit-content;
|
|
428
|
+
margin: 14px auto 0;
|
|
429
|
+
border-radius: 999px;
|
|
430
|
+
background: color-mix(in srgb, var(--color-warning, #f28100) 16%, var(--color-surface, #fff) 84%);
|
|
431
|
+
color: var(--color-warning, #f28100);
|
|
432
|
+
padding: 4px 10px;
|
|
433
|
+
font-size: 11px;
|
|
434
|
+
line-height: 1.2;
|
|
435
|
+
font-weight: 800;
|
|
436
|
+
text-transform: uppercase;
|
|
437
|
+
}
|
|
438
|
+
|
|
374
439
|
.manage-subscription-reasons {
|
|
375
440
|
margin: 18px 0 0;
|
|
376
441
|
padding: 0;
|
|
@@ -446,4 +511,5 @@ const manageSubscriptionStyles = `
|
|
|
446
511
|
`;
|
|
447
512
|
export const __manageSubscriptionScreenTestables = {
|
|
448
513
|
resolveBillingDateLabel,
|
|
514
|
+
resolveSubscriptionStatusLabel,
|
|
449
515
|
};
|
|
@@ -11,8 +11,10 @@ export type StripeCheckoutExpressCheckoutButtonProps = {
|
|
|
11
11
|
availabilityPaymentMethods?: readonly (keyof AvailablePaymentMethods)[];
|
|
12
12
|
initialAvailable?: boolean | null;
|
|
13
13
|
keepInitialAvailableOnReady?: boolean;
|
|
14
|
+
serverUpdateKey?: string | null;
|
|
15
|
+
onServerUpdate?: () => Promise<boolean>;
|
|
14
16
|
onAvailabilityChange?: (available: boolean) => void;
|
|
15
17
|
onError?: (message: string | null) => void;
|
|
16
18
|
onSuccess?: () => void;
|
|
17
19
|
};
|
|
18
|
-
export declare function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl, customerEmail, className, options, availabilityPaymentMethods, initialAvailable, keepInitialAvailableOnReady, onAvailabilityChange, onError, onSuccess, }: StripeCheckoutExpressCheckoutButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl, customerEmail, className, options, availabilityPaymentMethods, initialAvailable, keepInitialAvailableOnReady, serverUpdateKey, onServerUpdate, onAvailabilityChange, onError, onSuccess, }: StripeCheckoutExpressCheckoutButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo, useState } from 'react';
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { ExpressCheckoutElement, useCheckout, } from '@stripe/react-stripe-js/checkout';
|
|
5
5
|
const buildDefaultOptions = () => ({
|
|
6
6
|
buttonHeight: 55,
|
|
@@ -25,9 +25,12 @@ const buildDefaultOptions = () => ({
|
|
|
25
25
|
paypal: 'never',
|
|
26
26
|
},
|
|
27
27
|
});
|
|
28
|
-
export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl, customerEmail, className, options, availabilityPaymentMethods = ['applePay'], initialAvailable, keepInitialAvailableOnReady = false, onAvailabilityChange, onError, onSuccess, }) {
|
|
28
|
+
export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl, customerEmail, className, options, availabilityPaymentMethods = ['applePay'], initialAvailable, keepInitialAvailableOnReady = false, serverUpdateKey, onServerUpdate, onAvailabilityChange, onError, onSuccess, }) {
|
|
29
29
|
const checkoutState = useCheckout();
|
|
30
|
+
const appliedServerUpdateKeyRef = useRef('');
|
|
31
|
+
const serverUpdatePromiseRef = useRef(null);
|
|
30
32
|
const [walletAvailable, setWalletAvailable] = useState(initialAvailable !== null && initialAvailable !== void 0 ? initialAvailable : null);
|
|
33
|
+
const normalizedServerUpdateKey = (serverUpdateKey === null || serverUpdateKey === void 0 ? void 0 : serverUpdateKey.trim()) || '';
|
|
31
34
|
const effectiveWalletAvailable = initialAvailable === true && walletAvailable !== false
|
|
32
35
|
? true
|
|
33
36
|
: walletAvailable;
|
|
@@ -36,6 +39,52 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl,
|
|
|
36
39
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
37
40
|
return Object.assign(Object.assign(Object.assign({}, baseOptions), (options !== null && options !== void 0 ? options : {})), { buttonTheme: Object.assign(Object.assign({}, ((_a = baseOptions.buttonTheme) !== null && _a !== void 0 ? _a : {})), ((_b = options === null || options === void 0 ? void 0 : options.buttonTheme) !== null && _b !== void 0 ? _b : {})), buttonType: Object.assign(Object.assign({}, ((_c = baseOptions.buttonType) !== null && _c !== void 0 ? _c : {})), ((_d = options === null || options === void 0 ? void 0 : options.buttonType) !== null && _d !== void 0 ? _d : {})), layout: Object.assign(Object.assign({}, ((_e = baseOptions.layout) !== null && _e !== void 0 ? _e : {})), ((_f = options === null || options === void 0 ? void 0 : options.layout) !== null && _f !== void 0 ? _f : {})), paymentMethods: Object.assign(Object.assign({}, ((_g = baseOptions.paymentMethods) !== null && _g !== void 0 ? _g : {})), ((_h = options === null || options === void 0 ? void 0 : options.paymentMethods) !== null && _h !== void 0 ? _h : {})), paymentMethodOrder: (_j = options === null || options === void 0 ? void 0 : options.paymentMethodOrder) !== null && _j !== void 0 ? _j : baseOptions.paymentMethodOrder });
|
|
38
41
|
}, [baseOptions, options]);
|
|
42
|
+
const ensureServerUpdated = useCallback(async () => {
|
|
43
|
+
if (!normalizedServerUpdateKey) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
if (appliedServerUpdateKeyRef.current === normalizedServerUpdateKey) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
if (!onServerUpdate || checkoutState.type !== 'success') {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (serverUpdatePromiseRef.current) {
|
|
53
|
+
return serverUpdatePromiseRef.current;
|
|
54
|
+
}
|
|
55
|
+
const updatePromise = (async () => {
|
|
56
|
+
const updateResult = await checkoutState.checkout.runServerUpdate(async () => {
|
|
57
|
+
const updated = await onServerUpdate();
|
|
58
|
+
if (!updated) {
|
|
59
|
+
throw new Error('Unable to update checkout session.');
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
if (updateResult.type === 'error') {
|
|
63
|
+
onError === null || onError === void 0 ? void 0 : onError(updateResult.error.message || 'Unable to update checkout session.');
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
appliedServerUpdateKeyRef.current = normalizedServerUpdateKey;
|
|
67
|
+
onError === null || onError === void 0 ? void 0 : onError(null);
|
|
68
|
+
return true;
|
|
69
|
+
})();
|
|
70
|
+
serverUpdatePromiseRef.current = updatePromise;
|
|
71
|
+
try {
|
|
72
|
+
return await updatePromise;
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
serverUpdatePromiseRef.current = null;
|
|
76
|
+
}
|
|
77
|
+
}, [checkoutState, normalizedServerUpdateKey, onError, onServerUpdate]);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (!normalizedServerUpdateKey) {
|
|
80
|
+
appliedServerUpdateKeyRef.current = '';
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (checkoutState.type !== 'success' || !onServerUpdate) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
void ensureServerUpdated();
|
|
87
|
+
}, [checkoutState.type, ensureServerUpdated, normalizedServerUpdateKey, onServerUpdate]);
|
|
39
88
|
const handleConfirm = async (event) => {
|
|
40
89
|
if (checkoutState.type !== 'success') {
|
|
41
90
|
const message = checkoutState.type === 'error'
|
|
@@ -46,6 +95,13 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl,
|
|
|
46
95
|
return;
|
|
47
96
|
}
|
|
48
97
|
onError === null || onError === void 0 ? void 0 : onError(null);
|
|
98
|
+
const updated = await ensureServerUpdated();
|
|
99
|
+
if (!updated) {
|
|
100
|
+
const message = 'Unable to update checkout session.';
|
|
101
|
+
onError === null || onError === void 0 ? void 0 : onError(message);
|
|
102
|
+
event.paymentFailed({ reason: 'fail', message });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
49
105
|
let preparedCustomerEmail = (customerEmail === null || customerEmail === void 0 ? void 0 : customerEmail.trim()) || null;
|
|
50
106
|
if (beforeConfirm) {
|
|
51
107
|
try {
|
|
@@ -31,6 +31,11 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
31
31
|
expressCheckoutAllowed &&
|
|
32
32
|
walletAvailable === null;
|
|
33
33
|
const placeholderIsPreparing = shouldRenderPlaceholder;
|
|
34
|
+
const serverUpdateKey = session.activeClientSecret &&
|
|
35
|
+
session.checkoutSessionId &&
|
|
36
|
+
session.activePlanKey !== session.planKey
|
|
37
|
+
? session.planKey
|
|
38
|
+
: null;
|
|
34
39
|
const markWalletUnavailable = useCallback((intentKey) => {
|
|
35
40
|
setWalletAvailability({
|
|
36
41
|
available: false,
|
|
@@ -105,7 +110,7 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
105
110
|
.filter(Boolean)
|
|
106
111
|
.join(' '), "aria-busy": placeholderIsPreparing || undefined, children: [shouldRenderExpressCheckout &&
|
|
107
112
|
session.activeClientSecret &&
|
|
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
|
|
113
|
+
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, serverUpdateKey: serverUpdateKey, stripePromise: session.stripePromise, summaryLabel: summaryLabel, onServerUpdate: session.updateCheckoutSessionPlan })) : null, shouldRenderPlaceholder ? (_jsx("div", { className: 'wallet-subscription-checkout-slot__placeholder', children: (renderPreparingPlaceholder !== null && renderPreparingPlaceholder !== void 0 ? renderPreparingPlaceholder : renderPlaceholder)({
|
|
109
114
|
className,
|
|
110
115
|
disabled: slotDisabled,
|
|
111
116
|
label: placeholderLabel,
|
|
@@ -17,6 +17,8 @@ export type StripeSubscriptionCheckoutSessionInput = {
|
|
|
17
17
|
};
|
|
18
18
|
export type StripeSubscriptionCheckoutSession = {
|
|
19
19
|
activeClientSecret: string | null;
|
|
20
|
+
activePlanKey: string | null;
|
|
21
|
+
checkoutSessionId: string | null;
|
|
20
22
|
configured: boolean;
|
|
21
23
|
error: string | null;
|
|
22
24
|
intentKey: string;
|
|
@@ -27,8 +29,10 @@ export type StripeSubscriptionCheckoutSession = {
|
|
|
27
29
|
reset: () => void;
|
|
28
30
|
restartCardCheckout: () => Promise<string | null>;
|
|
29
31
|
restartWalletCheckout: () => Promise<string | null>;
|
|
32
|
+
planKey: string;
|
|
30
33
|
setError: (message: string | null) => void;
|
|
31
34
|
stripePromise: Promise<Stripe | null> | null;
|
|
35
|
+
updateCheckoutSessionPlan: () => Promise<boolean>;
|
|
32
36
|
};
|
|
33
37
|
export declare function isInactiveCheckoutSessionError(message?: string | null): boolean;
|
|
34
38
|
export declare function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, customerEmail, displayPlan, enabled, onError, plan, returnUrl, runtimeConfig, userId, }: StripeSubscriptionCheckoutSessionInput): StripeSubscriptionCheckoutSession;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
3
3
|
import { createEmptyCheckoutPreparationLoading, } from '../paymentProvider.types.js';
|
|
4
|
-
import { createStripeSubscriptionCheckout, getStripePromise, isStripeConfigured, } from '../../services/stripe.service.js';
|
|
4
|
+
import { createStripeSubscriptionCheckout, getStripePromise, isStripeConfigured, updateStripeSubscriptionCheckoutPlan, } from '../../services/stripe.service.js';
|
|
5
5
|
const getFriendlyStripeCheckoutError = (error) => {
|
|
6
6
|
const message = error instanceof Error ? error.message : 'Unable to initialize checkout';
|
|
7
7
|
return message === 'Internal server error'
|
|
@@ -14,9 +14,11 @@ export function isInactiveCheckoutSessionError(message) {
|
|
|
14
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
15
|
}
|
|
16
16
|
export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, customerEmail, displayPlan, enabled = true, onError, plan, returnUrl, runtimeConfig, userId, }) {
|
|
17
|
-
var _a, _b, _c, _d;
|
|
17
|
+
var _a, _b, _c, _d, _e;
|
|
18
18
|
const [clientSecret, setClientSecret] = useState(null);
|
|
19
19
|
const [clientSecretIntentKey, setClientSecretIntentKey] = useState(null);
|
|
20
|
+
const [checkoutSessionId, setCheckoutSessionId] = useState(null);
|
|
21
|
+
const [clientSecretPlanKey, setClientSecretPlanKey] = useState(null);
|
|
20
22
|
const [error, setErrorState] = useState(null);
|
|
21
23
|
const [loading, setLoading] = useState(createEmptyCheckoutPreparationLoading);
|
|
22
24
|
const [runtimeStripePublishableKey, setRuntimeStripePublishableKey] = useState(null);
|
|
@@ -35,20 +37,27 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
35
37
|
'stripe',
|
|
36
38
|
checkoutMode,
|
|
37
39
|
runtimeConfigSignature,
|
|
38
|
-
(_a = plan === null || plan === void 0 ? void 0 : plan.id) !== null && _a !== void 0 ? _a : '',
|
|
39
|
-
(_b = plan === null || plan === void 0 ? void 0 : plan.amountCents) !== null && _b !== void 0 ? _b : '',
|
|
40
|
-
(_c = displayPlan === null || displayPlan === void 0 ? void 0 : displayPlan.id) !== null && _c !== void 0 ? _c : '',
|
|
41
|
-
(_d = displayPlan === null || displayPlan === void 0 ? void 0 : displayPlan.amountCents) !== null && _d !== void 0 ? _d : '',
|
|
42
40
|
(couponId === null || couponId === void 0 ? void 0 : couponId.trim()) || '',
|
|
43
41
|
returnUrl.trim(),
|
|
44
42
|
].join('|');
|
|
43
|
+
const planKey = [
|
|
44
|
+
(_a = plan === null || plan === void 0 ? void 0 : plan.id) !== null && _a !== void 0 ? _a : '',
|
|
45
|
+
(_b = plan === null || plan === void 0 ? void 0 : plan.providerPlanId) !== null && _b !== void 0 ? _b : '',
|
|
46
|
+
(_c = plan === null || plan === void 0 ? void 0 : plan.amountCents) !== null && _c !== void 0 ? _c : '',
|
|
47
|
+
(_d = displayPlan === null || displayPlan === void 0 ? void 0 : displayPlan.id) !== null && _d !== void 0 ? _d : '',
|
|
48
|
+
(_e = displayPlan === null || displayPlan === void 0 ? void 0 : displayPlan.amountCents) !== null && _e !== void 0 ? _e : '',
|
|
49
|
+
].join('|');
|
|
45
50
|
const activeClientSecret = clientSecretIntentKey === intentKey ? clientSecret : null;
|
|
51
|
+
const activeCheckoutSessionId = clientSecretIntentKey === intentKey ? checkoutSessionId : null;
|
|
52
|
+
const activePlanKey = clientSecretIntentKey === intentKey ? clientSecretPlanKey : null;
|
|
46
53
|
const stripePromise = useMemo(() => getStripePromise(checkoutMode, runtimeStripePublishableKey), [checkoutMode, runtimeStripePublishableKey]);
|
|
47
54
|
const clearActiveCheckoutSession = useCallback(() => {
|
|
48
55
|
requestIdRef.current += 1;
|
|
49
56
|
creatingIntentRef.current = null;
|
|
50
57
|
setClientSecret(null);
|
|
51
58
|
setClientSecretIntentKey(null);
|
|
59
|
+
setCheckoutSessionId(null);
|
|
60
|
+
setClientSecretPlanKey(null);
|
|
52
61
|
}, []);
|
|
53
62
|
const setError = useCallback((message) => {
|
|
54
63
|
if (isInactiveCheckoutSessionError(message)) {
|
|
@@ -89,10 +98,11 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
89
98
|
clearActiveCheckoutSession();
|
|
90
99
|
}
|
|
91
100
|
const requestKey = intentKey;
|
|
101
|
+
const requestPlanKey = planKey;
|
|
92
102
|
const requestId = requestIdRef.current + 1;
|
|
93
103
|
requestIdRef.current = requestId;
|
|
94
104
|
const subscriptionRequest = (async () => {
|
|
95
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
105
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
96
106
|
try {
|
|
97
107
|
const response = await createStripeSubscriptionCheckout({
|
|
98
108
|
plan,
|
|
@@ -113,18 +123,20 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
113
123
|
}
|
|
114
124
|
setClientSecret(response.clientSecret);
|
|
115
125
|
setClientSecretIntentKey(requestKey);
|
|
126
|
+
setCheckoutSessionId(((_d = response.checkoutSessionId) === null || _d === void 0 ? void 0 : _d.trim()) || null);
|
|
127
|
+
setClientSecretPlanKey(requestPlanKey);
|
|
116
128
|
return response.clientSecret;
|
|
117
129
|
}
|
|
118
130
|
catch (subscriptionError) {
|
|
119
|
-
if (((
|
|
120
|
-
((
|
|
131
|
+
if (((_e = creatingIntentRef.current) === null || _e === void 0 ? void 0 : _e.key) === requestKey &&
|
|
132
|
+
((_f = creatingIntentRef.current) === null || _f === void 0 ? void 0 : _f.id) === requestId) {
|
|
121
133
|
setError(getFriendlyStripeCheckoutError(subscriptionError));
|
|
122
134
|
}
|
|
123
135
|
return null;
|
|
124
136
|
}
|
|
125
137
|
finally {
|
|
126
|
-
if (((
|
|
127
|
-
((
|
|
138
|
+
if (((_g = creatingIntentRef.current) === null || _g === void 0 ? void 0 : _g.key) === requestKey &&
|
|
139
|
+
((_h = creatingIntentRef.current) === null || _h === void 0 ? void 0 : _h.id) === requestId) {
|
|
128
140
|
creatingIntentRef.current = null;
|
|
129
141
|
}
|
|
130
142
|
}
|
|
@@ -145,6 +157,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
145
157
|
displayPlan,
|
|
146
158
|
intentKey,
|
|
147
159
|
plan,
|
|
160
|
+
planKey,
|
|
148
161
|
returnUrl,
|
|
149
162
|
runtimeConfig,
|
|
150
163
|
setError,
|
|
@@ -178,8 +191,49 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
178
191
|
const prepareWalletCheckout = useCallback(() => prepareCheckout('wallet'), [prepareCheckout]);
|
|
179
192
|
const restartCardCheckout = useCallback(() => prepareCheckout('card', { forceNew: true }), [prepareCheckout]);
|
|
180
193
|
const restartWalletCheckout = useCallback(() => prepareCheckout('wallet', { forceNew: true }), [prepareCheckout]);
|
|
194
|
+
const updateCheckoutSessionPlan = useCallback(async () => {
|
|
195
|
+
if (!configured || !plan || !displayPlan || !activeCheckoutSessionId) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
if (activePlanKey === planKey) {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
setError(null);
|
|
202
|
+
try {
|
|
203
|
+
await updateStripeSubscriptionCheckoutPlan({
|
|
204
|
+
checkoutSessionId: activeCheckoutSessionId,
|
|
205
|
+
plan,
|
|
206
|
+
couponId,
|
|
207
|
+
customerEmail,
|
|
208
|
+
user_id: userId,
|
|
209
|
+
environment: checkoutMode,
|
|
210
|
+
runtimeConfig,
|
|
211
|
+
});
|
|
212
|
+
setClientSecretPlanKey(planKey);
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
catch (subscriptionError) {
|
|
216
|
+
setError(getFriendlyStripeCheckoutError(subscriptionError));
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}, [
|
|
220
|
+
activeCheckoutSessionId,
|
|
221
|
+
activePlanKey,
|
|
222
|
+
checkoutMode,
|
|
223
|
+
configured,
|
|
224
|
+
couponId,
|
|
225
|
+
customerEmail,
|
|
226
|
+
displayPlan,
|
|
227
|
+
plan,
|
|
228
|
+
planKey,
|
|
229
|
+
runtimeConfig,
|
|
230
|
+
setError,
|
|
231
|
+
userId,
|
|
232
|
+
]);
|
|
181
233
|
return {
|
|
182
234
|
activeClientSecret,
|
|
235
|
+
activePlanKey,
|
|
236
|
+
checkoutSessionId: activeCheckoutSessionId,
|
|
183
237
|
configured,
|
|
184
238
|
error,
|
|
185
239
|
intentKey,
|
|
@@ -190,7 +244,9 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, couponId, c
|
|
|
190
244
|
reset,
|
|
191
245
|
restartCardCheckout,
|
|
192
246
|
restartWalletCheckout,
|
|
247
|
+
planKey,
|
|
193
248
|
setError,
|
|
194
249
|
stripePromise,
|
|
250
|
+
updateCheckoutSessionPlan,
|
|
195
251
|
};
|
|
196
252
|
}
|
|
@@ -80,7 +80,21 @@ type CreateSubscriptionCheckoutResponse = {
|
|
|
80
80
|
stripePublishableKey?: string;
|
|
81
81
|
environment?: 'test' | 'live';
|
|
82
82
|
};
|
|
83
|
+
type UpdateSubscriptionCheckoutPlanInput = {
|
|
84
|
+
checkoutSessionId: string;
|
|
85
|
+
plan: CheckoutSessionPlanInput;
|
|
86
|
+
couponId?: string | null;
|
|
87
|
+
customerEmail?: string | null;
|
|
88
|
+
user_id?: string | null;
|
|
89
|
+
environment?: RuntimeMode;
|
|
90
|
+
runtimeConfig?: StripeRuntimeConfigOverrides;
|
|
91
|
+
};
|
|
92
|
+
type UpdateSubscriptionCheckoutPlanResponse = {
|
|
93
|
+
checkoutSessionId: string;
|
|
94
|
+
environment?: 'test' | 'live';
|
|
95
|
+
};
|
|
83
96
|
export declare function createStripeSubscriptionCheckout(input: CreateSubscriptionCheckoutInput): Promise<CreateSubscriptionCheckoutResponse>;
|
|
97
|
+
export declare function updateStripeSubscriptionCheckoutPlan(input: UpdateSubscriptionCheckoutPlanInput): Promise<UpdateSubscriptionCheckoutPlanResponse>;
|
|
84
98
|
type CreateCheckoutSessionInput = {
|
|
85
99
|
plan: CheckoutSessionPlanInput;
|
|
86
100
|
successUrl: string;
|
|
@@ -588,6 +588,42 @@ export async function createStripeSubscriptionCheckout(input) {
|
|
|
588
588
|
}
|
|
589
589
|
return (await response.json());
|
|
590
590
|
}
|
|
591
|
+
export async function updateStripeSubscriptionCheckoutPlan(input) {
|
|
592
|
+
var _a, _b, _c, _d, _e;
|
|
593
|
+
const recurring = resolveCheckoutPlanRecurringConfig(input.plan);
|
|
594
|
+
if (!recurring) {
|
|
595
|
+
throw new Error('Unable to resolve the recurring interval for the selected plan');
|
|
596
|
+
}
|
|
597
|
+
const runtimeConfig = resolveStripeRuntimeConfig(input.runtimeConfig);
|
|
598
|
+
const response = await fetch(buildStripeRuntimeApiUrl('/sdk/public/payments/subscriptions/update-plan', runtimeConfig), {
|
|
599
|
+
method: 'POST',
|
|
600
|
+
headers: buildStripeRuntimeHeaders(runtimeConfig, {
|
|
601
|
+
'Content-Type': 'application/json',
|
|
602
|
+
}),
|
|
603
|
+
body: JSON.stringify({
|
|
604
|
+
publishableKey: runtimeConfig.funnelSdkPublishableKey || undefined,
|
|
605
|
+
funnelId: runtimeConfig.funnelId || undefined,
|
|
606
|
+
funnelVersionId: runtimeConfig.funnelVersionId || undefined,
|
|
607
|
+
checkoutSessionId: input.checkoutSessionId.trim(),
|
|
608
|
+
planId: getPaywallPlanSelectionValue(input.plan),
|
|
609
|
+
providerPlanId: ((_a = input.plan.providerPlanId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
610
|
+
title: input.plan.title,
|
|
611
|
+
description: ((_b = input.plan.description) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
612
|
+
amountCents: input.plan.amountCents,
|
|
613
|
+
billingInterval: recurring.interval,
|
|
614
|
+
billingIntervalCount: recurring.intervalCount,
|
|
615
|
+
couponId: ((_c = input.couponId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
616
|
+
customerEmail: ((_d = input.customerEmail) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
617
|
+
user_id: ((_e = input.user_id) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
618
|
+
environment: input.environment || undefined,
|
|
619
|
+
}),
|
|
620
|
+
});
|
|
621
|
+
if (!response.ok) {
|
|
622
|
+
const errorMessage = await parseErrorMessage(response, 'Unable to update subscription checkout');
|
|
623
|
+
throw new Error(errorMessage);
|
|
624
|
+
}
|
|
625
|
+
return (await response.json());
|
|
626
|
+
}
|
|
591
627
|
export async function createStripeCheckoutSession(input) {
|
|
592
628
|
var _a, _b, _c, _d, _e;
|
|
593
629
|
const recurring = resolveCheckoutPlanRecurringConfig(input.plan);
|