@funnelsgrove/payments 0.7.1 → 0.7.3
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 +14 -7
- package/dist/index.d.ts +1 -19
- package/dist/index.js +4 -25
- package/dist/providers/stripe/{ApplePaySubscriptionCheckoutSlot.js → components/ApplePaySubscriptionCheckoutSlot.js} +1 -1
- package/dist/providers/stripe/{GooglePaySubscriptionCheckoutSlot.js → components/GooglePaySubscriptionCheckoutSlot.js} +1 -1
- package/dist/{components/shared → providers/stripe/components}/SharedStripeCheckoutDialog.d.ts +1 -1
- package/dist/{components/shared → providers/stripe/components}/SharedStripeCheckoutDialog.js +1 -1
- package/dist/{components/shared → providers/stripe/components}/SharedStripeCheckoutV2Dialog.d.ts +1 -1
- package/dist/{components/shared → providers/stripe/components}/SharedStripeCheckoutV2Dialog.js +9 -3
- package/dist/{components/shared → providers/stripe/components}/StripeCheckoutExpressCheckoutButton.d.ts +1 -1
- package/dist/{components/shared → providers/stripe/components}/StripeCheckoutExpressCheckoutButton.js +4 -1
- package/dist/{components/shared → providers/stripe/components}/StripeExpressCheckoutButton.d.ts +1 -1
- package/dist/{components/shared → providers/stripe/components}/StripeExpressCheckoutButton.js +4 -1
- package/dist/{components/shared → providers/stripe/components}/StripePlanSelector.d.ts +1 -1
- package/dist/{components/shared → providers/stripe/components}/StripePlanSelector.js +1 -1
- package/dist/providers/stripe/{StripeSubscriptionWalletSurface.d.ts → components/StripeSubscriptionWalletSurface.d.ts} +3 -3
- package/dist/providers/stripe/{StripeSubscriptionWalletSurface.js → components/StripeSubscriptionWalletSurface.js} +2 -2
- package/dist/providers/stripe/{WalletSubscriptionCheckoutSlot.d.ts → components/WalletSubscriptionCheckoutSlot.d.ts} +2 -2
- package/dist/providers/stripe/{WalletSubscriptionCheckoutSlot.js → components/WalletSubscriptionCheckoutSlot.js} +4 -4
- package/dist/providers/stripe/components/index.d.ts +13 -0
- package/dist/providers/stripe/components/index.js +13 -0
- package/dist/providers/stripe/hooks/index.d.ts +3 -0
- package/dist/providers/stripe/hooks/index.js +3 -0
- package/dist/{hooks → providers/stripe/hooks}/useResolvedPaywallPlans.d.ts +1 -1
- package/dist/{hooks → providers/stripe/hooks}/useResolvedPaywallPlans.js +1 -1
- package/dist/providers/stripe/{useStripeOneTimeCheckoutSession.d.ts → hooks/useStripeOneTimeCheckoutSession.d.ts} +2 -2
- package/dist/providers/stripe/{useStripeOneTimeCheckoutSession.js → hooks/useStripeOneTimeCheckoutSession.js} +3 -3
- package/dist/providers/stripe/{useStripeSubscriptionCheckoutSession.d.ts → hooks/useStripeSubscriptionCheckoutSession.d.ts} +3 -3
- package/dist/providers/stripe/{useStripeSubscriptionCheckoutSession.js → hooks/useStripeSubscriptionCheckoutSession.js} +3 -3
- package/dist/providers/stripe/index.d.ts +4 -0
- package/dist/providers/stripe/index.js +4 -0
- package/dist/{services → providers/stripe/services}/checkoutCompletionAnalytics.service.d.ts +5 -0
- package/dist/{services → providers/stripe/services}/checkoutCompletionAnalytics.service.js +41 -1
- package/dist/providers/stripe/services/index.d.ts +2 -0
- package/dist/providers/stripe/services/index.js +2 -0
- package/dist/{services → providers/stripe/services}/stripe.service.d.ts +18 -4
- package/dist/{services → providers/stripe/services}/stripe.service.js +47 -12
- package/dist/providers/stripe/testing/index.d.ts +1 -0
- package/dist/providers/stripe/testing/index.js +1 -0
- package/dist/services/paywallOffer.service.d.ts +1 -1
- package/dist/services/publishedBillingRuntime.service.d.ts +1 -1
- package/dist/services/publishedBillingRuntime.service.js +1 -1
- package/package.json +3 -3
- /package/dist/{components/shared → providers/stripe/components}/ApplePaySubscribeButton.d.ts +0 -0
- /package/dist/{components/shared → providers/stripe/components}/ApplePaySubscribeButton.js +0 -0
- /package/dist/providers/stripe/{ApplePaySubscriptionCheckoutSlot.d.ts → components/ApplePaySubscriptionCheckoutSlot.d.ts} +0 -0
- /package/dist/{components/shared → providers/stripe/components}/CheckoutBrandAssets.d.ts +0 -0
- /package/dist/{components/shared → providers/stripe/components}/CheckoutBrandAssets.js +0 -0
- /package/dist/{components/shared → providers/stripe/components}/GooglePaySubscribeButton.d.ts +0 -0
- /package/dist/{components/shared → providers/stripe/components}/GooglePaySubscribeButton.js +0 -0
- /package/dist/providers/stripe/{GooglePaySubscriptionCheckoutSlot.d.ts → components/GooglePaySubscriptionCheckoutSlot.d.ts} +0 -0
- /package/dist/{components/shared → providers/stripe/components}/StripeExpressCheckoutElement.d.ts +0 -0
- /package/dist/{components/shared → providers/stripe/components}/StripeExpressCheckoutElement.js +0 -0
- /package/dist/{components/shared → providers/stripe/components}/checkoutCountries.d.ts +0 -0
- /package/dist/{components/shared → providers/stripe/components}/checkoutCountries.js +0 -0
- /package/dist/{components/shared → providers/stripe/components}/walletPlatform.d.ts +0 -0
- /package/dist/{components/shared → providers/stripe/components}/walletPlatform.js +0 -0
- /package/dist/{testing → providers/stripe/testing}/walletCheckoutSmoke.d.ts +0 -0
- /package/dist/{testing → providers/stripe/testing}/walletCheckoutSmoke.js +0 -0
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Read this file before editing checkout code. Deeper implementation docs:
|
|
|
9
9
|
|
|
10
10
|
## Owns provider-backed checkout primitives
|
|
11
11
|
|
|
12
|
-
`@funnelsgrove/payments` owns reusable payment contracts, provider adapters, checkout-session helpers, wallet slots,
|
|
12
|
+
`@funnelsgrove/payments` owns reusable payment contracts, provider adapters, checkout-session helpers, wallet slots, checkout UI primitives, and Checkout Session-scoped semantic analytics. Funnel code owns paywall layout, copy, when an offer opens, post-payment navigation, and the lifecycle completion callback after verified payment success.
|
|
13
13
|
|
|
14
14
|
## Current Checkout Path
|
|
15
15
|
|
|
@@ -25,13 +25,14 @@ Use these for new subscription paywalls:
|
|
|
25
25
|
- `useStripeSubscriptionCheckoutSession`
|
|
26
26
|
- `SharedStripeCheckoutV2Dialog`
|
|
27
27
|
- `trackPaidStripeSubscriptionCheckoutCompleted`
|
|
28
|
+
- `trackStripeSubscriptionPaymentInfoSubmitted`
|
|
28
29
|
|
|
29
30
|
Use these for new one-time paywall plans:
|
|
30
31
|
|
|
31
32
|
- `createStripeOneTimeCheckout`
|
|
32
33
|
- `SharedStripeCheckoutV2Dialog`
|
|
33
34
|
|
|
34
|
-
Use `
|
|
35
|
+
Use `completeStripeOneClickPayment` for normal post-checkout one-click upsells. It delegates the charge to `funnelSdkService.chargeOneClickPayment` and owns any required Stripe confirmation. `chargeStripeOneClickPayment` remains the lower-level charge-only primitive.
|
|
35
36
|
|
|
36
37
|
## Advanced Wallet Primitives
|
|
37
38
|
|
|
@@ -78,21 +79,27 @@ When a live funnel still uses one of these, migrate the funnel deliberately with
|
|
|
78
79
|
- `services/planCatalog.service`: plan resolution and selection helpers.
|
|
79
80
|
- `services/runtimeBillingPlanCatalog.service`: test/live runtime catalog selection.
|
|
80
81
|
- `services/paywallOffer.service`: timed discount and display-plan helpers.
|
|
81
|
-
- `
|
|
82
|
-
- `providers/*`:
|
|
83
|
-
- `
|
|
84
|
-
- `
|
|
82
|
+
- `providers/paymentProvider.types`: provider-neutral checkout state shared by every adapter.
|
|
83
|
+
- `providers/stripe/services/*`: Stripe loader, Checkout Session, hosted checkout, one-click, analytics, and deprecated PaymentIntent compatibility clients.
|
|
84
|
+
- `providers/stripe/hooks/*`: Stripe-backed plan resolution and isolated card/wallet checkout-session state.
|
|
85
|
+
- `providers/stripe/components/*`: plan selector, checkout dialogs, Express Checkout wrappers, wallet slots, placeholders, and trust assets.
|
|
86
|
+
- `providers/stripe/testing/*`: Stripe wallet checkout smoke assertions.
|
|
87
|
+
- `components/ManageSubscriptionScreen`: provider-neutral subscription management UI.
|
|
85
88
|
|
|
86
89
|
Funnels should call `resolvePublishedBillingRuntime` once at their runtime-provider boundary. Screens consume its resolved view and should not parse offer sets or pricing-experiment variants themselves.
|
|
87
90
|
|
|
88
91
|
## Engineering Rules
|
|
89
92
|
|
|
90
|
-
- Keep provider-specific
|
|
93
|
+
- Keep every provider-specific component, hook, service, and test helper under `src/providers/<provider>`. Add future providers as sibling folders; do not place provider SDK imports in root `components`, `hooks`, or `services`.
|
|
91
94
|
- Stripe owns real card fields and wallet controls. Local wallet buttons are placeholders until Stripe confirms availability.
|
|
95
|
+
- Keep `planId` as the funnel plan key and send Stripe's price id only as `providerPlanId`; the API uses both fields to resolve the active test/live offer mapping.
|
|
92
96
|
- Wallet unavailable state must fall back to card/manual checkout or disappear.
|
|
93
97
|
- 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.
|
|
98
|
+
- Pass `checkoutAnalytics` to every current shared dialog and wallet surface. The package then owns `checkout_started`, `add_payment_info`, and verified `checkout_completed`, all deduplicated by the actual Checkout Session.
|
|
99
|
+
- Call funnel lifecycle `completeStep` only from the shared checkout `onSuccess` callback. Payment-info submission is not step completion.
|
|
94
100
|
- 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`.
|
|
95
101
|
- Shared checkout analytics deduplicates `checkout_started` by Checkout Session id. Card submit and wallet confirmation must not emit it again.
|
|
102
|
+
- Do not call `publicAnalyticsSdk.trackCheckoutStarted`, `trackPaymentInfoSubmitted`, or `trackCheckoutCompleted` directly from funnel checkout components.
|
|
96
103
|
- 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.
|
|
97
104
|
- Keep discount math reusable here, but keep offer activation timing in funnel code.
|
|
98
105
|
- Checkout metadata must avoid sensitive raw query params and use `@funnelsgrove/analytics` metadata helpers.
|
package/dist/index.d.ts
CHANGED
|
@@ -5,25 +5,7 @@ export * from './services/planCatalog.service.js';
|
|
|
5
5
|
export * from './services/runtimeBillingPlanCatalog.service.js';
|
|
6
6
|
export * from './services/publishedBillingRuntime.service.js';
|
|
7
7
|
export * from './services/paywallOffer.service.js';
|
|
8
|
-
export * from './services/stripe.service.js';
|
|
9
|
-
export * from './services/checkoutCompletionAnalytics.service.js';
|
|
10
8
|
export * from './services/paymentMethodAnalytics.service.js';
|
|
11
|
-
export * from './hooks/useResolvedPaywallPlans.js';
|
|
12
9
|
export * from './providers/paymentProvider.types.js';
|
|
13
|
-
export * from './providers/stripe/
|
|
14
|
-
export * from './providers/stripe/useStripeOneTimeCheckoutSession.js';
|
|
15
|
-
export * from './providers/stripe/WalletSubscriptionCheckoutSlot.js';
|
|
16
|
-
export * from './providers/stripe/ApplePaySubscriptionCheckoutSlot.js';
|
|
17
|
-
export * from './providers/stripe/GooglePaySubscriptionCheckoutSlot.js';
|
|
18
|
-
export * from './providers/stripe/StripeSubscriptionWalletSurface.js';
|
|
10
|
+
export * from './providers/stripe/index.js';
|
|
19
11
|
export { ManageSubscriptionScreen, type ManageSubscriptionContent, type ManageSubscriptionScreenProps, } from './components/ManageSubscriptionScreen.js';
|
|
20
|
-
export * from './components/shared/SharedStripeCheckoutV2Dialog.js';
|
|
21
|
-
export * from './components/shared/StripeExpressCheckoutElement.js';
|
|
22
|
-
export * from './components/shared/StripePlanSelector.js';
|
|
23
|
-
export * from './components/shared/walletPlatform.js';
|
|
24
|
-
export * from './components/shared/StripeCheckoutExpressCheckoutButton.js';
|
|
25
|
-
export * from './components/shared/StripeExpressCheckoutButton.js';
|
|
26
|
-
export * from './components/shared/SharedStripeCheckoutDialog.js';
|
|
27
|
-
export * from './components/shared/ApplePaySubscribeButton.js';
|
|
28
|
-
export * from './components/shared/GooglePaySubscribeButton.js';
|
|
29
|
-
export * from './testing/walletCheckoutSmoke.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Provider-neutral billing contracts, plan resolution, and shared runtime helpers.
|
|
2
2
|
export * from './config/billing.config.js';
|
|
3
3
|
export * from './services/preview-frame.service.js';
|
|
4
4
|
export * from './services/runtime-mode.service.js';
|
|
@@ -6,30 +6,9 @@ export * from './services/planCatalog.service.js';
|
|
|
6
6
|
export * from './services/runtimeBillingPlanCatalog.service.js';
|
|
7
7
|
export * from './services/publishedBillingRuntime.service.js';
|
|
8
8
|
export * from './services/paywallOffer.service.js';
|
|
9
|
-
// Stripe API clients and checkout completion handoff.
|
|
10
|
-
export * from './services/stripe.service.js';
|
|
11
|
-
export * from './services/checkoutCompletionAnalytics.service.js';
|
|
12
9
|
export * from './services/paymentMethodAnalytics.service.js';
|
|
13
|
-
export * from './hooks/useResolvedPaywallPlans.js';
|
|
14
|
-
// Provider-neutral and Stripe subscription checkout primitives.
|
|
15
10
|
export * from './providers/paymentProvider.types.js';
|
|
16
|
-
|
|
17
|
-
export * from './providers/stripe/
|
|
18
|
-
|
|
19
|
-
export * from './providers/stripe/ApplePaySubscriptionCheckoutSlot.js';
|
|
20
|
-
export * from './providers/stripe/GooglePaySubscriptionCheckoutSlot.js';
|
|
21
|
-
export * from './providers/stripe/StripeSubscriptionWalletSurface.js';
|
|
22
|
-
// Shared checkout and subscription-management UI.
|
|
11
|
+
// Provider-specific integrations are grouped behind provider barrels.
|
|
12
|
+
export * from './providers/stripe/index.js';
|
|
13
|
+
// Provider-neutral subscription management UI.
|
|
23
14
|
export { ManageSubscriptionScreen, } from './components/ManageSubscriptionScreen.js';
|
|
24
|
-
export * from './components/shared/SharedStripeCheckoutV2Dialog.js';
|
|
25
|
-
export * from './components/shared/StripeExpressCheckoutElement.js';
|
|
26
|
-
export * from './components/shared/StripePlanSelector.js';
|
|
27
|
-
export * from './components/shared/walletPlatform.js';
|
|
28
|
-
export * from './components/shared/StripeCheckoutExpressCheckoutButton.js';
|
|
29
|
-
export * from './components/shared/StripeExpressCheckoutButton.js';
|
|
30
|
-
// Compatibility-only surfaces kept for saved drafts and published artifacts.
|
|
31
|
-
export * from './components/shared/SharedStripeCheckoutDialog.js';
|
|
32
|
-
export * from './components/shared/ApplePaySubscribeButton.js';
|
|
33
|
-
export * from './components/shared/GooglePaySubscribeButton.js';
|
|
34
|
-
// QA helpers.
|
|
35
|
-
export * from './testing/walletCheckoutSmoke.js';
|
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
-
import { ApplePaySubscribeButton } from '
|
|
14
|
+
import { ApplePaySubscribeButton } from './ApplePaySubscribeButton.js';
|
|
15
15
|
import { WalletSubscriptionCheckoutLoadingPlaceholder, WalletSubscriptionCheckoutSlot, } from './WalletSubscriptionCheckoutSlot.js';
|
|
16
16
|
const applePayExpressCheckoutOptions = {
|
|
17
17
|
buttonHeight: 55,
|
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
-
import { GooglePaySubscribeButton } from '
|
|
14
|
+
import { GooglePaySubscribeButton } from './GooglePaySubscribeButton.js';
|
|
15
15
|
import { WalletSubscriptionCheckoutLoadingPlaceholder, WalletSubscriptionCheckoutSlot, } from './WalletSubscriptionCheckoutSlot.js';
|
|
16
16
|
const googlePayExpressCheckoutOptions = {
|
|
17
17
|
buttonHeight: 55,
|
package/dist/{components/shared → providers/stripe/components}/SharedStripeCheckoutDialog.d.ts
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { Stripe } from '@stripe/stripe-js';
|
|
3
|
-
import { type StripeSubscriptionCheckoutAnalyticsContext } from '
|
|
3
|
+
import { type StripeSubscriptionCheckoutAnalyticsContext } from '../services/checkoutCompletionAnalytics.service.js';
|
|
4
4
|
export type SharedStripeCheckoutSummaryRow = {
|
|
5
5
|
id: string;
|
|
6
6
|
label: string;
|
package/dist/{components/shared → providers/stripe/components}/SharedStripeCheckoutDialog.js
RENAMED
|
@@ -16,7 +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 { queueStripeSubscriptionCheckoutStarted, } from '
|
|
19
|
+
import { queueStripeSubscriptionCheckoutStarted, } from '../services/checkoutCompletionAnalytics.service.js';
|
|
20
20
|
const isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
21
21
|
const defaultPaymentMethodLabels = ['Visa', 'Mastercard', 'PayPal', 'G Pay', 'Apple Pay'];
|
|
22
22
|
const normalizeBillingName = (input) => {
|
package/dist/{components/shared → providers/stripe/components}/SharedStripeCheckoutV2Dialog.d.ts
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Stripe } from '@stripe/stripe-js';
|
|
2
|
-
import { type StripeSubscriptionCheckoutAnalyticsContext } from '
|
|
2
|
+
import { type StripeSubscriptionCheckoutAnalyticsContext } from '../services/checkoutCompletionAnalytics.service.js';
|
|
3
3
|
export type SharedStripeCheckoutV2DialogProps = {
|
|
4
4
|
amountCents: number;
|
|
5
5
|
buttonColor: string;
|
package/dist/{components/shared → providers/stripe/components}/SharedStripeCheckoutV2Dialog.js
RENAMED
|
@@ -16,9 +16,9 @@ import { CheckoutProvider, PaymentElement, useCheckout, } from '@stripe/react-st
|
|
|
16
16
|
import { PaymentBrandMark, SecurityLockIcon } from './CheckoutBrandAssets.js';
|
|
17
17
|
import { StripeCheckoutExpressCheckoutButton } from './StripeCheckoutExpressCheckoutButton.js';
|
|
18
18
|
import { getUnsupportedCheckoutCountryMessage, normalizeSupportedCheckoutCountries, } from './checkoutCountries.js';
|
|
19
|
-
import { isInactiveCheckoutSessionError } from '
|
|
19
|
+
import { isInactiveCheckoutSessionError } from '../hooks/useStripeSubscriptionCheckoutSession.js';
|
|
20
20
|
import { getStripeWalletPaymentMethodOrder, usePlatformWalletPaymentMethods, } from './walletPlatform.js';
|
|
21
|
-
import { queueStripeSubscriptionCheckoutStarted, trackPaidStripeSubscriptionCheckoutCompleted, } from '
|
|
21
|
+
import { queueStripeSubscriptionCheckoutStarted, trackPaidStripeSubscriptionCheckoutCompleted, trackStripeSubscriptionPaymentInfoSubmitted, } from '../services/checkoutCompletionAnalytics.service.js';
|
|
22
22
|
const defaultPaymentMethodLabels = ['Visa', 'Mastercard', 'Maestro', 'Discover'];
|
|
23
23
|
const stripeCheckoutV2Appearance = {
|
|
24
24
|
labels: 'above',
|
|
@@ -185,6 +185,12 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
185
185
|
}
|
|
186
186
|
await (onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess());
|
|
187
187
|
};
|
|
188
|
+
const trackPaymentInfoSubmitted = async () => {
|
|
189
|
+
if (checkoutAnalytics) {
|
|
190
|
+
await trackStripeSubscriptionPaymentInfoSubmitted(Object.assign({ checkoutSessionId }, checkoutAnalytics)).catch(() => 'analytics_rejected');
|
|
191
|
+
}
|
|
192
|
+
await (onPaymentInfoSubmitted === null || onPaymentInfoSubmitted === void 0 ? void 0 : onPaymentInfoSubmitted());
|
|
193
|
+
};
|
|
188
194
|
useEffect(() => {
|
|
189
195
|
if (effectiveSelectedMethod !== 'card' || typeof window === 'undefined') {
|
|
190
196
|
return;
|
|
@@ -250,7 +256,7 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
250
256
|
setSubmitting(false);
|
|
251
257
|
return;
|
|
252
258
|
}
|
|
253
|
-
await (
|
|
259
|
+
await trackPaymentInfoSubmitted();
|
|
254
260
|
const result = await checkoutState.checkout.confirm({
|
|
255
261
|
redirect: 'if_required',
|
|
256
262
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AvailablePaymentMethods, StripeCheckoutExpressCheckoutElementOptions } from '@stripe/stripe-js';
|
|
2
|
-
import { type StripeSubscriptionCheckoutAnalyticsContext } from '
|
|
2
|
+
import { type StripeSubscriptionCheckoutAnalyticsContext } from '../services/checkoutCompletionAnalytics.service.js';
|
|
3
3
|
export type StripeCheckoutExpressCheckoutButtonProps = {
|
|
4
4
|
amountCents: number;
|
|
5
5
|
beforeConfirm?: () => Promise<string | null>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { ExpressCheckoutElement, useCheckout, } from '@stripe/react-stripe-js/checkout';
|
|
5
|
-
import { queueStripeSubscriptionCheckoutStarted, trackPaidStripeSubscriptionCheckoutCompleted, } from '
|
|
5
|
+
import { queueStripeSubscriptionCheckoutStarted, trackPaidStripeSubscriptionCheckoutCompleted, trackStripeSubscriptionPaymentInfoSubmitted, } from '../services/checkoutCompletionAnalytics.service.js';
|
|
6
6
|
import { getUnsupportedCheckoutCountryMessage, normalizeSupportedCheckoutCountries, } from './checkoutCountries.js';
|
|
7
7
|
const ExpressCheckoutElementWithCancel = ExpressCheckoutElement;
|
|
8
8
|
const buildDefaultOptions = () => ({
|
|
@@ -143,6 +143,9 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, checkoutAna
|
|
|
143
143
|
event.paymentFailed({ reason: 'invalid_payment_data', message });
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
|
+
if (checkoutAnalytics) {
|
|
147
|
+
await trackStripeSubscriptionPaymentInfoSubmitted(Object.assign({ checkoutSessionId }, checkoutAnalytics)).catch(() => 'analytics_rejected');
|
|
148
|
+
}
|
|
146
149
|
await (onPaymentInfoSubmitted === null || onPaymentInfoSubmitted === void 0 ? void 0 : onPaymentInfoSubmitted());
|
|
147
150
|
const result = await checkoutState.checkout.confirm(Object.assign(Object.assign({}, (confirmEmail
|
|
148
151
|
? { email: preparedCustomerEmail || (customerEmail === null || customerEmail === void 0 ? void 0 : customerEmail.trim()) || undefined }
|
package/dist/{components/shared → providers/stripe/components}/StripeExpressCheckoutButton.d.ts
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AvailablePaymentMethods, StripeExpressCheckoutElementOptions } from '@stripe/stripe-js';
|
|
2
|
-
import { type StripeSubscriptionCheckoutAnalyticsContext } from '
|
|
2
|
+
import { type StripeSubscriptionCheckoutAnalyticsContext } from '../services/checkoutCompletionAnalytics.service.js';
|
|
3
3
|
export type StripeExpressCheckoutButtonProps = {
|
|
4
4
|
amountCents: number;
|
|
5
5
|
beforeConfirm?: () => Promise<string | null>;
|
package/dist/{components/shared → providers/stripe/components}/StripeExpressCheckoutButton.js
RENAMED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useMemo, useState } from 'react';
|
|
4
4
|
import { ExpressCheckoutElement, useElements, useStripe } from '@stripe/react-stripe-js';
|
|
5
|
-
import { queueStripeSubscriptionCheckoutStarted, } from '
|
|
5
|
+
import { queueStripeSubscriptionCheckoutStarted, trackStripeSubscriptionPaymentInfoSubmitted, } from '../services/checkoutCompletionAnalytics.service.js';
|
|
6
6
|
const normalizeBillingName = (input) => {
|
|
7
7
|
var _a, _b, _c;
|
|
8
8
|
const normalizedName = (_a = input.name) === null || _a === void 0 ? void 0 : _a.trim();
|
|
@@ -105,6 +105,9 @@ export function StripeExpressCheckoutButton({ amountCents, beforeConfirm, checko
|
|
|
105
105
|
event.paymentFailed({ reason: 'invalid_payment_data', message });
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
108
|
+
if (checkoutAnalytics) {
|
|
109
|
+
await trackStripeSubscriptionPaymentInfoSubmitted(Object.assign({ checkoutSessionId }, checkoutAnalytics)).catch(() => 'analytics_rejected');
|
|
110
|
+
}
|
|
108
111
|
await (onPaymentInfoSubmitted === null || onPaymentInfoSubmitted === void 0 ? void 0 : onPaymentInfoSubmitted());
|
|
109
112
|
const result = await stripe.confirmPayment({
|
|
110
113
|
elements,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import { type PaywallPlan } from '
|
|
2
|
+
import { type PaywallPlan } from '../services/stripe.service.js';
|
|
3
3
|
type StripePlanSelectorProps = {
|
|
4
4
|
plans?: readonly PaywallPlan[] | null;
|
|
5
5
|
selectedPlanId: string | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useMemo } from 'react';
|
|
4
|
-
import { findPaywallPlan, getDefaultPlanSelectionValue, } from '
|
|
4
|
+
import { findPaywallPlan, getDefaultPlanSelectionValue, } from '../services/stripe.service.js';
|
|
5
5
|
export function StripePlanSelector({ plans, selectedPlanId, onSelectPlan, loading = false, error = null, className, loadingClassName, errorClassName, renderPlan, }) {
|
|
6
6
|
const safePlans = useMemo(() => {
|
|
7
7
|
return Array.isArray(plans) ? plans : [];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { Appearance, StripeCheckoutExpressCheckoutElementOptions } from '@stripe/stripe-js';
|
|
3
|
-
import { type PlatformWalletPaymentMethod } from '
|
|
4
|
-
import type { StripeSubscriptionCheckoutAnalyticsContext } from '
|
|
5
|
-
import { type StripeSubscriptionCheckoutSessionInput } from '
|
|
3
|
+
import { type PlatformWalletPaymentMethod } from './walletPlatform.js';
|
|
4
|
+
import type { StripeSubscriptionCheckoutAnalyticsContext } from '../services/checkoutCompletionAnalytics.service.js';
|
|
5
|
+
import { type StripeSubscriptionCheckoutSessionInput } from '../hooks/useStripeSubscriptionCheckoutSession.js';
|
|
6
6
|
export type StripeSubscriptionWalletSurfaceCheckoutInput = Omit<StripeSubscriptionCheckoutSessionInput, 'onError'> & {
|
|
7
7
|
customerName?: string | null;
|
|
8
8
|
};
|
|
@@ -12,10 +12,10 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
};
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
14
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
15
|
-
import { usePlatformWalletPaymentMethods, } from '
|
|
15
|
+
import { usePlatformWalletPaymentMethods, } from './walletPlatform.js';
|
|
16
16
|
import { ApplePaySubscriptionCheckoutSlot } from './ApplePaySubscriptionCheckoutSlot.js';
|
|
17
17
|
import { GooglePaySubscriptionCheckoutSlot } from './GooglePaySubscriptionCheckoutSlot.js';
|
|
18
|
-
import { useStripeSubscriptionCheckoutSession, } from '
|
|
18
|
+
import { useStripeSubscriptionCheckoutSession, } from '../hooks/useStripeSubscriptionCheckoutSession.js';
|
|
19
19
|
export function buildStripeSubscriptionWalletSurfaceAnalyticsMetadata(analyticsMetadata, surfaceId) {
|
|
20
20
|
return Object.assign(Object.assign({}, (analyticsMetadata !== null && analyticsMetadata !== void 0 ? analyticsMetadata : {})), { checkoutSurfaceId: surfaceId });
|
|
21
21
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { Appearance, AvailablePaymentMethods, StripeCheckoutExpressCheckoutElementOptions } from '@stripe/stripe-js';
|
|
3
|
-
import { type StripeSubscriptionCheckoutAnalyticsContext } from '
|
|
4
|
-
import { type StripeSubscriptionCheckoutSession } from '
|
|
3
|
+
import { type StripeSubscriptionCheckoutAnalyticsContext } from '../services/checkoutCompletionAnalytics.service.js';
|
|
4
|
+
import { type StripeSubscriptionCheckoutSession } from '../hooks/useStripeSubscriptionCheckoutSession.js';
|
|
5
5
|
export type WalletSubscriptionCheckoutRenderStateInput = {
|
|
6
6
|
expressCheckoutAllowed: boolean;
|
|
7
7
|
hasActiveClientSecret: boolean;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
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
|
-
import { StripeExpressCheckoutElement } from '
|
|
5
|
-
import { trackStripeSubscriptionCheckoutStarted, } from '
|
|
6
|
-
import { toAnalyticsPaymentMethod } from '
|
|
7
|
-
import { isInactiveCheckoutSessionError, } from '
|
|
4
|
+
import { StripeExpressCheckoutElement } from './StripeExpressCheckoutElement.js';
|
|
5
|
+
import { trackStripeSubscriptionCheckoutStarted, } from '../services/checkoutCompletionAnalytics.service.js';
|
|
6
|
+
import { toAnalyticsPaymentMethod } from '../../../services/paymentMethodAnalytics.service.js';
|
|
7
|
+
import { isInactiveCheckoutSessionError, } from '../hooks/useStripeSubscriptionCheckoutSession.js';
|
|
8
8
|
export function getWalletSubscriptionCheckoutRenderState({ expressCheckoutAllowed, hasActiveClientSecret, hasStripePromise, suspended, walletAvailable, walletPreparing, }) {
|
|
9
9
|
const shouldRenderExpressCheckout = !suspended &&
|
|
10
10
|
expressCheckoutAllowed &&
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './ApplePaySubscribeButton.js';
|
|
2
|
+
export * from './ApplePaySubscriptionCheckoutSlot.js';
|
|
3
|
+
export * from './GooglePaySubscribeButton.js';
|
|
4
|
+
export * from './GooglePaySubscriptionCheckoutSlot.js';
|
|
5
|
+
export * from './SharedStripeCheckoutDialog.js';
|
|
6
|
+
export * from './SharedStripeCheckoutV2Dialog.js';
|
|
7
|
+
export * from './StripeCheckoutExpressCheckoutButton.js';
|
|
8
|
+
export * from './StripeExpressCheckoutButton.js';
|
|
9
|
+
export * from './StripeExpressCheckoutElement.js';
|
|
10
|
+
export * from './StripePlanSelector.js';
|
|
11
|
+
export * from './StripeSubscriptionWalletSurface.js';
|
|
12
|
+
export * from './WalletSubscriptionCheckoutSlot.js';
|
|
13
|
+
export * from './walletPlatform.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './ApplePaySubscribeButton.js';
|
|
2
|
+
export * from './ApplePaySubscriptionCheckoutSlot.js';
|
|
3
|
+
export * from './GooglePaySubscribeButton.js';
|
|
4
|
+
export * from './GooglePaySubscriptionCheckoutSlot.js';
|
|
5
|
+
export * from './SharedStripeCheckoutDialog.js';
|
|
6
|
+
export * from './SharedStripeCheckoutV2Dialog.js';
|
|
7
|
+
export * from './StripeCheckoutExpressCheckoutButton.js';
|
|
8
|
+
export * from './StripeExpressCheckoutButton.js';
|
|
9
|
+
export * from './StripeExpressCheckoutElement.js';
|
|
10
|
+
export * from './StripePlanSelector.js';
|
|
11
|
+
export * from './StripeSubscriptionWalletSurface.js';
|
|
12
|
+
export * from './WalletSubscriptionCheckoutSlot.js';
|
|
13
|
+
export * from './walletPlatform.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type RuntimeMode } from '@funnelsgrove/runtime';
|
|
2
|
-
import type { BillingFallbackPlanConfig, BillingPlanInputCatalog } from '
|
|
2
|
+
import type { BillingFallbackPlanConfig, BillingPlanInputCatalog } from '../../../config/billing.config.js';
|
|
3
3
|
import { type PaywallPlan, type PaywallPlanResolutionOptions } from '../services/stripe.service.js';
|
|
4
4
|
type UseResolvedPaywallPlansInput = {
|
|
5
5
|
runtimeMode: RuntimeMode;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import { isPreviewFrameRuntime } from '@funnelsgrove/runtime';
|
|
4
4
|
import { getFallbackPlans, getPaywallPlans, } from '../services/stripe.service.js';
|
|
5
|
-
import { isBillingPlanMappingCatalog } from '
|
|
5
|
+
import { isBillingPlanMappingCatalog } from '../../../services/planCatalog.service.js';
|
|
6
6
|
export const useResolvedPaywallPlans = ({ runtimeMode, planCatalog, resolutionOptions, previewPlans, }) => {
|
|
7
7
|
const fallbackPlans = useMemo(() => getFallbackPlans(planCatalog, resolutionOptions), [planCatalog, resolutionOptions]);
|
|
8
8
|
const isMappingCatalog = Boolean(planCatalog) && !Array.isArray(planCatalog) && isBillingPlanMappingCatalog(planCatalog);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Stripe } from '@stripe/stripe-js';
|
|
2
2
|
import type { RuntimeMode } from '@funnelsgrove/runtime';
|
|
3
|
-
import { type CheckoutPreparationLoading, type CheckoutPreparationSource } from '
|
|
4
|
-
import { type PaywallPlan, type StripeRuntimeConfigOverrides } from '
|
|
3
|
+
import { type CheckoutPreparationLoading, type CheckoutPreparationSource } from '../../paymentProvider.types.js';
|
|
4
|
+
import { type PaywallPlan, type StripeRuntimeConfigOverrides } from '../services/stripe.service.js';
|
|
5
5
|
type StripeOneTimeCheckoutPlanInput = Pick<PaywallPlan, 'amountCents' | 'analyticsPurchaseValue' | 'description' | 'id' | 'providerPlanId' | 'title'>;
|
|
6
6
|
export type StripeOneTimeCheckoutSessionInput = {
|
|
7
7
|
analyticsMetadata?: Record<string, unknown> | null;
|
|
@@ -11,10 +11,10 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
14
|
-
import { createEmptyCheckoutPreparationLoading, } from '
|
|
15
|
-
import { createStripeOneTimeCheckout, getStripePromise, isStripeConfigured, } from '
|
|
14
|
+
import { createEmptyCheckoutPreparationLoading, } from '../../paymentProvider.types.js';
|
|
15
|
+
import { createStripeOneTimeCheckout, getStripePromise, isStripeConfigured, } from '../services/stripe.service.js';
|
|
16
16
|
import { isInactiveCheckoutSessionError } from './useStripeSubscriptionCheckoutSession.js';
|
|
17
|
-
import { toAnalyticsPaymentMethod } from '
|
|
17
|
+
import { toAnalyticsPaymentMethod } from '../../../services/paymentMethodAnalytics.service.js';
|
|
18
18
|
export function resolveStripeOneTimeCheckoutPreparationOptions(source, options = {}) {
|
|
19
19
|
var _a, _b;
|
|
20
20
|
const checkoutStartSource = (_a = options.checkoutStartSource) !== null && _a !== void 0 ? _a : (source === 'wallet' ? 'wallet_render' : 'card_click');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Stripe } from '@stripe/stripe-js';
|
|
2
2
|
import type { RuntimeMode } from '@funnelsgrove/runtime';
|
|
3
|
-
import { type CheckoutPreparationLoading, type CheckoutPreparationSource } from '
|
|
4
|
-
import type { PaywallDisplayPlan } from '
|
|
5
|
-
import { type PaywallPlan, type StripeRuntimeConfigOverrides } from '
|
|
3
|
+
import { type CheckoutPreparationLoading, type CheckoutPreparationSource } from '../../paymentProvider.types.js';
|
|
4
|
+
import type { PaywallDisplayPlan } from '../../../services/paywallOffer.service.js';
|
|
5
|
+
import { type PaywallPlan, type StripeRuntimeConfigOverrides } from '../services/stripe.service.js';
|
|
6
6
|
export type StripeSubscriptionCheckoutSessionInput = {
|
|
7
7
|
analyticsMetadata?: Record<string, unknown> | null;
|
|
8
8
|
checkoutMode: RuntimeMode;
|
|
@@ -11,9 +11,9 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
14
|
-
import { createEmptyCheckoutPreparationLoading, } from '
|
|
15
|
-
import { createStripeSubscriptionCheckout, getStripePromise, isStripeConfigured, updateStripeSubscriptionCheckoutPlan, } from '
|
|
16
|
-
import { toAnalyticsPaymentMethod } from '
|
|
14
|
+
import { createEmptyCheckoutPreparationLoading, } from '../../paymentProvider.types.js';
|
|
15
|
+
import { createStripeSubscriptionCheckout, getStripePromise, isStripeConfigured, updateStripeSubscriptionCheckoutPlan, } from '../services/stripe.service.js';
|
|
16
|
+
import { toAnalyticsPaymentMethod } from '../../../services/paymentMethodAnalytics.service.js';
|
|
17
17
|
export function resolveStripeSubscriptionCheckoutPreparationOptions(source, options = {}) {
|
|
18
18
|
var _a, _b;
|
|
19
19
|
const checkoutStartSource = (_a = options.checkoutStartSource) !== null && _a !== void 0 ? _a : (source === 'wallet' ? 'wallet_render' : 'card_click');
|
package/dist/{services → providers/stripe/services}/checkoutCompletionAnalytics.service.d.ts
RENAMED
|
@@ -18,8 +18,13 @@ export type TrackStripeSubscriptionCheckoutStartedInput = StripeSubscriptionChec
|
|
|
18
18
|
export type TrackPaidStripeSubscriptionCheckoutCompletedInput = StripeSubscriptionCheckoutAnalyticsContext & {
|
|
19
19
|
checkoutSessionId?: string | null;
|
|
20
20
|
};
|
|
21
|
+
export type TrackStripeSubscriptionPaymentInfoSubmittedInput = StripeSubscriptionCheckoutAnalyticsContext & {
|
|
22
|
+
checkoutSessionId?: string | null;
|
|
23
|
+
};
|
|
21
24
|
export type TrackStripeSubscriptionCheckoutStartedResult = 'already_tracked' | 'analytics_rejected' | 'missing_checkout_session' | 'tracked';
|
|
22
25
|
export type TrackPaidStripeSubscriptionCheckoutCompletedResult = 'already_tracked' | 'analytics_rejected' | 'missing_checkout_session' | 'tracked' | 'unpaid';
|
|
26
|
+
export type TrackStripeSubscriptionPaymentInfoSubmittedResult = 'already_tracked' | 'analytics_rejected' | 'missing_checkout_session' | 'tracked';
|
|
23
27
|
export declare function trackStripeSubscriptionCheckoutStarted(input: TrackStripeSubscriptionCheckoutStartedInput): Promise<TrackStripeSubscriptionCheckoutStartedResult>;
|
|
24
28
|
export declare function queueStripeSubscriptionCheckoutStarted(input: TrackStripeSubscriptionCheckoutStartedInput): void;
|
|
29
|
+
export declare function trackStripeSubscriptionPaymentInfoSubmitted(input: TrackStripeSubscriptionPaymentInfoSubmittedInput): Promise<TrackStripeSubscriptionPaymentInfoSubmittedResult>;
|
|
25
30
|
export declare function trackPaidStripeSubscriptionCheckoutCompleted(input: TrackPaidStripeSubscriptionCheckoutCompletedInput): Promise<TrackPaidStripeSubscriptionCheckoutCompletedResult>;
|
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import { publicAnalyticsSdk, } from '@funnelsgrove/analytics';
|
|
13
13
|
import { verifyStripeSubscriptionCheckoutPayment, } from './stripe.service.js';
|
|
14
|
-
import { toAnalyticsPaymentMethod } from '
|
|
14
|
+
import { toAnalyticsPaymentMethod } from '../../../services/paymentMethodAnalytics.service.js';
|
|
15
15
|
const asRecord = (value) => {
|
|
16
16
|
return value && typeof value === 'object' && !Array.isArray(value)
|
|
17
17
|
? value
|
|
@@ -19,6 +19,7 @@ const asRecord = (value) => {
|
|
|
19
19
|
};
|
|
20
20
|
const activeCheckoutCompletionKeys = new Set();
|
|
21
21
|
const activeCheckoutStartedKeys = new Set();
|
|
22
|
+
const activePaymentInfoSubmittedKeys = new Set();
|
|
22
23
|
const buildCheckoutStorageKey = (eventName, checkoutSessionId, runtimeConfig) => {
|
|
23
24
|
var _a;
|
|
24
25
|
const funnelId = ((_a = runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelId) === null || _a === void 0 ? void 0 : _a.trim()) || 'unknown_funnel';
|
|
@@ -92,6 +93,45 @@ export async function trackStripeSubscriptionCheckoutStarted(input) {
|
|
|
92
93
|
export function queueStripeSubscriptionCheckoutStarted(input) {
|
|
93
94
|
void trackStripeSubscriptionCheckoutStarted(input).catch(() => undefined);
|
|
94
95
|
}
|
|
96
|
+
export async function trackStripeSubscriptionPaymentInfoSubmitted(input) {
|
|
97
|
+
var _a;
|
|
98
|
+
const checkoutSessionId = ((_a = input.checkoutSessionId) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
99
|
+
if (!checkoutSessionId) {
|
|
100
|
+
return 'missing_checkout_session';
|
|
101
|
+
}
|
|
102
|
+
const storageKey = buildCheckoutStorageKey('add_payment_info', checkoutSessionId, input.runtimeConfig);
|
|
103
|
+
if (activePaymentInfoSubmittedKeys.has(storageKey)
|
|
104
|
+
|| hasTrackedCheckoutSession('add_payment_info', checkoutSessionId, input.runtimeConfig)) {
|
|
105
|
+
return 'already_tracked';
|
|
106
|
+
}
|
|
107
|
+
activePaymentInfoSubmittedKeys.add(storageKey);
|
|
108
|
+
try {
|
|
109
|
+
let eventId = null;
|
|
110
|
+
try {
|
|
111
|
+
eventId = publicAnalyticsSdk.trackPaymentInfoSubmitted({
|
|
112
|
+
eventId: `add_payment_info:${checkoutSessionId}`,
|
|
113
|
+
featureFlags: input.featureFlags,
|
|
114
|
+
stepId: input.stepId,
|
|
115
|
+
stepName: input.stepName,
|
|
116
|
+
stepType: input.stepType,
|
|
117
|
+
stepContractVersion: input.stepContractVersion,
|
|
118
|
+
metadata: Object.assign(Object.assign({}, asRecord(input.metadata)), { checkoutSessionId, checkout_session_id: checkoutSessionId, environment: input.environment || asRecord(input.metadata).environment, payment_provider: 'stripe' }),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (_b) {
|
|
122
|
+
// Analytics must not prevent Stripe confirmation.
|
|
123
|
+
}
|
|
124
|
+
if (!eventId) {
|
|
125
|
+
return 'analytics_rejected';
|
|
126
|
+
}
|
|
127
|
+
markCheckoutSessionTracked('add_payment_info', checkoutSessionId, input.runtimeConfig);
|
|
128
|
+
await publicAnalyticsSdk.flush().catch(() => 0);
|
|
129
|
+
return 'tracked';
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
activePaymentInfoSubmittedKeys.delete(storageKey);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
95
135
|
export async function trackPaidStripeSubscriptionCheckoutCompleted(input) {
|
|
96
136
|
var _a;
|
|
97
137
|
const checkoutSessionId = ((_a = input.checkoutSessionId) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type Stripe } from '@stripe/stripe-js';
|
|
2
|
-
import { type BillingFallbackPlanConfig, type BillingPlanCatalog, type BillingPlanInterval, type BillingPlanInputCatalog } from '
|
|
2
|
+
import { type BillingFallbackPlanConfig, type BillingPlanCatalog, type BillingPlanInterval, type BillingPlanInputCatalog } from '../../../config/billing.config.js';
|
|
3
3
|
import { type FunnelSdkRuntimeConfigOverrides, type ResolvedCountryPricing } from '@funnelsgrove/runtime';
|
|
4
4
|
import type { RuntimeMode } from '@funnelsgrove/runtime';
|
|
5
|
-
import { type RemoteProjectBillingPlan } from '
|
|
5
|
+
import { type RemoteProjectBillingPlan } from '../../../services/planCatalog.service.js';
|
|
6
6
|
export type PaywallPlan = {
|
|
7
7
|
id: string;
|
|
8
8
|
offerSetId?: string;
|
|
@@ -94,19 +94,25 @@ export declare function createStripeOneTimeCheckout(input: CreateOneTimeCheckout
|
|
|
94
94
|
* @deprecated Use createStripeOneTimeCheckout for one-time paywall checkout.
|
|
95
95
|
*/
|
|
96
96
|
export declare function createStripePaymentIntent(input: CreatePaymentIntentInput): Promise<CreatePaymentIntentResponse>;
|
|
97
|
-
type ChargeOneClickPaymentInput = {
|
|
97
|
+
export type ChargeOneClickPaymentInput = {
|
|
98
98
|
planId: string;
|
|
99
|
+
providerPlanId?: string | null;
|
|
99
100
|
amountCents: number;
|
|
100
101
|
analyticsMetadata?: Record<string, unknown> | null;
|
|
101
102
|
checkoutSessionId?: string | null;
|
|
102
103
|
currency?: string | null;
|
|
104
|
+
description?: string | null;
|
|
103
105
|
idempotencyKey?: string | null;
|
|
106
|
+
stripeCustomerId?: string | null;
|
|
107
|
+
userId?: string | null;
|
|
108
|
+
/** @deprecated Use stripeCustomerId. */
|
|
104
109
|
stripe_customer_id?: string | null;
|
|
110
|
+
/** @deprecated Use userId. */
|
|
105
111
|
user_id?: string | null;
|
|
106
112
|
environment?: RuntimeMode;
|
|
107
113
|
runtimeConfig?: StripeRuntimeConfigOverrides;
|
|
108
114
|
};
|
|
109
|
-
type ChargeOneClickPaymentResponse = {
|
|
115
|
+
export type ChargeOneClickPaymentResponse = {
|
|
110
116
|
paymentIntentId: string;
|
|
111
117
|
status: string;
|
|
112
118
|
amountCents?: number;
|
|
@@ -116,6 +122,14 @@ type ChargeOneClickPaymentResponse = {
|
|
|
116
122
|
stripePublishableKey?: string;
|
|
117
123
|
};
|
|
118
124
|
export declare function chargeStripeOneClickPayment(input: ChargeOneClickPaymentInput): Promise<ChargeOneClickPaymentResponse>;
|
|
125
|
+
export type CompleteStripeOneClickPaymentInput = ChargeOneClickPaymentInput & {
|
|
126
|
+
returnUrl: string;
|
|
127
|
+
};
|
|
128
|
+
export type CompleteStripeOneClickPaymentResponse = ChargeOneClickPaymentResponse & {
|
|
129
|
+
confirmationAttempted: boolean;
|
|
130
|
+
};
|
|
131
|
+
export declare const requiresStripeOneClickConfirmation: (status: string) => boolean;
|
|
132
|
+
export declare function completeStripeOneClickPayment(input: CompleteStripeOneClickPaymentInput): Promise<CompleteStripeOneClickPaymentResponse>;
|
|
119
133
|
type CreateSubscriptionCheckoutInput = {
|
|
120
134
|
plan: CheckoutSessionPlanInput;
|
|
121
135
|
couponId?: string | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { loadStripe } from '@stripe/stripe-js';
|
|
2
|
-
import { billingPlanList, } from '
|
|
2
|
+
import { billingPlanList, } from '../../../config/billing.config.js';
|
|
3
3
|
import { FUNNEL_ID, FUNNEL_SDK_PUBLISHABLE_KEY, funnelSdkService, } from '@funnelsgrove/runtime';
|
|
4
|
-
import { isBillingPlanMappingCatalog, resolveMappedProjectPlans, } from '
|
|
4
|
+
import { isBillingPlanMappingCatalog, resolveMappedProjectPlans, } from '../../../services/planCatalog.service.js';
|
|
5
5
|
const stripePromiseByKey = new Map();
|
|
6
6
|
const syncedPlansPromiseByMode = new Map();
|
|
7
7
|
export const buildPaywallPlanResolutionSignature = (options) => {
|
|
@@ -355,6 +355,9 @@ export function getPaywallPlanSelectionValue(plan) {
|
|
|
355
355
|
var _a;
|
|
356
356
|
return ((_a = plan.providerPlanId) === null || _a === void 0 ? void 0 : _a.trim()) || plan.id;
|
|
357
357
|
}
|
|
358
|
+
// The API resolves offer-set mappings by the funnel plan key. Stripe's price id travels in
|
|
359
|
+
// providerPlanId; duplicating it into planId bypasses the configured test/live offer mapping.
|
|
360
|
+
const getPaywallPlanRequestId = (plan) => plan.id.trim() || getPaywallPlanSelectionValue(plan);
|
|
358
361
|
export function findPaywallPlan(plans, selectionValue) {
|
|
359
362
|
const normalizedSelectionValue = (selectionValue === null || selectionValue === void 0 ? void 0 : selectionValue.trim()) || '';
|
|
360
363
|
if (!normalizedSelectionValue) {
|
|
@@ -554,7 +557,7 @@ export async function createStripeOneTimeCheckout(input) {
|
|
|
554
557
|
return funnelSdkService.createOneTimeCheckout({
|
|
555
558
|
offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
556
559
|
offerSetKey: ((_b = input.plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
557
|
-
planId:
|
|
560
|
+
planId: getPaywallPlanRequestId(input.plan),
|
|
558
561
|
providerPlanId: ((_c = input.plan.providerPlanId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
559
562
|
title: input.plan.title,
|
|
560
563
|
description: ((_d = input.plan.description) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
@@ -586,20 +589,52 @@ export async function createStripePaymentIntent(input) {
|
|
|
586
589
|
});
|
|
587
590
|
}
|
|
588
591
|
export async function chargeStripeOneClickPayment(input) {
|
|
589
|
-
var _a, _b, _c, _d, _e;
|
|
592
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
590
593
|
return funnelSdkService.chargeOneClickPayment({
|
|
591
594
|
planId: input.planId,
|
|
595
|
+
providerPlanId: ((_a = input.providerPlanId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
592
596
|
amountCents: input.amountCents,
|
|
593
|
-
currency: ((
|
|
597
|
+
currency: ((_b = input.currency) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
598
|
+
description: ((_c = input.description) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
594
599
|
analyticsMetadata: normalizeAnalyticsMetadata(input.analyticsMetadata),
|
|
595
|
-
userId: ((
|
|
596
|
-
stripeCustomerId: ((
|
|
597
|
-
checkoutSessionId: ((
|
|
598
|
-
idempotencyKey: ((
|
|
600
|
+
userId: ((_d = input.userId) === null || _d === void 0 ? void 0 : _d.trim()) || ((_e = input.user_id) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
601
|
+
stripeCustomerId: ((_f = input.stripeCustomerId) === null || _f === void 0 ? void 0 : _f.trim()) || ((_g = input.stripe_customer_id) === null || _g === void 0 ? void 0 : _g.trim()) || undefined,
|
|
602
|
+
checkoutSessionId: ((_h = input.checkoutSessionId) === null || _h === void 0 ? void 0 : _h.trim()) || undefined,
|
|
603
|
+
idempotencyKey: ((_j = input.idempotencyKey) === null || _j === void 0 ? void 0 : _j.trim()) || undefined,
|
|
599
604
|
environment: input.environment,
|
|
600
605
|
runtimeConfig: input.runtimeConfig,
|
|
601
606
|
});
|
|
602
607
|
}
|
|
608
|
+
export const requiresStripeOneClickConfirmation = (status) => {
|
|
609
|
+
return status === 'requires_action' || status === 'requires_confirmation';
|
|
610
|
+
};
|
|
611
|
+
export async function completeStripeOneClickPayment(input) {
|
|
612
|
+
var _a, _b, _c, _d, _e, _f;
|
|
613
|
+
const payment = await chargeStripeOneClickPayment(input);
|
|
614
|
+
if (!requiresStripeOneClickConfirmation(payment.status)) {
|
|
615
|
+
return Object.assign(Object.assign({}, payment), { confirmationAttempted: false });
|
|
616
|
+
}
|
|
617
|
+
const clientSecret = (_a = payment.clientSecret) === null || _a === void 0 ? void 0 : _a.trim();
|
|
618
|
+
const stripePublishableKey = (_b = payment.stripePublishableKey) === null || _b === void 0 ? void 0 : _b.trim();
|
|
619
|
+
if (!clientSecret || !stripePublishableKey) {
|
|
620
|
+
throw new Error('One-click payment requires Stripe confirmation, but confirmation details are missing.');
|
|
621
|
+
}
|
|
622
|
+
const stripe = await getStripePromise((_d = (_c = payment.environment) !== null && _c !== void 0 ? _c : input.environment) !== null && _d !== void 0 ? _d : 'live', stripePublishableKey);
|
|
623
|
+
if (!stripe) {
|
|
624
|
+
throw new Error('Stripe could not be initialized for one-click payment confirmation.');
|
|
625
|
+
}
|
|
626
|
+
const confirmation = await stripe.confirmPayment({
|
|
627
|
+
clientSecret,
|
|
628
|
+
confirmParams: {
|
|
629
|
+
return_url: input.returnUrl,
|
|
630
|
+
},
|
|
631
|
+
redirect: 'if_required',
|
|
632
|
+
});
|
|
633
|
+
if (confirmation.error) {
|
|
634
|
+
throw new Error(confirmation.error.message || 'Unable to confirm one-click payment.');
|
|
635
|
+
}
|
|
636
|
+
return Object.assign(Object.assign({}, payment), { status: (_f = (_e = confirmation.paymentIntent) === null || _e === void 0 ? void 0 : _e.status) !== null && _f !== void 0 ? _f : payment.status, confirmationAttempted: true });
|
|
637
|
+
}
|
|
603
638
|
export async function createStripeSubscriptionCheckout(input) {
|
|
604
639
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
605
640
|
const recurring = resolveCheckoutPlanRecurringConfig(input.plan);
|
|
@@ -609,7 +644,7 @@ export async function createStripeSubscriptionCheckout(input) {
|
|
|
609
644
|
return funnelSdkService.createSubscriptionCheckout({
|
|
610
645
|
offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
611
646
|
offerSetKey: ((_b = input.plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
612
|
-
planId:
|
|
647
|
+
planId: getPaywallPlanRequestId(input.plan),
|
|
613
648
|
providerPlanId: ((_c = input.plan.providerPlanId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
614
649
|
title: input.plan.title,
|
|
615
650
|
description: ((_d = input.plan.description) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
@@ -640,7 +675,7 @@ export async function updateStripeSubscriptionCheckoutPlan(input) {
|
|
|
640
675
|
checkoutSessionId: input.checkoutSessionId.trim(),
|
|
641
676
|
offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
642
677
|
offerSetKey: ((_b = input.plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
643
|
-
planId:
|
|
678
|
+
planId: getPaywallPlanRequestId(input.plan),
|
|
644
679
|
providerPlanId: ((_c = input.plan.providerPlanId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
645
680
|
title: input.plan.title,
|
|
646
681
|
description: ((_d = input.plan.description) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
@@ -680,7 +715,7 @@ export async function createStripeCheckoutSession(input) {
|
|
|
680
715
|
return funnelSdkService.createHostedCheckoutSession({
|
|
681
716
|
offerSetId: ((_a = input.plan.offerSetId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
682
717
|
offerSetKey: ((_b = input.plan.offerSetKey) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
683
|
-
planId:
|
|
718
|
+
planId: getPaywallPlanRequestId(input.plan),
|
|
684
719
|
providerPlanId: ((_c = input.plan.providerPlanId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
685
720
|
title: input.plan.title,
|
|
686
721
|
description: ((_d = input.plan.description) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './walletCheckoutSmoke.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './walletCheckoutSmoke.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BillingDiscountCatalog, BillingDiscountList } from '../config/billing.config.js';
|
|
2
|
-
import type { PaywallPlan } from '
|
|
2
|
+
import type { PaywallPlan } from '../providers/stripe/services/stripe.service.js';
|
|
3
3
|
export type PaywallDiscountCatalog = BillingDiscountCatalog;
|
|
4
4
|
export type PaywallDiscountStage = 'first' | 'second' | 'completed';
|
|
5
5
|
export type PaywallActiveDiscountStage = Exclude<PaywallDiscountStage, 'completed'>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type FunnelExperimentDefinition, type FunnelManifestExperiment, type OfferSetRuntimePlanOverrides, type ResolvedFunnelRuntimeConfig, type ResolvedPublishedExperiments, type RuntimeMode } from '@funnelsgrove/runtime';
|
|
2
2
|
import type { BillingDiscountCatalog, BillingDiscountList, BillingFallbackPlanConfig, BillingPlanCatalog } from '../config/billing.config.js';
|
|
3
|
-
import { type PaywallPlan } from '
|
|
3
|
+
import { type PaywallPlan } from '../providers/stripe/services/stripe.service.js';
|
|
4
4
|
export type PublishedBillingPlan = BillingFallbackPlanConfig & OfferSetRuntimePlanOverrides;
|
|
5
5
|
export type ResolvedPublishedBillingRuntime = {
|
|
6
6
|
revisionId: string | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveGeneratedOfferSetRuntime, resolvePublishedOfferSetSelection, resolvePublishedRuntimeExperiments, } from '@funnelsgrove/runtime';
|
|
2
2
|
import { buildBillingDiscountCatalog } from './paywallOffer.service.js';
|
|
3
|
-
import { buildConfigPaywallPlans } from '
|
|
3
|
+
import { buildConfigPaywallPlans, } from '../providers/stripe/services/stripe.service.js';
|
|
4
4
|
export const resolvePublishedBillingRuntime = ({ config, featureFlags, mode, search = '', defaultOfferSetId, baseCatalogsByMode, fallbackDiscounts, resolvedExperiments = resolvePublishedRuntimeExperiments(config), }) => {
|
|
5
5
|
var _a, _b;
|
|
6
6
|
const offerSets = (_a = config === null || config === void 0 ? void 0 : config.offerSets) !== null && _a !== void 0 ? _a : [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnelsgrove/payments",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/The-Solid-Grove/funnelsgrove.git",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"test:run": "vitest run --passWithNoTests"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@funnelsgrove/analytics": "^0.1.
|
|
36
|
-
"@funnelsgrove/runtime": "^0.7.
|
|
35
|
+
"@funnelsgrove/analytics": "^0.1.52",
|
|
36
|
+
"@funnelsgrove/runtime": "^0.7.3",
|
|
37
37
|
"@stripe/react-stripe-js": "^5.6.0",
|
|
38
38
|
"@stripe/stripe-js": "^8.7.0",
|
|
39
39
|
"react": "19.2.3",
|
/package/dist/{components/shared → providers/stripe/components}/ApplePaySubscribeButton.d.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/{components/shared → providers/stripe/components}/GooglePaySubscribeButton.d.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/{components/shared → providers/stripe/components}/StripeExpressCheckoutElement.d.ts
RENAMED
|
File without changes
|
/package/dist/{components/shared → providers/stripe/components}/StripeExpressCheckoutElement.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|