@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.
@@ -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 { StripeSubscriptionCheckoutAnalyticsContext } from '../../services/checkoutCompletionAnalytics.service.js';
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 autoWalletAttemptedIntentKeyRef = useRef(null);
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 (slotDisabled ||
70
- suspended ||
71
- !expressCheckoutAllowed ||
72
- walletAvailable === false ||
73
- session.activeClientSecret) {
71
+ if (!walletCheckoutStartedAfterClickIntentKey ||
72
+ walletCheckoutStartedAfterClickIntentKey !== session.intentKey ||
73
+ !session.checkoutSessionId) {
74
74
  return;
75
75
  }
76
- const requestKey = session.intentKey;
77
- if (autoWalletAttemptedIntentKeyRef.current === requestKey) {
76
+ if (!checkoutAnalytics ||
77
+ walletCheckoutStartedAfterClickSessionIdRef.current === session.checkoutSessionId) {
78
78
  return;
79
79
  }
80
- autoWalletAttemptedIntentKeyRef.current = requestKey;
81
- void (async () => {
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
- expressCheckoutAllowed,
89
- reportWalletPreparationFailure,
90
- session,
91
- slotDisabled,
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/payments",
3
- "version": "0.1.48",
3
+ "version": "0.1.49",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",