@funnelsgrove/payments 0.11.5 → 0.11.6

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.
@@ -0,0 +1,11 @@
1
+ export type StripeCheckoutAttempt = {
2
+ key: string;
3
+ id: string;
4
+ };
5
+ export declare const resolveStripeCheckoutAttempt: (input: {
6
+ current: StripeCheckoutAttempt | null;
7
+ forceNew: boolean;
8
+ intentKey: string;
9
+ paymentsApiVersion?: "v1" | "v2" | null;
10
+ createId: () => string;
11
+ }) => StripeCheckoutAttempt | null;
@@ -0,0 +1,10 @@
1
+ export const resolveStripeCheckoutAttempt = (input) => {
2
+ var _a;
3
+ if (input.paymentsApiVersion !== 'v2') {
4
+ return null;
5
+ }
6
+ if (!input.forceNew && ((_a = input.current) === null || _a === void 0 ? void 0 : _a.key) === input.intentKey) {
7
+ return input.current;
8
+ }
9
+ return { key: input.intentKey, id: input.createId() };
10
+ };
@@ -15,6 +15,7 @@ import { createEmptyCheckoutPreparationLoading, } from '../../paymentProvider.ty
15
15
  import { createStripeOneTimeCheckout, getStripePromise, isStripeConfigured, } from '../services/stripe.service.js';
16
16
  import { isInactiveCheckoutSessionError } from './useStripeSubscriptionCheckoutSession.js';
17
17
  import { toAnalyticsPaymentMethod } from '../../../services/paymentMethodAnalytics.service.js';
18
+ import { resolveStripeCheckoutAttempt, } from './checkoutAttempt.js';
18
19
  export function resolveStripeOneTimeCheckoutPreparationOptions(source, options = {}) {
19
20
  var _a, _b;
20
21
  const checkoutStartSource = (_a = options.checkoutStartSource) !== null && _a !== void 0 ? _a : (source === 'wallet' ? 'wallet_render' : 'card_click');
@@ -154,7 +155,7 @@ export function useStripeOneTimeCheckoutSession({ runtimeConfigRevisionId, payme
154
155
  : Object.assign(Object.assign({}, current), { [source]: value }));
155
156
  }, []);
156
157
  const createCheckoutSession = useCallback(async (options = {}) => {
157
- var _a, _b, _c;
158
+ var _a, _b;
158
159
  const forceNew = options.forceNew === true;
159
160
  if (!configured || !plan) {
160
161
  return null;
@@ -169,10 +170,14 @@ export function useStripeOneTimeCheckoutSession({ runtimeConfigRevisionId, payme
169
170
  clearActiveCheckoutSession();
170
171
  attemptRef.current = null;
171
172
  }
172
- if ((runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.paymentsApiVersion) === 'v2' && ((_b = attemptRef.current) === null || _b === void 0 ? void 0 : _b.key) !== intentKey) {
173
- attemptRef.current = { key: intentKey, id: crypto.randomUUID() };
174
- }
175
- const idempotencyKey = (_c = attemptRef.current) === null || _c === void 0 ? void 0 : _c.id;
173
+ attemptRef.current = resolveStripeCheckoutAttempt({
174
+ current: attemptRef.current,
175
+ forceNew,
176
+ intentKey,
177
+ paymentsApiVersion: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.paymentsApiVersion,
178
+ createId: () => crypto.randomUUID(),
179
+ });
180
+ const idempotencyKey = (_b = attemptRef.current) === null || _b === void 0 ? void 0 : _b.id;
176
181
  if (idempotencyKey && !userId && !anonymousUserIdRef.current) {
177
182
  anonymousUserIdRef.current = `anonymous_${crypto.randomUUID()}`;
178
183
  }
@@ -14,6 +14,7 @@ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } f
14
14
  import { createEmptyCheckoutPreparationLoading, } from '../../paymentProvider.types.js';
15
15
  import { createStripeSubscriptionCheckout, getStripePromise, isStripeConfigured, updateStripeSubscriptionCheckoutPlan, } from '../services/stripe.service.js';
16
16
  import { toAnalyticsPaymentMethod } from '../../../services/paymentMethodAnalytics.service.js';
17
+ import { resolveStripeCheckoutAttempt, } from './checkoutAttempt.js';
17
18
  export function resolveStripeSubscriptionCheckoutPreparationOptions(source, options = {}) {
18
19
  var _a, _b;
19
20
  const checkoutStartSource = (_a = options.checkoutStartSource) !== null && _a !== void 0 ? _a : (source === 'wallet' ? 'wallet_render' : 'card_click');
@@ -78,6 +79,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
78
79
  const [runtimeStripePublishableKey, setRuntimeStripePublishableKey] = useState(null);
79
80
  const creatingIntentRef = useRef(null);
80
81
  const requestIdRef = useRef(0);
82
+ const attemptRef = useRef(null);
81
83
  const anonymousUserIdRef = useRef(null);
82
84
  const configured = enabled &&
83
85
  (isStripeConfigured(checkoutMode) ||
@@ -130,6 +132,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
130
132
  onError === null || onError === void 0 ? void 0 : onError(message);
131
133
  }, [clearActiveCheckoutSession, onError]);
132
134
  const reset = useCallback(() => {
135
+ attemptRef.current = null;
133
136
  clearActiveCheckoutSession();
134
137
  setLoading(createEmptyCheckoutPreparationLoading());
135
138
  setRuntimeStripePublishableKey(null);
@@ -148,7 +151,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
148
151
  : Object.assign(Object.assign({}, current), { [source]: value }));
149
152
  }, []);
150
153
  const createCheckoutSubscription = useCallback(async (options = {}) => {
151
- var _a;
154
+ var _a, _b;
152
155
  const forceNew = options.forceNew === true;
153
156
  if (!configured || !plan || !displayPlan) {
154
157
  return null;
@@ -161,6 +164,18 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
161
164
  }
162
165
  if (forceNew) {
163
166
  clearActiveCheckoutSession();
167
+ attemptRef.current = null;
168
+ }
169
+ attemptRef.current = resolveStripeCheckoutAttempt({
170
+ current: attemptRef.current,
171
+ forceNew,
172
+ intentKey,
173
+ paymentsApiVersion: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.paymentsApiVersion,
174
+ createId: () => crypto.randomUUID(),
175
+ });
176
+ const idempotencyKey = (_b = attemptRef.current) === null || _b === void 0 ? void 0 : _b.id;
177
+ if (idempotencyKey && !userId && !anonymousUserIdRef.current) {
178
+ anonymousUserIdRef.current = `anonymous_${crypto.randomUUID()}`;
164
179
  }
165
180
  const requestKey = intentKey;
166
181
  const requestPlanKey = planKey;
@@ -182,6 +197,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
182
197
  paymentProfileId,
183
198
  provider,
184
199
  anonymousUserId: anonymousUserIdRef.current,
200
+ idempotencyKey,
185
201
  });
186
202
  if (((_a = creatingIntentRef.current) === null || _a === void 0 ? void 0 : _a.key) !== requestKey ||
187
203
  ((_b = creatingIntentRef.current) === null || _b === void 0 ? void 0 : _b.id) !== requestId) {
@@ -31,6 +31,7 @@ export declare const toSubscriptionCheckoutRequest: (input: CreateSubscriptionCh
31
31
  paymentProfileId: string | undefined;
32
32
  runtimeConfigRevisionId: string | undefined;
33
33
  anonymousUserId: string | undefined;
34
+ idempotencyKey: string | undefined;
34
35
  title: string;
35
36
  description: string | undefined;
36
37
  amountCents: number;
@@ -27,7 +27,7 @@ export const toOneTimeCheckoutRequest = (input) => {
27
27
  };
28
28
  };
29
29
  export const toSubscriptionCheckoutRequest = (input) => {
30
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
30
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
31
31
  const recurring = requireCheckoutRecurringConfig(input.plan);
32
32
  return {
33
33
  offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
@@ -39,21 +39,22 @@ export const toSubscriptionCheckoutRequest = (input) => {
39
39
  paymentProfileId: ((_e = input.paymentProfileId) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
40
40
  runtimeConfigRevisionId: ((_f = input.runtimeConfigRevisionId) === null || _f === void 0 ? void 0 : _f.trim()) || undefined,
41
41
  anonymousUserId: ((_g = input.anonymousUserId) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
42
+ idempotencyKey: ((_h = input.idempotencyKey) === null || _h === void 0 ? void 0 : _h.trim()) || undefined,
42
43
  title: input.plan.title,
43
- description: ((_h = input.plan.description) === null || _h === void 0 ? void 0 : _h.trim()) || undefined,
44
+ description: ((_j = input.plan.description) === null || _j === void 0 ? void 0 : _j.trim()) || undefined,
44
45
  amountCents: input.plan.amountCents,
45
46
  billingInterval: recurring.interval,
46
47
  billingIntervalCount: recurring.intervalCount,
47
- followUpProviderPlanId: ((_j = input.plan.followUpProviderPlanId) === null || _j === void 0 ? void 0 : _j.trim()) || undefined,
48
- followUpPlanTitle: ((_k = input.plan.followUpPlanTitle) === null || _k === void 0 ? void 0 : _k.trim()) || undefined,
48
+ followUpProviderPlanId: ((_k = input.plan.followUpProviderPlanId) === null || _k === void 0 ? void 0 : _k.trim()) || undefined,
49
+ followUpPlanTitle: ((_l = input.plan.followUpPlanTitle) === null || _l === void 0 ? void 0 : _l.trim()) || undefined,
49
50
  followUpBillingInterval: input.plan.followUpBillingInterval,
50
51
  followUpBillingIntervalCount: input.plan.followUpBillingIntervalCount,
51
52
  introIterations: input.plan.introIterations,
52
- couponId: ((_l = input.couponId) === null || _l === void 0 ? void 0 : _l.trim()) || undefined,
53
+ couponId: ((_m = input.couponId) === null || _m === void 0 ? void 0 : _m.trim()) || undefined,
53
54
  analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
54
- customerEmail: ((_m = input.customerEmail) === null || _m === void 0 ? void 0 : _m.trim()) || undefined,
55
+ customerEmail: ((_o = input.customerEmail) === null || _o === void 0 ? void 0 : _o.trim()) || undefined,
55
56
  returnUrl: input.returnUrl,
56
- userId: ((_o = input.user_id) === null || _o === void 0 ? void 0 : _o.trim()) || undefined,
57
+ userId: ((_p = input.user_id) === null || _p === void 0 ? void 0 : _p.trim()) || undefined,
57
58
  environment: input.environment,
58
59
  runtimeConfig: input.runtimeConfig,
59
60
  };
@@ -32,6 +32,7 @@ export type CreateSubscriptionCheckoutInput = {
32
32
  paymentProfileId?: string | null;
33
33
  provider?: 'stripe' | null;
34
34
  anonymousUserId?: string | null;
35
+ idempotencyKey?: string | null;
35
36
  couponId?: string | null;
36
37
  analyticsMetadata?: Record<string, unknown> | null;
37
38
  customerEmail?: string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/payments",
3
- "version": "0.11.5",
3
+ "version": "0.11.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/The-Solid-Grove/funnelsgrove.git",