@funnelsgrove/payments 0.1.24 → 0.1.26

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.
@@ -217,10 +217,7 @@ function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel,
217
217
  setSubmitting(false);
218
218
  return;
219
219
  }
220
- const result = await checkoutState.checkout.confirm({
221
- email: syncedEmail || undefined,
222
- redirect: 'if_required',
223
- });
220
+ const result = await checkoutState.checkout.confirm(Object.assign(Object.assign({}, (customerEmailEditable ? { email: syncedEmail || undefined } : {})), { redirect: 'if_required' }));
224
221
  if (result.type === 'error') {
225
222
  const message = result.error.message || 'Payment failed.';
226
223
  setSharedError(message);
@@ -260,7 +257,7 @@ function SharedStripeCheckoutV2Form({ amountCents, buttonColor, cardSubmitLabel,
260
257
  effectiveSelectedMethod === 'wallet' ? 'is-visible' : '',
261
258
  ]
262
259
  .filter(Boolean)
263
- .join(' '), children: [_jsxs("p", { className: 'shared-checkout-v2-secure-pill', children: [_jsx(SecurityLockIcon, { className: 'shared-checkout-v2-secure-pill-icon' }), secureLabel] }), _jsxs("div", { className: 'shared-checkout-v2-wallet-shell', "aria-label": walletAriaLabel, children: [_jsx(StripeCheckoutExpressCheckoutButton, { amountCents: amountCents, availabilityPaymentMethods: walletPaymentMethods, beforeConfirm: ensureCustomerEmail, className: 'shared-checkout-v2-express-buttons', customerEmail: resolvedCustomerEmail, customerName: customerName, initialAvailable: initialWalletAvailable, keepInitialAvailableOnReady: initialWalletAvailable === true, onAvailabilityChange: handleWalletAvailabilityChange, onError: setSharedError, onSuccess: onSuccess, options: expressCheckoutOptions, returnUrl: returnUrl, summaryLabel: expressCheckoutSummaryLabel }), _jsx("span", { className: 'shared-checkout-v2-sr-only', children: walletAriaLabel })] })] }), _jsxs("div", { hidden: effectiveSelectedMethod !== 'card', className: [
260
+ .join(' '), children: [_jsxs("p", { className: 'shared-checkout-v2-secure-pill', children: [_jsx(SecurityLockIcon, { className: 'shared-checkout-v2-secure-pill-icon' }), secureLabel] }), _jsxs("div", { className: 'shared-checkout-v2-wallet-shell', "aria-label": walletAriaLabel, children: [_jsx(StripeCheckoutExpressCheckoutButton, { amountCents: amountCents, availabilityPaymentMethods: walletPaymentMethods, beforeConfirm: ensureCustomerEmail, className: 'shared-checkout-v2-express-buttons', confirmEmail: customerEmailEditable, customerEmail: resolvedCustomerEmail, customerName: customerName, initialAvailable: initialWalletAvailable, keepInitialAvailableOnReady: initialWalletAvailable === true, onAvailabilityChange: handleWalletAvailabilityChange, onError: setSharedError, onSuccess: onSuccess, options: expressCheckoutOptions, returnUrl: returnUrl, summaryLabel: expressCheckoutSummaryLabel }), _jsx("span", { className: 'shared-checkout-v2-sr-only', children: walletAriaLabel })] })] }), _jsxs("div", { hidden: effectiveSelectedMethod !== 'card', className: [
264
261
  'shared-checkout-v2-card-panel',
265
262
  effectiveSelectedMethod === 'card' ? 'is-visible' : '',
266
263
  ]
@@ -4,6 +4,7 @@ export type StripeCheckoutExpressCheckoutButtonProps = {
4
4
  beforeConfirm?: () => Promise<string | null>;
5
5
  summaryLabel: string;
6
6
  returnUrl: string;
7
+ confirmEmail?: boolean;
7
8
  customerEmail?: string | null;
8
9
  customerName?: string | null;
9
10
  className?: string;
@@ -17,4 +18,4 @@ export type StripeCheckoutExpressCheckoutButtonProps = {
17
18
  onError?: (message: string | null) => void;
18
19
  onSuccess?: () => void | Promise<void>;
19
20
  };
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;
21
+ export declare function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl, confirmEmail, customerEmail, className, options, availabilityPaymentMethods, initialAvailable, keepInitialAvailableOnReady, serverUpdateKey, onServerUpdate, onAvailabilityChange, onError, onSuccess, }: StripeCheckoutExpressCheckoutButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -25,7 +25,7 @@ const buildDefaultOptions = () => ({
25
25
  paypal: 'never',
26
26
  },
27
27
  });
28
- export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl, customerEmail, className, options, availabilityPaymentMethods = ['applePay'], initialAvailable, keepInitialAvailableOnReady = false, serverUpdateKey, onServerUpdate, onAvailabilityChange, onError, onSuccess, }) {
28
+ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl, confirmEmail = true, customerEmail, className, options, availabilityPaymentMethods = ['applePay'], initialAvailable, keepInitialAvailableOnReady = false, serverUpdateKey, onServerUpdate, onAvailabilityChange, onError, onSuccess, }) {
29
29
  const checkoutState = useCheckout();
30
30
  const appliedServerUpdateKeyRef = useRef('');
31
31
  const serverUpdatePromiseRef = useRef(null);
@@ -122,11 +122,9 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, returnUrl,
122
122
  event.paymentFailed({ reason: 'invalid_payment_data', message });
123
123
  return;
124
124
  }
125
- const result = await checkoutState.checkout.confirm({
126
- email: preparedCustomerEmail || (customerEmail === null || customerEmail === void 0 ? void 0 : customerEmail.trim()) || undefined,
127
- expressCheckoutConfirmEvent: event,
128
- redirect: 'if_required',
129
- });
125
+ const result = await checkoutState.checkout.confirm(Object.assign(Object.assign({}, (confirmEmail
126
+ ? { email: preparedCustomerEmail || (customerEmail === null || customerEmail === void 0 ? void 0 : customerEmail.trim()) || undefined }
127
+ : {})), { expressCheckoutConfirmEvent: event, redirect: 'if_required' }));
130
128
  if (result.type === 'error') {
131
129
  const message = result.error.message || 'Wallet checkout failed.';
132
130
  onError === null || onError === void 0 ? void 0 : onError(message);
@@ -527,12 +527,50 @@ export const resolveCheckoutPlanRecurringConfig = (plan) => {
527
527
  inferCheckoutPlanRecurringFromText(plan.id) ||
528
528
  inferCheckoutPlanRecurringFromText(plan.description));
529
529
  };
530
- const normalizeAnalyticsMetadata = (metadata) => {
531
- if (!metadata || !isRecord(metadata)) {
530
+ const SENSITIVE_CHECKOUT_URL_QUERY_KEYS = new Set([
531
+ 'customeremail',
532
+ 'customer_email',
533
+ 'email',
534
+ 'fullname',
535
+ 'full_name',
536
+ 'name',
537
+ 'phone',
538
+ 'phonenumber',
539
+ 'phone_number',
540
+ ]);
541
+ const sanitizeCheckoutUrl = (value) => {
542
+ if (typeof value !== 'string') {
543
+ return undefined;
544
+ }
545
+ const trimmed = value.trim();
546
+ if (!trimmed) {
532
547
  return undefined;
533
548
  }
534
- const normalized = Object.fromEntries(Object.entries(metadata).filter(([, value]) => value !== undefined && value !== null && value !== ''));
535
- return Object.keys(normalized).length > 0 ? normalized : undefined;
549
+ try {
550
+ const parsed = new URL(trimmed, typeof window !== 'undefined' ? window.location.origin : 'https://example.invalid');
551
+ for (const key of Array.from(parsed.searchParams.keys())) {
552
+ if (SENSITIVE_CHECKOUT_URL_QUERY_KEYS.has(key.trim().toLowerCase())) {
553
+ parsed.searchParams.delete(key);
554
+ }
555
+ }
556
+ return parsed.toString();
557
+ }
558
+ catch (_a) {
559
+ return trimmed;
560
+ }
561
+ };
562
+ const currentCheckoutUrl = () => {
563
+ var _a;
564
+ if (typeof window === 'undefined') {
565
+ return undefined;
566
+ }
567
+ return sanitizeCheckoutUrl((_a = window.location) === null || _a === void 0 ? void 0 : _a.href);
568
+ };
569
+ const normalizeAnalyticsMetadata = (metadata) => {
570
+ const normalized = Object.fromEntries(Object.entries(isRecord(metadata) ? metadata : {}).filter(([, value]) => value !== undefined && value !== null && value !== ''));
571
+ const checkoutUrl = sanitizeCheckoutUrl(normalized.url) || currentCheckoutUrl();
572
+ const withCheckoutUrl = checkoutUrl ? Object.assign(Object.assign({}, normalized), { url: checkoutUrl }) : normalized;
573
+ return Object.keys(withCheckoutUrl).length > 0 ? withCheckoutUrl : undefined;
536
574
  };
537
575
  export async function createStripePaymentIntent(input) {
538
576
  var _a, _b;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/payments",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",