@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.
@@ -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
- setSharedError(result.error.message || 'Payment failed.');
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 58px;
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: -33px;
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 { StripeSubscriptionCheckoutSession } from './useStripeSubscriptionCheckoutSession.js';
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
- creatingIntentRef.current = null;
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 = (_b = response.stripePublishableKey) === null || _b === void 0 ? void 0 : _b.trim();
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 (((_c = creatingIntentRef.current) === null || _c === void 0 ? void 0 : _c.key) === requestKey) {
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 (((_d = creatingIntentRef.current) === null || _d === void 0 ? void 0 : _d.key) === requestKey) {
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/payments",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",