@funnelsgrove/payments 0.1.48 → 0.1.49
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/SharedStripeCheckoutDialog.d.ts +4 -1
- package/dist/components/shared/SharedStripeCheckoutDialog.js +8 -1
- package/dist/providers/stripe/WalletSubscriptionCheckoutSlot.d.ts +1 -1
- package/dist/providers/stripe/WalletSubscriptionCheckoutSlot.js +16 -21
- package/dist/testing/walletCheckoutSmoke.d.ts +1 -1
- package/dist/testing/walletCheckoutSmoke.js +22 -0
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { Stripe } from '@stripe/stripe-js';
|
|
3
|
+
import { type StripeSubscriptionCheckoutAnalyticsContext } from '../../services/checkoutCompletionAnalytics.service.js';
|
|
3
4
|
export type SharedStripeCheckoutSummaryRow = {
|
|
4
5
|
id: string;
|
|
5
6
|
label: string;
|
|
@@ -8,6 +9,8 @@ export type SharedStripeCheckoutSummaryRow = {
|
|
|
8
9
|
};
|
|
9
10
|
export type SharedStripeCheckoutDialogProps = {
|
|
10
11
|
amountCents: number;
|
|
12
|
+
checkoutAnalytics?: StripeSubscriptionCheckoutAnalyticsContext | null;
|
|
13
|
+
checkoutSessionId?: string | null;
|
|
11
14
|
clientSecret: string;
|
|
12
15
|
closeAriaLabel: string;
|
|
13
16
|
customerEmailEditable?: boolean;
|
|
@@ -41,4 +44,4 @@ export type SharedStripeCheckoutDialogProps = {
|
|
|
41
44
|
};
|
|
42
45
|
export declare function useApplePayQrFallbackAllowed(): boolean;
|
|
43
46
|
export declare function useApplePayExpressCheckoutAllowed(): boolean;
|
|
44
|
-
export declare function SharedStripeCheckoutDialog({ clientSecret, onClose, stripePromise, ...props }: SharedStripeCheckoutDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
47
|
+
export declare function SharedStripeCheckoutDialog({ checkoutAnalytics, checkoutSessionId, clientSecret, onClose, stripePromise, ...props }: SharedStripeCheckoutDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -16,6 +16,7 @@ import { CardCvcElement, CardExpiryElement, CardNumberElement, Elements, useElem
|
|
|
16
16
|
import { ApplePaySubscribeButton } from './ApplePaySubscribeButton.js';
|
|
17
17
|
import { PaymentBrandMark, SecurityLockIcon, StripeWordmark, } from './CheckoutBrandAssets.js';
|
|
18
18
|
import { StripeExpressCheckoutButton } from './StripeExpressCheckoutButton.js';
|
|
19
|
+
import { trackStripeSubscriptionCheckoutStarted, } from '../../services/checkoutCompletionAnalytics.service.js';
|
|
19
20
|
const isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
20
21
|
const defaultPaymentMethodLabels = ['Visa', 'Mastercard', 'PayPal', 'G Pay', 'Apple Pay'];
|
|
21
22
|
const normalizeBillingName = (input) => {
|
|
@@ -244,7 +245,13 @@ function SharedStripeCheckoutForm({ amountCents, clientSecret, closeAriaLabel, c
|
|
|
244
245
|
} }) })] })] })] }), fieldError ? _jsx("p", { className: 'shared-stripe-checkout-error', children: fieldError }) : null, _jsx("button", { type: 'submit', className: 'shared-stripe-checkout-submit', disabled: !canSubmit, children: submitting ? processingLabel : submitLabel }), _jsxs("div", { className: 'shared-stripe-checkout-trust', children: [_jsxs("p", { className: 'shared-stripe-checkout-secure', children: [_jsx(SecurityLockIcon, { className: 'shared-stripe-checkout-secure-icon' }), _jsx("span", { children: secureLabel })] }), _jsxs("p", { className: 'shared-stripe-checkout-powered', children: [poweredByText ? _jsx("span", { children: poweredByText }) : null, showsStripeWordmark ? (_jsx(StripeWordmark, { className: 'shared-stripe-checkout-powered-mark' })) : null] })] }), paymentMethodLabels.length > 0 ? (_jsx("div", { className: 'shared-stripe-checkout-brands', "aria-hidden": 'true', children: paymentMethodLabels.map((label) => (_jsx(PaymentBrandMark, { label: label, className: 'shared-stripe-checkout-brand' }, label))) })) : null, legalNotice ? (_jsx("div", { className: 'shared-stripe-checkout-legal', children: legalNotice })) : null, renewalNotice ? (_jsx("div", { className: 'shared-stripe-checkout-renewal', children: renewalNotice })) : null] })] }));
|
|
245
246
|
}
|
|
246
247
|
export function SharedStripeCheckoutDialog(_a) {
|
|
247
|
-
var { clientSecret, onClose, stripePromise } = _a, props = __rest(_a, ["clientSecret", "onClose", "stripePromise"]);
|
|
248
|
+
var { checkoutAnalytics, checkoutSessionId, clientSecret, onClose, stripePromise } = _a, props = __rest(_a, ["checkoutAnalytics", "checkoutSessionId", "clientSecret", "onClose", "stripePromise"]);
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
if (!checkoutAnalytics) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
void trackStripeSubscriptionCheckoutStarted(Object.assign({ checkoutSessionId }, checkoutAnalytics));
|
|
254
|
+
}, [checkoutAnalytics, checkoutSessionId, clientSecret]);
|
|
248
255
|
useEffect(() => {
|
|
249
256
|
const handleKeyDown = (event) => {
|
|
250
257
|
if (event.key === 'Escape') {
|
|
@@ -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 StripeSubscriptionCheckoutAnalyticsContext } from '../../services/checkoutCompletionAnalytics.service.js';
|
|
4
4
|
import { type StripeSubscriptionCheckoutSession } from './useStripeSubscriptionCheckoutSession.js';
|
|
5
5
|
export type WalletSubscriptionCheckoutRenderStateInput = {
|
|
6
6
|
expressCheckoutAllowed: 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 { trackStripeSubscriptionCheckoutStarted, } from '../../services/checkoutCompletionAnalytics.service.js';
|
|
5
6
|
import { isInactiveCheckoutSessionError, } from './useStripeSubscriptionCheckoutSession.js';
|
|
6
7
|
export function getWalletSubscriptionCheckoutRenderState({ expressCheckoutAllowed, hasActiveClientSecret, hasStripePromise, suspended, walletAvailable, walletPreparing, }) {
|
|
7
8
|
const shouldRenderExpressCheckout = !suspended &&
|
|
@@ -32,7 +33,8 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
32
33
|
available: null,
|
|
33
34
|
intentKey: session.intentKey,
|
|
34
35
|
});
|
|
35
|
-
const
|
|
36
|
+
const [walletCheckoutStartedAfterClickIntentKey, setWalletCheckoutStartedAfterClickIntentKey] = useState(null);
|
|
37
|
+
const walletCheckoutStartedAfterClickSessionIdRef = useRef(null);
|
|
36
38
|
const slotDisabled = disabled || !session.configured;
|
|
37
39
|
const walletAvailable = walletAvailability.intentKey === session.intentKey
|
|
38
40
|
? walletAvailability.available
|
|
@@ -66,31 +68,22 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
66
68
|
});
|
|
67
69
|
}, []);
|
|
68
70
|
useEffect(() => {
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
!
|
|
72
|
-
walletAvailable === false ||
|
|
73
|
-
session.activeClientSecret) {
|
|
71
|
+
if (!walletCheckoutStartedAfterClickIntentKey ||
|
|
72
|
+
walletCheckoutStartedAfterClickIntentKey !== session.intentKey ||
|
|
73
|
+
!session.checkoutSessionId) {
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
if (!checkoutAnalytics ||
|
|
77
|
+
walletCheckoutStartedAfterClickSessionIdRef.current === session.checkoutSessionId) {
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
|
-
|
|
81
|
-
void (
|
|
82
|
-
const readyClientSecret = await session.prepareWalletCheckout();
|
|
83
|
-
if (!readyClientSecret) {
|
|
84
|
-
reportWalletPreparationFailure(requestKey);
|
|
85
|
-
}
|
|
86
|
-
})();
|
|
80
|
+
walletCheckoutStartedAfterClickSessionIdRef.current = session.checkoutSessionId;
|
|
81
|
+
void trackStripeSubscriptionCheckoutStarted(Object.assign({ checkoutSessionId: session.checkoutSessionId }, checkoutAnalytics));
|
|
87
82
|
}, [
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
session,
|
|
91
|
-
|
|
92
|
-
suspended,
|
|
93
|
-
walletAvailable,
|
|
83
|
+
checkoutAnalytics,
|
|
84
|
+
session.checkoutSessionId,
|
|
85
|
+
session.intentKey,
|
|
86
|
+
walletCheckoutStartedAfterClickIntentKey,
|
|
94
87
|
]);
|
|
95
88
|
const handleError = (message) => {
|
|
96
89
|
if (isInactiveCheckoutSessionError(message)) {
|
|
@@ -115,8 +108,10 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, availabilityPaymen
|
|
|
115
108
|
await (onUnavailableClick === null || onUnavailableClick === void 0 ? void 0 : onUnavailableClick());
|
|
116
109
|
return;
|
|
117
110
|
}
|
|
111
|
+
setWalletCheckoutStartedAfterClickIntentKey(session.intentKey);
|
|
118
112
|
const readyClientSecret = await session.prepareWalletCheckout();
|
|
119
113
|
if (!readyClientSecret) {
|
|
114
|
+
setWalletCheckoutStartedAfterClickIntentKey(null);
|
|
120
115
|
reportWalletPreparationFailure(session.intentKey);
|
|
121
116
|
}
|
|
122
117
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type WalletCheckoutSmokeProfileId = 'mobile-safari' | 'mobile-chrome';
|
|
1
|
+
export type WalletCheckoutSmokeProfileId = 'mobile-safari' | 'mobile-chrome' | 'instagram-ios' | 'instagram-android';
|
|
2
2
|
export type WalletCheckoutSmokeProfile = {
|
|
3
3
|
id: WalletCheckoutSmokeProfileId;
|
|
4
4
|
name: string;
|
|
@@ -22,6 +22,28 @@ export function buildWalletCheckoutSmokeProfiles() {
|
|
|
22
22
|
isMobile: true,
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
|
+
{
|
|
26
|
+
id: 'instagram-ios',
|
|
27
|
+
name: 'Instagram iOS in-app browser',
|
|
28
|
+
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Instagram 333.0.0.36.109 (iPhone16,2; iOS 17_5; en_US; en-US; scale=3.00; 1290x2796; 579418012)',
|
|
29
|
+
viewport: {
|
|
30
|
+
width: 390,
|
|
31
|
+
height: 844,
|
|
32
|
+
hasTouch: true,
|
|
33
|
+
isMobile: true,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'instagram-android',
|
|
38
|
+
name: 'Instagram Android in-app browser',
|
|
39
|
+
userAgent: 'Mozilla/5.0 (Linux; Android 14; Pixel 8 Build/AP2A.240605.024; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.0.0 Mobile Safari/537.36 Instagram 333.0.0.39.92 Android (34/14; 420dpi; 1080x2400; Google/google; Pixel 8; shiba; shiba; en_US; 579418012)',
|
|
40
|
+
viewport: {
|
|
41
|
+
width: 412,
|
|
42
|
+
height: 915,
|
|
43
|
+
hasTouch: true,
|
|
44
|
+
isMobile: true,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
25
47
|
];
|
|
26
48
|
}
|
|
27
49
|
export function evaluateWalletCheckoutSmokeSnapshot(snapshot) {
|