@funnelsgrove/payments 0.1.59 → 0.3.0

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/README.md CHANGED
@@ -87,8 +87,9 @@ When a live funnel still uses one of these, migrate the funnel deliberately with
87
87
  - Keep provider-specific implementation under `src/providers/<provider>`.
88
88
  - Stripe owns real card fields and wallet controls. Local wallet buttons are placeholders until Stripe confirms availability.
89
89
  - Wallet unavailable state must fall back to card/manual checkout or disappear.
90
- - Do not count checkout intent until the visitor taps or confirms a visible checkout CTA.
91
- - Wallet slots may create render-only Checkout Sessions on mount so Apple Pay and Google Pay render before the visitor taps. These sessions must use `checkoutStartSource: 'wallet_render'`; trusted server `checkout_started` analytics ignores that source.
90
+ - Count `checkout_started` only at shared UI boundaries: when a shared card dialog opens or when Stripe reports an Apple Pay / Google Pay button click.
91
+ - Wallet slots may create render-only Checkout Sessions on mount so Apple Pay and Google Pay render before the visitor taps. Session creation is technical preparation and must never emit `checkout_started`.
92
+ - Shared checkout analytics deduplicates `checkout_started` by Checkout Session id. Card submit and wallet confirmation must not emit it again.
92
93
  - Funnel paywalls should style wallet buttons through the shared slot API: `className` for the Stripe button/placeholder, `slotClassName` for the outer slot, `appearance` for Stripe Elements appearance, and `options` for Stripe Express Checkout options.
93
94
  - Keep discount math reusable here, but keep offer activation timing in funnel code.
94
95
  - Checkout metadata must avoid sensitive raw query params and use `@funnelsgrove/analytics` metadata helpers.
@@ -191,9 +191,6 @@ function SharedStripeCheckoutForm({ amountCents, checkoutAnalytics, checkoutSess
191
191
  setSubmitting(false);
192
192
  return;
193
193
  }
194
- if (checkoutAnalytics) {
195
- queueStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId, paymentMethod: 'card' }));
196
- }
197
194
  const result = await stripe.confirmCardPayment(clientSecret, {
198
195
  payment_method: {
199
196
  card: cardNumberElement,
@@ -249,6 +246,12 @@ function SharedStripeCheckoutForm({ amountCents, checkoutAnalytics, checkoutSess
249
246
  }
250
247
  export function SharedStripeCheckoutDialog(_a) {
251
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
+ queueStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId, checkoutStartSource: 'card_form_open', paymentMethod: 'card' }));
254
+ }, [checkoutAnalytics, checkoutSessionId]);
252
255
  useEffect(() => {
253
256
  const handleKeyDown = (event) => {
254
257
  if (event.key === 'Escape') {
@@ -250,9 +250,6 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
250
250
  setSubmitting(false);
251
251
  return;
252
252
  }
253
- if (checkoutAnalytics) {
254
- queueStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId, paymentMethod: 'card' }));
255
- }
256
253
  await (onPaymentInfoSubmitted === null || onPaymentInfoSubmitted === void 0 ? void 0 : onPaymentInfoSubmitted());
257
254
  const result = await checkoutState.checkout.confirm({
258
255
  redirect: 'if_required',
@@ -330,6 +327,12 @@ export function SharedStripeCheckoutV2Dialog(_a) {
330
327
  var { checkoutAnalytics, checkoutSessionId, clientSecret, onClose, stripePromise, supportedCountries } = _a, props = __rest(_a, ["checkoutAnalytics", "checkoutSessionId", "clientSecret", "onClose", "stripePromise", "supportedCountries"]);
331
328
  const normalizedSupportedCountries = useMemo(() => normalizeSupportedCheckoutCountries(supportedCountries), [supportedCountries]);
332
329
  const fixedBillingCountry = getFixedSupportedBillingCountry(normalizedSupportedCountries);
330
+ useEffect(() => {
331
+ if (!checkoutAnalytics) {
332
+ return;
333
+ }
334
+ queueStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId, checkoutStartSource: 'card_form_open', paymentMethod: 'card' }));
335
+ }, [checkoutAnalytics, checkoutSessionId]);
333
336
  useEffect(() => {
334
337
  const handleKeyDown = (event) => {
335
338
  if (event.key === 'Escape') {
@@ -123,9 +123,6 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, checkoutAna
123
123
  event.paymentFailed({ reason: 'fail', message });
124
124
  return;
125
125
  }
126
- if (checkoutAnalytics) {
127
- queueStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId, paymentMethod: event.expressPaymentType }));
128
- }
129
126
  let preparedCustomerEmail = (customerEmail === null || customerEmail === void 0 ? void 0 : customerEmail.trim()) || null;
130
127
  if (beforeConfirm) {
131
128
  try {
@@ -162,13 +159,19 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, checkoutAna
162
159
  window.location.assign(returnUrl);
163
160
  }
164
161
  };
162
+ const handleClick = (event) => {
163
+ if (checkoutAnalytics) {
164
+ queueStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId, checkoutStartSource: 'wallet_click', paymentMethod: event.expressPaymentType }));
165
+ }
166
+ event.resolve();
167
+ };
165
168
  return (_jsxs(_Fragment, { children: [_jsx("div", { className: [
166
169
  'stripe-express-checkout-button',
167
170
  className !== null && className !== void 0 ? className : '',
168
171
  effectiveWalletAvailable === false ? 'is-hidden' : '',
169
172
  ]
170
173
  .filter(Boolean)
171
- .join(' '), children: _jsx(ExpressCheckoutElementWithCancel, { options: resolvedOptions, onCancel: onCancel, onConfirm: (event) => void handleConfirm(event), onLoadError: ({ error }) => {
174
+ .join(' '), children: _jsx(ExpressCheckoutElementWithCancel, { options: resolvedOptions, onCancel: onCancel, onClick: handleClick, onConfirm: (event) => void handleConfirm(event), onLoadError: ({ error }) => {
172
175
  setWalletAvailable(false);
173
176
  onAvailabilityChange === null || onAvailabilityChange === void 0 ? void 0 : onAvailabilityChange(false);
174
177
  onError === null || onError === void 0 ? void 0 : onError(error.message || 'Unable to load wallet checkout.');
@@ -78,9 +78,6 @@ export function StripeExpressCheckoutButton({ amountCents, beforeConfirm, checko
78
78
  return;
79
79
  }
80
80
  onError === null || onError === void 0 ? void 0 : onError(null);
81
- if (checkoutAnalytics) {
82
- queueStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId, paymentMethod: event.expressPaymentType }));
83
- }
84
81
  let preparedCustomerEmail = (customerEmail === null || customerEmail === void 0 ? void 0 : customerEmail.trim()) || null;
85
82
  if (beforeConfirm) {
86
83
  try {
@@ -138,13 +135,19 @@ export function StripeExpressCheckoutButton({ amountCents, beforeConfirm, checko
138
135
  window.location.assign(returnUrl);
139
136
  }
140
137
  };
138
+ const handleClick = (event) => {
139
+ if (checkoutAnalytics) {
140
+ queueStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId, checkoutStartSource: 'wallet_click', paymentMethod: event.expressPaymentType }));
141
+ }
142
+ event.resolve();
143
+ };
141
144
  return (_jsxs(_Fragment, { children: [_jsx("div", { className: [
142
145
  'stripe-express-checkout-button',
143
146
  className !== null && className !== void 0 ? className : '',
144
147
  effectiveWalletAvailable === false ? 'is-hidden' : '',
145
148
  ]
146
149
  .filter(Boolean)
147
- .join(' '), children: _jsx(ExpressCheckoutElement, { options: resolvedOptions, onCancel: onCancel, onConfirm: (event) => void handleConfirm(event), onLoadError: ({ error }) => {
150
+ .join(' '), children: _jsx(ExpressCheckoutElement, { options: resolvedOptions, onCancel: onCancel, onClick: handleClick, onConfirm: (event) => void handleConfirm(event), onLoadError: ({ error }) => {
148
151
  setWalletAvailable(false);
149
152
  onAvailabilityChange === null || onAvailabilityChange === void 0 ? void 0 : onAvailabilityChange(false);
150
153
  onError === null || onError === void 0 ? void 0 : onError(error.message || 'Unable to load wallet checkout.');
@@ -6,6 +6,7 @@ export type BillingPlanComparison = {
6
6
  };
7
7
  export type BillingPlanInterval = 'day' | 'week' | 'month' | 'year';
8
8
  export type BillingPlanConfig = {
9
+ offerSetId?: string;
9
10
  offerSetKey?: string;
10
11
  projectPlanId: string;
11
12
  title: string;
@@ -36,6 +37,8 @@ export type BillingFallbackPlanConfig = BillingPlanConfig & {
36
37
  export type BillingPlanCatalog = Record<string, BillingFallbackPlanConfig>;
37
38
  export type BillingPlanMappingConfig = {
38
39
  projectPlanId: string;
40
+ offerSetId?: string;
41
+ offerSetKey?: string;
39
42
  };
40
43
  export type BillingPlanMappingCatalog = Record<string, BillingPlanMappingConfig>;
41
44
  export type BillingPlanInputCatalog = BillingPlanCatalog | BillingPlanMappingCatalog;
@@ -121,7 +121,7 @@ export function WalletSubscriptionCheckoutSlot({ amountCents, appearance, availa
121
121
  return;
122
122
  }
123
123
  walletCheckoutStartedAfterClickSessionIdRef.current = session.checkoutSessionId;
124
- void trackStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId: session.checkoutSessionId, paymentMethod: analyticsPaymentMethod }));
124
+ void trackStripeSubscriptionCheckoutStarted(Object.assign(Object.assign({}, checkoutAnalytics), { checkoutSessionId: session.checkoutSessionId, checkoutStartSource: 'wallet_click', paymentMethod: analyticsPaymentMethod }));
125
125
  }, [
126
126
  analyticsPaymentMethod,
127
127
  checkoutAnalytics,
@@ -12,6 +12,7 @@ export type StripeSubscriptionCheckoutAnalyticsContext = {
12
12
  };
13
13
  export type TrackStripeSubscriptionCheckoutStartedInput = StripeSubscriptionCheckoutAnalyticsContext & {
14
14
  checkoutSessionId?: string | null;
15
+ checkoutStartSource?: 'card_form_open' | 'wallet_click';
15
16
  paymentMethod?: unknown;
16
17
  };
17
18
  export type TrackPaidStripeSubscriptionCheckoutCompletedInput = StripeSubscriptionCheckoutAnalyticsContext & {
@@ -70,7 +70,12 @@ export async function trackStripeSubscriptionCheckoutStarted(input) {
70
70
  stepName: input.stepName,
71
71
  stepType: input.stepType,
72
72
  stepContractVersion: input.stepContractVersion,
73
- metadata: Object.assign(Object.assign(Object.assign({}, metadata), { checkoutSessionId, checkout_session_id: checkoutSessionId, environment: input.environment || metadata.environment, payment_provider: 'stripe' }), (paymentMethod ? { payment_method: paymentMethod } : {})),
73
+ metadata: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, metadata), { checkoutSessionId, checkout_session_id: checkoutSessionId }), (input.checkoutStartSource
74
+ ? {
75
+ checkoutStartSource: input.checkoutStartSource,
76
+ checkout_start_source: input.checkoutStartSource,
77
+ }
78
+ : {})), { environment: input.environment || metadata.environment, payment_provider: 'stripe' }), (paymentMethod ? { payment_method: paymentMethod } : {})),
74
79
  };
75
80
  const eventId = publicAnalyticsSdk.trackCheckoutStarted(conversionInput);
76
81
  if (!eventId) {
@@ -2,6 +2,8 @@ import type { BillingFallbackPlanConfig, BillingPlanCatalog, BillingPlanMappingC
2
2
  export type RemoteProjectBillingPlan = {
3
3
  id: string;
4
4
  key: string;
5
+ offerSetId?: string;
6
+ offerSetKey?: string;
5
7
  projectPlanId: string | null;
6
8
  providerPlanId: string;
7
9
  displayName: string | null;
@@ -5,7 +5,11 @@ const isBillingPlanMappingConfig = (value) => {
5
5
  if (!isRecord(value) || typeof value.projectPlanId !== 'string') {
6
6
  return false;
7
7
  }
8
- return Object.keys(value).every((key) => key === 'projectPlanId');
8
+ if ((value.offerSetId !== undefined && typeof value.offerSetId !== 'string')
9
+ || (value.offerSetKey !== undefined && typeof value.offerSetKey !== 'string')) {
10
+ return false;
11
+ }
12
+ return Object.keys(value).every((key) => (key === 'projectPlanId' || key === 'offerSetId' || key === 'offerSetKey'));
9
13
  };
10
14
  export const isBillingPlanMappingCatalog = (value) => {
11
15
  if (!isRecord(value)) {
@@ -16,6 +20,7 @@ export const isBillingPlanMappingCatalog = (value) => {
16
20
  };
17
21
  export const buildBillingPlanMappingCatalog = (planCatalog) => {
18
22
  return Object.fromEntries(Object.entries(planCatalog).flatMap(([key, plan]) => {
23
+ var _a, _b;
19
24
  const planKey = key.trim();
20
25
  const projectPlanId = plan.projectPlanId.trim();
21
26
  if (!planKey || !projectPlanId) {
@@ -24,9 +29,7 @@ export const buildBillingPlanMappingCatalog = (planCatalog) => {
24
29
  return [
25
30
  [
26
31
  planKey,
27
- {
28
- projectPlanId,
29
- },
32
+ Object.assign(Object.assign({ projectPlanId }, (((_a = plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) ? { offerSetId: plan.offerSetId.trim() } : {})), (((_b = plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) ? { offerSetKey: plan.offerSetKey.trim() } : {})),
30
33
  ],
31
34
  ];
32
35
  }));
@@ -5,6 +5,7 @@ import type { RuntimeMode } from '@funnelsgrove/runtime';
5
5
  import { type RemoteProjectBillingPlan } from './planCatalog.service.js';
6
6
  export type PaywallPlan = {
7
7
  id: string;
8
+ offerSetId?: string;
8
9
  offerSetKey?: string;
9
10
  title: string;
10
11
  description?: string;
@@ -46,7 +47,7 @@ export declare function resolvePaywallPlansFromProjectPlans(projectPlans: readon
46
47
  export declare function getPaywallPlans(mode: RuntimeMode, planCatalog?: BillingPlanInputCatalog | readonly BillingFallbackPlanConfig[], options?: PaywallPlanResolutionOptions): Promise<readonly PaywallPlan[]>;
47
48
  export declare function isStripeConfigured(mode: RuntimeMode): boolean;
48
49
  export declare function getStripePromise(_mode: RuntimeMode, runtimePublishableKey?: string | null): Promise<Stripe | null> | null;
49
- type CheckoutSessionPlanInput = Pick<PaywallPlan, 'amountCents' | 'analyticsPurchaseValue' | 'billingInterval' | 'billingIntervalCount' | 'description' | 'id' | 'providerPlanId' | 'title' | 'followUpProviderPlanId' | 'followUpPlanTitle' | 'followUpBillingInterval' | 'followUpBillingIntervalCount' | 'introIterations' | 'offerSetKey'>;
50
+ type CheckoutSessionPlanInput = Pick<PaywallPlan, 'amountCents' | 'analyticsPurchaseValue' | 'billingInterval' | 'billingIntervalCount' | 'description' | 'id' | 'providerPlanId' | 'title' | 'followUpProviderPlanId' | 'followUpPlanTitle' | 'followUpBillingInterval' | 'followUpBillingIntervalCount' | 'introIterations' | 'offerSetId' | 'offerSetKey'>;
50
51
  type CheckoutPlanRecurringConfig = {
51
52
  interval: BillingPlanInterval;
52
53
  intervalCount: number;
@@ -54,6 +55,8 @@ type CheckoutPlanRecurringConfig = {
54
55
  export declare const resolveCheckoutPlanRecurringConfig: (plan: CheckoutSessionPlanInput) => CheckoutPlanRecurringConfig | null;
55
56
  type CreatePaymentIntentInput = {
56
57
  planId: string;
58
+ offerSetId?: string | null;
59
+ offerSetKey?: string | null;
57
60
  amountCents: number;
58
61
  couponId?: string | null;
59
62
  analyticsMetadata?: Record<string, unknown> | null;
@@ -194,6 +194,8 @@ const toRemoteProjectBillingPlan = (rawPlan) => {
194
194
  return {
195
195
  id: asTrimmedStringOrNull(rawPlan.id) || providerPlanId,
196
196
  key: asTrimmedStringOrNull(rawPlan.key) || providerPlanId,
197
+ offerSetId: asTrimmedStringOrNull(rawPlan.offerSetId) || undefined,
198
+ offerSetKey: asTrimmedStringOrNull(rawPlan.offerSetKey) || undefined,
197
199
  projectPlanId: asTrimmedStringOrNull(rawPlan.projectPlanId),
198
200
  providerPlanId,
199
201
  displayName: asTrimmedStringOrNull(rawPlan.displayName),
@@ -237,6 +239,8 @@ const toPlanFromRemoteProjectPlan = (rawPlan, options, planIdOverride) => {
237
239
  : formatMoneyFromMinor(amountMinor, currencyCode, locale);
238
240
  return {
239
241
  id: planId,
242
+ offerSetId: rawPlan.offerSetId,
243
+ offerSetKey: rawPlan.offerSetKey,
240
244
  title,
241
245
  description: rawPlan.description || asTrimmedStringOrNull(metadata.description) || undefined,
242
246
  providerPlanId: rawPlan.providerPlanId,
@@ -369,8 +373,8 @@ export function getDefaultPlanSelectionValue(plans, pricing) {
369
373
  }
370
374
  return getPaywallPlanSelectionValue(plans.find((plan) => plan.id === defaultPlanId) || plans[0]);
371
375
  }
372
- const getStripeSyncedPlanRecords = async (mode) => {
373
- const cacheKey = `${mode}:${FUNNEL_ID || 'no-funnel'}:${FUNNEL_SDK_PUBLISHABLE_KEY}`;
376
+ const getStripeSyncedPlanRecords = async (mode, offerSet) => {
377
+ const cacheKey = `${mode}:${FUNNEL_ID || 'no-funnel'}:${FUNNEL_SDK_PUBLISHABLE_KEY}:${offerSet.offerSetId || ''}:${offerSet.offerSetKey || ''}`;
374
378
  const cachedPromise = syncedPlansPromiseByMode.get(cacheKey);
375
379
  if (cachedPromise) {
376
380
  return cachedPromise;
@@ -378,6 +382,8 @@ const getStripeSyncedPlanRecords = async (mode) => {
378
382
  const nextPromise = (async () => {
379
383
  const payload = await funnelSdkService.listPaymentPlans({
380
384
  environment: mode,
385
+ offerSetId: offerSet.offerSetId,
386
+ offerSetKey: offerSet.offerSetKey,
381
387
  });
382
388
  const rawPlans = Array.isArray(payload.plans) ? payload.plans : [];
383
389
  return rawPlans
@@ -388,8 +394,23 @@ const getStripeSyncedPlanRecords = async (mode) => {
388
394
  syncedPlansPromiseByMode.set(cacheKey, nextPromise);
389
395
  return nextPromise;
390
396
  };
397
+ const resolvePlanCatalogOfferSet = (planCatalog) => {
398
+ const configuredPlans = planCatalog
399
+ ? (Array.isArray(planCatalog) ? planCatalog : Object.values(planCatalog))
400
+ : [];
401
+ const offerSetIds = [...new Set(configuredPlans
402
+ .map((plan) => { var _a; return (_a = plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim(); })
403
+ .filter((value) => Boolean(value)))];
404
+ const offerSetKeys = [...new Set(configuredPlans
405
+ .map((plan) => { var _a; return (_a = plan.offerSetKey) === null || _a === void 0 ? void 0 : _a.trim(); })
406
+ .filter((value) => Boolean(value)))];
407
+ return {
408
+ offerSetId: offerSetIds.length === 1 ? offerSetIds[0] : undefined,
409
+ offerSetKey: offerSetKeys.length === 1 ? offerSetKeys[0] : undefined,
410
+ };
411
+ };
391
412
  export async function getStripeSyncedPlans(mode, planCatalog, options) {
392
- const rawPlans = await getStripeSyncedPlanRecords(mode);
413
+ const rawPlans = await getStripeSyncedPlanRecords(mode, resolvePlanCatalogOfferSet(planCatalog));
393
414
  const mappedPlans = (planCatalog && !Array.isArray(planCatalog) && isBillingPlanMappingCatalog(planCatalog)
394
415
  ? resolveMappedProjectPlans(planCatalog, rawPlans).map((rawPlan) => toPlanFromRemoteProjectPlan(rawPlan, options, rawPlan.funnelKey))
395
416
  : rawPlans.map((rawPlan) => toPlanFromRemoteProjectPlan(rawPlan, options)))
@@ -410,7 +431,7 @@ export async function getPaywallPlans(mode, planCatalog, options) {
410
431
  return getFallbackPlans(planCatalog, options);
411
432
  }
412
433
  try {
413
- const syncedPlans = resolvePaywallPlansFromProjectPlans(await getStripeSyncedPlanRecords(mode), planCatalog, options);
434
+ const syncedPlans = resolvePaywallPlansFromProjectPlans(await getStripeSyncedPlanRecords(mode, resolvePlanCatalogOfferSet(planCatalog)), planCatalog, options);
414
435
  if (syncedPlans.length > 0) {
415
436
  return syncedPlans;
416
437
  }
@@ -529,19 +550,20 @@ const normalizeCheckoutAnalyticsMetadata = (metadata, plan) => {
529
550
  return Object.assign(Object.assign({}, (normalized !== null && normalized !== void 0 ? normalized : {})), { analyticsPurchaseValue });
530
551
  };
531
552
  export async function createStripeOneTimeCheckout(input) {
532
- var _a, _b, _c, _d, _e, _f;
553
+ var _a, _b, _c, _d, _e, _f, _g;
533
554
  return funnelSdkService.createOneTimeCheckout({
534
- offerSetKey: ((_a = input.plan.offerSetKey) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
555
+ offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
556
+ offerSetKey: ((_b = input.plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
535
557
  planId: getPaywallPlanSelectionValue(input.plan),
536
- providerPlanId: ((_b = input.plan.providerPlanId) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
558
+ providerPlanId: ((_c = input.plan.providerPlanId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
537
559
  title: input.plan.title,
538
- description: ((_c = input.plan.description) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
560
+ description: ((_d = input.plan.description) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
539
561
  amountCents: input.plan.amountCents,
540
- couponId: ((_d = input.couponId) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
562
+ couponId: ((_e = input.couponId) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
541
563
  analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
542
- customerEmail: ((_e = input.customerEmail) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
564
+ customerEmail: ((_f = input.customerEmail) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
543
565
  returnUrl: input.returnUrl,
544
- userId: ((_f = input.user_id) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
566
+ userId: ((_g = input.user_id) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
545
567
  environment: input.environment,
546
568
  runtimeConfig: input.runtimeConfig,
547
569
  });
@@ -550,13 +572,15 @@ export async function createStripeOneTimeCheckout(input) {
550
572
  * @deprecated Use createStripeOneTimeCheckout for one-time paywall checkout.
551
573
  */
552
574
  export async function createStripePaymentIntent(input) {
553
- var _a, _b;
575
+ var _a, _b, _c, _d;
554
576
  return funnelSdkService.createOneTimePaymentIntent({
577
+ offerSetId: ((_a = input.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
578
+ offerSetKey: ((_b = input.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
555
579
  planId: input.planId,
556
580
  amountCents: input.amountCents,
557
- couponId: ((_a = input.couponId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
581
+ couponId: ((_c = input.couponId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
558
582
  analyticsMetadata: normalizeAnalyticsMetadata(input.analyticsMetadata),
559
- userId: ((_b = input.user_id) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
583
+ userId: ((_d = input.user_id) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
560
584
  environment: input.environment,
561
585
  runtimeConfig: input.runtimeConfig,
562
586
  });
@@ -577,59 +601,61 @@ export async function chargeStripeOneClickPayment(input) {
577
601
  });
578
602
  }
579
603
  export async function createStripeSubscriptionCheckout(input) {
580
- var _a, _b, _c, _d, _e, _f, _g, _h;
604
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
581
605
  const recurring = resolveCheckoutPlanRecurringConfig(input.plan);
582
606
  if (!recurring) {
583
607
  throw new Error('Unable to resolve the recurring interval for the selected plan');
584
608
  }
585
609
  return funnelSdkService.createSubscriptionCheckout({
586
- offerSetKey: ((_a = input.plan.offerSetKey) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
610
+ offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
611
+ offerSetKey: ((_b = input.plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
587
612
  planId: getPaywallPlanSelectionValue(input.plan),
588
- providerPlanId: ((_b = input.plan.providerPlanId) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
613
+ providerPlanId: ((_c = input.plan.providerPlanId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
589
614
  title: input.plan.title,
590
- description: ((_c = input.plan.description) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
615
+ description: ((_d = input.plan.description) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
591
616
  amountCents: input.plan.amountCents,
592
617
  billingInterval: recurring.interval,
593
618
  billingIntervalCount: recurring.intervalCount,
594
- followUpProviderPlanId: ((_d = input.plan.followUpProviderPlanId) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
595
- followUpPlanTitle: ((_e = input.plan.followUpPlanTitle) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
619
+ followUpProviderPlanId: ((_e = input.plan.followUpProviderPlanId) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
620
+ followUpPlanTitle: ((_f = input.plan.followUpPlanTitle) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
596
621
  followUpBillingInterval: input.plan.followUpBillingInterval,
597
622
  followUpBillingIntervalCount: input.plan.followUpBillingIntervalCount,
598
623
  introIterations: input.plan.introIterations,
599
- couponId: ((_f = input.couponId) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
624
+ couponId: ((_g = input.couponId) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
600
625
  analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
601
- customerEmail: ((_g = input.customerEmail) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
626
+ customerEmail: ((_h = input.customerEmail) === null || _h === void 0 ? void 0 : _h.trim()) || undefined,
602
627
  returnUrl: input.returnUrl,
603
- userId: ((_h = input.user_id) === null || _h === void 0 ? void 0 : _h.trim()) || undefined,
628
+ userId: ((_j = input.user_id) === null || _j === void 0 ? void 0 : _j.trim()) || undefined,
604
629
  environment: input.environment,
605
630
  runtimeConfig: input.runtimeConfig,
606
631
  });
607
632
  }
608
633
  export async function updateStripeSubscriptionCheckoutPlan(input) {
609
- var _a, _b, _c, _d, _e, _f, _g, _h;
634
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
610
635
  const recurring = resolveCheckoutPlanRecurringConfig(input.plan);
611
636
  if (!recurring) {
612
637
  throw new Error('Unable to resolve the recurring interval for the selected plan');
613
638
  }
614
639
  return funnelSdkService.updateSubscriptionCheckoutPlan({
615
640
  checkoutSessionId: input.checkoutSessionId.trim(),
616
- offerSetKey: ((_a = input.plan.offerSetKey) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
641
+ offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
642
+ offerSetKey: ((_b = input.plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
617
643
  planId: getPaywallPlanSelectionValue(input.plan),
618
- providerPlanId: ((_b = input.plan.providerPlanId) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
644
+ providerPlanId: ((_c = input.plan.providerPlanId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
619
645
  title: input.plan.title,
620
- description: ((_c = input.plan.description) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
646
+ description: ((_d = input.plan.description) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
621
647
  amountCents: input.plan.amountCents,
622
648
  billingInterval: recurring.interval,
623
649
  billingIntervalCount: recurring.intervalCount,
624
- followUpProviderPlanId: ((_d = input.plan.followUpProviderPlanId) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
625
- followUpPlanTitle: ((_e = input.plan.followUpPlanTitle) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
650
+ followUpProviderPlanId: ((_e = input.plan.followUpProviderPlanId) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
651
+ followUpPlanTitle: ((_f = input.plan.followUpPlanTitle) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
626
652
  followUpBillingInterval: input.plan.followUpBillingInterval,
627
653
  followUpBillingIntervalCount: input.plan.followUpBillingIntervalCount,
628
654
  introIterations: input.plan.introIterations,
629
- couponId: ((_f = input.couponId) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
655
+ couponId: ((_g = input.couponId) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
630
656
  analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
631
- customerEmail: ((_g = input.customerEmail) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
632
- userId: ((_h = input.user_id) === null || _h === void 0 ? void 0 : _h.trim()) || undefined,
657
+ customerEmail: ((_h = input.customerEmail) === null || _h === void 0 ? void 0 : _h.trim()) || undefined,
658
+ userId: ((_j = input.user_id) === null || _j === void 0 ? void 0 : _j.trim()) || undefined,
633
659
  environment: input.environment,
634
660
  runtimeConfig: input.runtimeConfig,
635
661
  });
@@ -646,26 +672,27 @@ export async function verifyStripeSubscriptionCheckoutPayment(input) {
646
672
  });
647
673
  }
648
674
  export async function createStripeCheckoutSession(input) {
649
- var _a, _b, _c, _d, _e, _f;
675
+ var _a, _b, _c, _d, _e, _f, _g;
650
676
  const recurring = resolveCheckoutPlanRecurringConfig(input.plan);
651
677
  if (!recurring) {
652
678
  throw new Error('Unable to resolve the recurring interval for the selected plan');
653
679
  }
654
680
  return funnelSdkService.createHostedCheckoutSession({
655
- offerSetKey: ((_a = input.plan.offerSetKey) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
681
+ offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
682
+ offerSetKey: ((_b = input.plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
656
683
  planId: getPaywallPlanSelectionValue(input.plan),
657
- providerPlanId: ((_b = input.plan.providerPlanId) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
684
+ providerPlanId: ((_c = input.plan.providerPlanId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
658
685
  title: input.plan.title,
659
- description: ((_c = input.plan.description) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
686
+ description: ((_d = input.plan.description) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
660
687
  amountCents: input.plan.amountCents,
661
688
  billingInterval: recurring.interval,
662
689
  billingIntervalCount: recurring.intervalCount,
663
- couponId: ((_d = input.couponId) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
690
+ couponId: ((_e = input.couponId) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
664
691
  analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
665
692
  successUrl: input.successUrl,
666
693
  cancelUrl: input.cancelUrl,
667
- customerEmail: ((_e = input.customerEmail) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
668
- userId: ((_f = input.user_id) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
694
+ customerEmail: ((_f = input.customerEmail) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
695
+ userId: ((_g = input.user_id) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
669
696
  environment: input.environment,
670
697
  runtimeConfig: input.runtimeConfig,
671
698
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/payments",
3
- "version": "0.1.59",
3
+ "version": "0.3.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/The-Solid-Grove/funnelsgrove.git",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@funnelsgrove/analytics": "^0.1.28",
36
- "@funnelsgrove/runtime": "^0.1.54",
36
+ "@funnelsgrove/runtime": "^0.3.0",
37
37
  "@stripe/react-stripe-js": "^5.6.0",
38
38
  "@stripe/stripe-js": "^8.7.0",
39
39
  "react": "19.2.3",