@funnelsgrove/payments 0.1.46 → 0.1.48
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 +70 -52
- package/dist/index.d.ts +5 -5
- package/dist/index.js +11 -5
- package/dist/services/stripe.service.d.ts +2 -7
- package/dist/services/stripe.service.js +72 -218
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,70 +2,88 @@
|
|
|
2
2
|
|
|
3
3
|
Shared billing and checkout helpers for funnels.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Read this file before editing checkout code. Deeper implementation docs:
|
|
6
6
|
|
|
7
7
|
- [Shared Payments](../../docs/funnel-sdk/shared-payments.md)
|
|
8
|
-
- [Funnel
|
|
8
|
+
- [Funnel SDK runtime service](../../docs/funnel-sdk/funnel-api.md)
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Owns provider-backed checkout primitives
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
- Publish from the repo root with `npm publish --workspace @funnelsgrove/payments --access public`.
|
|
14
|
-
- The package pins `@funnelsgrove/runtime` to the same exact version and the build resolves against the runtime package's emitted `dist` contract.
|
|
15
|
-
- The build normalizes generated relative ESM imports to explicit `.js` files for published package consumers.
|
|
12
|
+
`@funnelsgrove/payments` owns reusable payment contracts, provider adapters, checkout-session helpers, wallet slots, and checkout UI primitives. Funnel code owns paywall layout, copy, when an offer opens, post-payment navigation, and funnel-specific analytics timing.
|
|
16
13
|
|
|
17
|
-
##
|
|
14
|
+
## Current Checkout Path
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
|
|
16
|
+
Use these for new subscription paywalls:
|
|
17
|
+
|
|
18
|
+
- `useStripeSubscriptionCheckoutSession`
|
|
19
|
+
- `SharedStripeCheckoutV2Dialog`
|
|
20
|
+
- `ApplePaySubscriptionCheckoutSlot`
|
|
21
|
+
- `GooglePaySubscriptionCheckoutSlot`
|
|
22
|
+
- `WalletSubscriptionCheckoutSlot`
|
|
23
|
+
- `trackPaidStripeSubscriptionCheckoutCompleted`
|
|
24
|
+
|
|
25
|
+
Use `chargeStripeOneClickPayment` for post-checkout one-click upsells when the shared client helper fits the funnel. It delegates to `funnelSdkService.chargeOneClickPayment`.
|
|
26
|
+
|
|
27
|
+
## Compatibility-Only Surfaces
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Keep these exports available for saved drafts, old published artifacts, and controlled migrations. Do not use them for new subscription checkout work:
|
|
30
30
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
- keep provider-specific implementation under `src/providers/<provider>` so funnels can consume stable payment slots while future providers add their own adapters
|
|
31
|
+
- `createStripePaymentIntent`
|
|
32
|
+
- `SharedStripeCheckoutDialog`
|
|
33
|
+
- `ApplePaySubscribeButton`
|
|
34
|
+
- `GooglePaySubscribeButton`
|
|
35
|
+
- `APPLE_PAY_QR_CODE_URL`
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
When a live funnel still uses one of these, migrate the funnel deliberately with its own tests before removing the export.
|
|
38
|
+
|
|
39
|
+
## Use This Package For
|
|
39
40
|
|
|
40
41
|
- billing catalog types and normalization helpers
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- Stripe Express Checkout elements must stay mounted and measurable until Stripe reports availability; only hide the container after `onReady` or `onLoadError` reports that the requested wallet method is unavailable.
|
|
52
|
-
- Shared checkout dialogs must switch to card checkout when Stripe reports no requested wallet availability, so an unavailable Apple Pay or Google Pay shell never leaves a fake wallet tab blocking the card form.
|
|
53
|
-
- Wallet slots should not leave disabled grey placeholder shells blocking the paywall. While availability is unknown, the placeholder can sit behind Stripe's real wallet element; after Stripe reports unavailable or preparation cannot create a client secret, the placeholder must disappear instead of opening a card checkout under wallet branding.
|
|
54
|
-
- Checkout v2 owns only real Stripe Elements for card and wallet collection: Stripe controls the card-field placeholders, Stripe's `ExpressCheckoutElement` controls Apple Pay / Google Pay availability, desktop web can expose both wallet icons, and mobile narrows to Apple Pay on iOS or Google Pay on Android.
|
|
55
|
-
- Checkout v2 can receive a paywall-confirmed wallet availability hint and seed its wallet tab from that state, letting a checkout reopen keep Apple Pay or Google Pay visible while its own Express Checkout element remounts against the same client secret.
|
|
56
|
-
- Checkout v2 renders the wallet tab icons from the active platform wallet list and keeps Apple Pay / Google Pay marks large enough to read inside the tab.
|
|
57
|
-
- Checkout v2 keeps the fixed mobile dialog viewport-bound and scrolls the inner checkout shell so card fields, wallet controls, trust copy, and bottom actions remain reachable on short screens.
|
|
58
|
-
- Checkout v2 renders an editable email field when a funnel opens card checkout without a stored customer email, so direct preview paywall QA can complete Stripe confirmation instead of failing validation invisibly.
|
|
59
|
-
- The shared special-offer dialog can render a funnel-provided gift image while keeping the discount label overlaid and retaining the inline SVG fallback for funnels without a custom asset.
|
|
60
|
-
- the shared large-format Apple Pay and Google Pay subscribe CTAs, QR-code handoff link support, and the compact Visa / Mastercard / G Pay / Apple Pay image row used by the embedded checkout shell trust footer
|
|
61
|
-
- the Google Pay fallback CTA uses the downloaded Google Pay `G` mark paths, keeps at least 8px clear space, and matches Apple Pay's roughly 27px rendered subscribe text size until Stripe replaces it with the real wallet control
|
|
62
|
-
|
|
63
|
-
## What Does Not Belong Here
|
|
42
|
+
- runtime-mode-aware plan catalog selection
|
|
43
|
+
- Stripe SDK and public payment API client helpers
|
|
44
|
+
- subscription checkout-session preparation, reuse, update, and recovery
|
|
45
|
+
- reusable plan-selector UI
|
|
46
|
+
- shared embedded checkout dialogs
|
|
47
|
+
- Stripe Express Checkout wallet slots and lower-level wallet primitives
|
|
48
|
+
- generic timed-offer display helpers
|
|
49
|
+
- checkout completion analytics handoff to `@funnelsgrove/analytics`
|
|
50
|
+
|
|
51
|
+
## Do Not Use This Package For
|
|
64
52
|
|
|
65
53
|
- funnel routing
|
|
66
|
-
- funnel-owned analytics event definitions outside the shared checkout completion handoff
|
|
67
|
-
- funnel-owned step layout outside the shared checkout shell
|
|
68
|
-
- funnel-owned billing catalog entries
|
|
69
|
-
- funnel-specific decisions about when to activate or upgrade an offer
|
|
70
54
|
- manifest validation
|
|
55
|
+
- funnel-owned billing catalog entries
|
|
56
|
+
- funnel-specific paywall layout or copy
|
|
57
|
+
- funnel-specific decisions about when to activate, upgrade, or recover an offer
|
|
58
|
+
- analytics transport internals
|
|
71
59
|
- direct provider SDK calls inside funnel paywall steps; add provider adapters here first, then wire the funnel to the shared session or slot
|
|
60
|
+
|
|
61
|
+
## Public Surfaces
|
|
62
|
+
|
|
63
|
+
- `config/billing.config`: billing catalog, mapping, plan, and discount contracts.
|
|
64
|
+
- `services/planCatalog.service`: plan resolution and selection helpers.
|
|
65
|
+
- `services/runtimeBillingPlanCatalog.service`: test/live runtime catalog selection.
|
|
66
|
+
- `services/paywallOffer.service`: timed discount and display-plan helpers.
|
|
67
|
+
- `services/stripe.service`: Stripe loader, checkout-session, hosted checkout, one-click, and compatibility PaymentIntent clients.
|
|
68
|
+
- `providers/*`: provider-neutral checkout state and Stripe subscription checkout slots.
|
|
69
|
+
- `components/shared/*`: plan selector, checkout dialogs, Express Checkout wrappers, wallet placeholders, and trust assets.
|
|
70
|
+
- `testing/walletCheckoutSmoke`: wallet checkout smoke assertions.
|
|
71
|
+
|
|
72
|
+
## Engineering Rules
|
|
73
|
+
|
|
74
|
+
- Keep provider-specific implementation under `src/providers/<provider>`.
|
|
75
|
+
- Stripe owns real card fields and wallet controls. Local wallet buttons are placeholders until Stripe confirms availability.
|
|
76
|
+
- Wallet unavailable state must fall back to card/manual checkout or disappear.
|
|
77
|
+
- Do not create checkout sessions until the visitor taps a visible checkout CTA.
|
|
78
|
+
- Keep discount math reusable here, but keep offer activation timing in funnel code.
|
|
79
|
+
- Checkout metadata must avoid sensitive raw query params and use `@funnelsgrove/analytics` metadata helpers.
|
|
80
|
+
|
|
81
|
+
## Build, Test, Publish
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm run test:run --workspace @funnelsgrove/payments
|
|
85
|
+
npm run build --workspace @funnelsgrove/payments
|
|
86
|
+
npm publish --workspace @funnelsgrove/payments --access public
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The build normalizes generated relative ESM imports to explicit `.js` files for published package consumers.
|
package/dist/index.d.ts
CHANGED
|
@@ -13,13 +13,13 @@ export * from './providers/stripe/WalletSubscriptionCheckoutSlot.js';
|
|
|
13
13
|
export * from './providers/stripe/ApplePaySubscriptionCheckoutSlot.js';
|
|
14
14
|
export * from './providers/stripe/GooglePaySubscriptionCheckoutSlot.js';
|
|
15
15
|
export { ManageSubscriptionScreen, type ManageSubscriptionContent, type ManageSubscriptionScreenProps, } from './components/ManageSubscriptionScreen.js';
|
|
16
|
-
export * from './components/shared/SharedStripeCheckoutDialog.js';
|
|
17
16
|
export * from './components/shared/SharedStripeCheckoutV2Dialog.js';
|
|
18
|
-
export * from './components/shared/ApplePaySubscribeButton.js';
|
|
19
|
-
export * from './components/shared/GooglePaySubscribeButton.js';
|
|
20
|
-
export * from './components/shared/StripeCheckoutExpressCheckoutButton.js';
|
|
21
|
-
export * from './components/shared/StripeExpressCheckoutButton.js';
|
|
22
17
|
export * from './components/shared/StripeExpressCheckoutElement.js';
|
|
23
18
|
export * from './components/shared/StripePlanSelector.js';
|
|
24
19
|
export * from './components/shared/walletPlatform.js';
|
|
20
|
+
export * from './components/shared/StripeCheckoutExpressCheckoutButton.js';
|
|
21
|
+
export * from './components/shared/StripeExpressCheckoutButton.js';
|
|
22
|
+
export * from './components/shared/SharedStripeCheckoutDialog.js';
|
|
23
|
+
export * from './components/shared/ApplePaySubscribeButton.js';
|
|
24
|
+
export * from './components/shared/GooglePaySubscribeButton.js';
|
|
25
25
|
export * from './testing/walletCheckoutSmoke.js';
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
|
+
// Billing contracts and plan resolution.
|
|
1
2
|
export * from './config/billing.config.js';
|
|
2
3
|
export * from './services/preview-frame.service.js';
|
|
3
4
|
export * from './services/runtime-mode.service.js';
|
|
4
5
|
export * from './services/planCatalog.service.js';
|
|
5
6
|
export * from './services/runtimeBillingPlanCatalog.service.js';
|
|
6
7
|
export * from './services/paywallOffer.service.js';
|
|
8
|
+
// Stripe API clients and checkout completion handoff.
|
|
7
9
|
export * from './services/stripe.service.js';
|
|
8
10
|
export * from './services/checkoutCompletionAnalytics.service.js';
|
|
9
11
|
export * from './hooks/useResolvedPaywallPlans.js';
|
|
12
|
+
// Provider-neutral and Stripe subscription checkout primitives.
|
|
10
13
|
export * from './providers/paymentProvider.types.js';
|
|
11
14
|
export * from './providers/stripe/useStripeSubscriptionCheckoutSession.js';
|
|
12
15
|
export * from './providers/stripe/WalletSubscriptionCheckoutSlot.js';
|
|
13
16
|
export * from './providers/stripe/ApplePaySubscriptionCheckoutSlot.js';
|
|
14
17
|
export * from './providers/stripe/GooglePaySubscriptionCheckoutSlot.js';
|
|
18
|
+
// Shared checkout and subscription-management UI.
|
|
15
19
|
export { ManageSubscriptionScreen, } from './components/ManageSubscriptionScreen.js';
|
|
16
|
-
export * from './components/shared/SharedStripeCheckoutDialog.js';
|
|
17
20
|
export * from './components/shared/SharedStripeCheckoutV2Dialog.js';
|
|
18
|
-
export * from './components/shared/ApplePaySubscribeButton.js';
|
|
19
|
-
export * from './components/shared/GooglePaySubscribeButton.js';
|
|
20
|
-
export * from './components/shared/StripeCheckoutExpressCheckoutButton.js';
|
|
21
|
-
export * from './components/shared/StripeExpressCheckoutButton.js';
|
|
22
21
|
export * from './components/shared/StripeExpressCheckoutElement.js';
|
|
23
22
|
export * from './components/shared/StripePlanSelector.js';
|
|
24
23
|
export * from './components/shared/walletPlatform.js';
|
|
24
|
+
export * from './components/shared/StripeCheckoutExpressCheckoutButton.js';
|
|
25
|
+
export * from './components/shared/StripeExpressCheckoutButton.js';
|
|
26
|
+
// Compatibility-only surfaces kept for saved drafts and published artifacts.
|
|
27
|
+
export * from './components/shared/SharedStripeCheckoutDialog.js';
|
|
28
|
+
export * from './components/shared/ApplePaySubscribeButton.js';
|
|
29
|
+
export * from './components/shared/GooglePaySubscribeButton.js';
|
|
30
|
+
// QA helpers.
|
|
25
31
|
export * from './testing/walletCheckoutSmoke.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Stripe } from '@stripe/stripe-js';
|
|
2
2
|
import { type BillingFallbackPlanConfig, type BillingPlanCatalog, type BillingPlanInterval, type BillingPlanInputCatalog } from '../config/billing.config.js';
|
|
3
|
-
import { type ResolvedCountryPricing } from '@funnelsgrove/runtime';
|
|
3
|
+
import { type FunnelSdkRuntimeConfigOverrides, type ResolvedCountryPricing } from '@funnelsgrove/runtime';
|
|
4
4
|
import type { RuntimeMode } from '@funnelsgrove/runtime';
|
|
5
5
|
import { type RemoteProjectBillingPlan } from './planCatalog.service.js';
|
|
6
6
|
export type PaywallPlan = {
|
|
@@ -22,12 +22,7 @@ export type PaywallPlan = {
|
|
|
22
22
|
billingIntervalCount?: number;
|
|
23
23
|
source: 'stripe' | 'config';
|
|
24
24
|
};
|
|
25
|
-
export type StripeRuntimeConfigOverrides =
|
|
26
|
-
apiBaseUrl?: string | null;
|
|
27
|
-
funnelId?: string | null;
|
|
28
|
-
funnelVersionId?: string | null;
|
|
29
|
-
funnelSdkPublishableKey?: string | null;
|
|
30
|
-
};
|
|
25
|
+
export type StripeRuntimeConfigOverrides = FunnelSdkRuntimeConfigOverrides;
|
|
31
26
|
export type PaywallPlanResolutionOptions = {
|
|
32
27
|
locale?: string | null;
|
|
33
28
|
pricing?: ResolvedCountryPricing<string> | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var _a, _b, _c, _d;
|
|
2
2
|
import { loadStripe } from '@stripe/stripe-js';
|
|
3
3
|
import { billingPlanList, } from '../config/billing.config.js';
|
|
4
|
-
import {
|
|
4
|
+
import { FUNNEL_ID, FUNNEL_SDK_PUBLISHABLE_KEY, funnelSdkService, runtimeEnvConfig, } from '@funnelsgrove/runtime';
|
|
5
5
|
import { isBillingPlanMappingCatalog, resolveMappedProjectPlans, } from './planCatalog.service.js';
|
|
6
6
|
const STRIPE_TEST_PUBLISHABLE_KEY = ((_b = (_a = runtimeEnvConfig.stripeTestPublishableKey) !== null && _a !== void 0 ? _a : runtimeEnvConfig.stripePublishableKey) !== null && _b !== void 0 ? _b : '').trim();
|
|
7
7
|
const STRIPE_LIVE_PUBLISHABLE_KEY = ((_d = (_c = runtimeEnvConfig.stripeLivePublishableKey) !== null && _c !== void 0 ? _c : runtimeEnvConfig.stripePublishableKey) !== null && _d !== void 0 ? _d : '').trim();
|
|
@@ -26,35 +26,6 @@ const asTrimmedStringOrNull = (value) => {
|
|
|
26
26
|
const trimmed = value.trim();
|
|
27
27
|
return trimmed || null;
|
|
28
28
|
};
|
|
29
|
-
const trimTrailingSlash = (value) => {
|
|
30
|
-
return value.replace(/\/+$/, '');
|
|
31
|
-
};
|
|
32
|
-
const toNormalizedPath = (path) => {
|
|
33
|
-
return path.startsWith('/') ? path : `/${path}`;
|
|
34
|
-
};
|
|
35
|
-
const resolveStripeRuntimeConfig = (runtimeConfig) => {
|
|
36
|
-
var _a, _b, _c;
|
|
37
|
-
return {
|
|
38
|
-
apiBaseUrl: asTrimmedStringOrNull(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.apiBaseUrl),
|
|
39
|
-
funnelId: (_a = asTrimmedStringOrNull(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelId)) !== null && _a !== void 0 ? _a : asTrimmedStringOrNull(FUNNEL_ID),
|
|
40
|
-
funnelVersionId: (_b = asTrimmedStringOrNull(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelVersionId)) !== null && _b !== void 0 ? _b : asTrimmedStringOrNull(runtimeEnvConfig.funnelVersionId),
|
|
41
|
-
funnelSdkPublishableKey: resolvePreviewPaymentPublishableKey((_c = asTrimmedStringOrNull(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelSdkPublishableKey)) !== null && _c !== void 0 ? _c : asTrimmedStringOrNull(FUNNEL_SDK_PUBLISHABLE_KEY)) || null,
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
|
-
const buildStripeRuntimeApiUrl = (path, runtimeConfig) => {
|
|
45
|
-
const { apiBaseUrl } = resolveStripeRuntimeConfig(runtimeConfig);
|
|
46
|
-
if (!apiBaseUrl) {
|
|
47
|
-
return buildMainApiUrl(path);
|
|
48
|
-
}
|
|
49
|
-
return `${trimTrailingSlash(apiBaseUrl)}${toNormalizedPath(path)}`;
|
|
50
|
-
};
|
|
51
|
-
const buildStripeRuntimeHeaders = (runtimeConfig, headers) => {
|
|
52
|
-
const { funnelSdkPublishableKey } = resolveStripeRuntimeConfig(runtimeConfig);
|
|
53
|
-
if (!funnelSdkPublishableKey) {
|
|
54
|
-
return Object.assign({}, (headers !== null && headers !== void 0 ? headers : {}));
|
|
55
|
-
}
|
|
56
|
-
return Object.assign({ 'x-sdk-publishable-key': funnelSdkPublishableKey }, (headers !== null && headers !== void 0 ? headers : {}));
|
|
57
|
-
};
|
|
58
29
|
const asFiniteNumberOrNull = (value) => {
|
|
59
30
|
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
60
31
|
return null;
|
|
@@ -329,28 +300,6 @@ const toFallbackPaywallPlans = (planCatalog, options) => {
|
|
|
329
300
|
const isFallbackBillingPlanCatalog = (planCatalog) => {
|
|
330
301
|
return Array.isArray(planCatalog) || !isBillingPlanMappingCatalog(planCatalog);
|
|
331
302
|
};
|
|
332
|
-
const parseErrorMessage = async (response, fallbackMessage) => {
|
|
333
|
-
try {
|
|
334
|
-
const payload = (await response.json());
|
|
335
|
-
const apiError = asTrimmedStringOrNull(payload.error);
|
|
336
|
-
if (apiError) {
|
|
337
|
-
return apiError;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
catch (_a) {
|
|
341
|
-
// ignore JSON parsing errors
|
|
342
|
-
}
|
|
343
|
-
try {
|
|
344
|
-
const errorText = await response.text();
|
|
345
|
-
if (errorText.trim()) {
|
|
346
|
-
return errorText;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
catch (_b) {
|
|
350
|
-
// ignore text parsing errors
|
|
351
|
-
}
|
|
352
|
-
return fallbackMessage;
|
|
353
|
-
};
|
|
354
303
|
export function getFallbackPlans(planCatalog, options) {
|
|
355
304
|
if (!planCatalog) {
|
|
356
305
|
return reorderPlans(fallbackPaywallPlans, options === null || options === void 0 ? void 0 : options.pricing);
|
|
@@ -431,20 +380,9 @@ const getStripeSyncedPlanRecords = async (mode) => {
|
|
|
431
380
|
return cachedPromise;
|
|
432
381
|
}
|
|
433
382
|
const nextPromise = (async () => {
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
if (FUNNEL_ID) {
|
|
437
|
-
url.searchParams.set('funnelId', FUNNEL_ID);
|
|
438
|
-
}
|
|
439
|
-
const response = await fetch(url.toString(), {
|
|
440
|
-
method: 'GET',
|
|
441
|
-
headers: buildSdkHeaders(),
|
|
383
|
+
const payload = await funnelSdkService.listPaymentPlans({
|
|
384
|
+
environment: mode,
|
|
442
385
|
});
|
|
443
|
-
if (!response.ok) {
|
|
444
|
-
const errorMessage = await parseErrorMessage(response, 'Unable to load Stripe plans');
|
|
445
|
-
throw new Error(errorMessage);
|
|
446
|
-
}
|
|
447
|
-
const payload = (await response.json());
|
|
448
386
|
const rawPlans = Array.isArray(payload.plans) ? payload.plans : [];
|
|
449
387
|
return rawPlans
|
|
450
388
|
.filter((rawPlan) => isRecord(rawPlan))
|
|
@@ -595,58 +533,30 @@ const normalizeCheckoutAnalyticsMetadata = (metadata, plan) => {
|
|
|
595
533
|
};
|
|
596
534
|
export async function createStripePaymentIntent(input) {
|
|
597
535
|
var _a, _b;
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
funnelId: runtimeConfig.funnelId || undefined,
|
|
607
|
-
funnelVersionId: runtimeConfig.funnelVersionId || undefined,
|
|
608
|
-
planId: input.planId,
|
|
609
|
-
amountCents: input.amountCents,
|
|
610
|
-
couponId: ((_a = input.couponId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
611
|
-
analyticsMetadata: normalizeAnalyticsMetadata(input.analyticsMetadata),
|
|
612
|
-
user_id: ((_b = input.user_id) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
613
|
-
environment: input.environment || undefined,
|
|
614
|
-
}),
|
|
536
|
+
return funnelSdkService.createOneTimePaymentIntent({
|
|
537
|
+
planId: input.planId,
|
|
538
|
+
amountCents: input.amountCents,
|
|
539
|
+
couponId: ((_a = input.couponId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
540
|
+
analyticsMetadata: normalizeAnalyticsMetadata(input.analyticsMetadata),
|
|
541
|
+
userId: ((_b = input.user_id) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
542
|
+
environment: input.environment,
|
|
543
|
+
runtimeConfig: input.runtimeConfig,
|
|
615
544
|
});
|
|
616
|
-
if (!response.ok) {
|
|
617
|
-
const errorMessage = await parseErrorMessage(response, 'Unable to create payment intent');
|
|
618
|
-
throw new Error(errorMessage);
|
|
619
|
-
}
|
|
620
|
-
return (await response.json());
|
|
621
545
|
}
|
|
622
546
|
export async function chargeStripeOneClickPayment(input) {
|
|
623
547
|
var _a, _b, _c, _d, _e;
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
amountCents: input.amountCents,
|
|
636
|
-
currency: ((_a = input.currency) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
637
|
-
analyticsMetadata: normalizeAnalyticsMetadata(input.analyticsMetadata),
|
|
638
|
-
user_id: ((_b = input.user_id) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
639
|
-
stripe_customer_id: ((_c = input.stripe_customer_id) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
640
|
-
checkoutSessionId: ((_d = input.checkoutSessionId) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
641
|
-
idempotencyKey: ((_e = input.idempotencyKey) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
642
|
-
environment: input.environment || undefined,
|
|
643
|
-
}),
|
|
548
|
+
return funnelSdkService.chargeOneClickPayment({
|
|
549
|
+
planId: input.planId,
|
|
550
|
+
amountCents: input.amountCents,
|
|
551
|
+
currency: ((_a = input.currency) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
552
|
+
analyticsMetadata: normalizeAnalyticsMetadata(input.analyticsMetadata),
|
|
553
|
+
userId: ((_b = input.user_id) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
554
|
+
stripeCustomerId: ((_c = input.stripe_customer_id) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
555
|
+
checkoutSessionId: ((_d = input.checkoutSessionId) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
556
|
+
idempotencyKey: ((_e = input.idempotencyKey) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
557
|
+
environment: input.environment,
|
|
558
|
+
runtimeConfig: input.runtimeConfig,
|
|
644
559
|
});
|
|
645
|
-
if (!response.ok) {
|
|
646
|
-
const errorMessage = await parseErrorMessage(response, 'Unable to charge one-click payment');
|
|
647
|
-
throw new Error(errorMessage);
|
|
648
|
-
}
|
|
649
|
-
return (await response.json());
|
|
650
560
|
}
|
|
651
561
|
export async function createStripeSubscriptionCheckout(input) {
|
|
652
562
|
var _a, _b, _c, _d, _e;
|
|
@@ -654,36 +564,22 @@ export async function createStripeSubscriptionCheckout(input) {
|
|
|
654
564
|
if (!recurring) {
|
|
655
565
|
throw new Error('Unable to resolve the recurring interval for the selected plan');
|
|
656
566
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
billingInterval: recurring.interval,
|
|
673
|
-
billingIntervalCount: recurring.intervalCount,
|
|
674
|
-
couponId: ((_c = input.couponId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
675
|
-
analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
|
|
676
|
-
customerEmail: ((_d = input.customerEmail) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
677
|
-
returnUrl: input.returnUrl,
|
|
678
|
-
user_id: ((_e = input.user_id) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
679
|
-
environment: input.environment || undefined,
|
|
680
|
-
}),
|
|
567
|
+
return funnelSdkService.createSubscriptionCheckout({
|
|
568
|
+
planId: getPaywallPlanSelectionValue(input.plan),
|
|
569
|
+
providerPlanId: ((_a = input.plan.providerPlanId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
570
|
+
title: input.plan.title,
|
|
571
|
+
description: ((_b = input.plan.description) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
572
|
+
amountCents: input.plan.amountCents,
|
|
573
|
+
billingInterval: recurring.interval,
|
|
574
|
+
billingIntervalCount: recurring.intervalCount,
|
|
575
|
+
couponId: ((_c = input.couponId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
576
|
+
analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
|
|
577
|
+
customerEmail: ((_d = input.customerEmail) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
578
|
+
returnUrl: input.returnUrl,
|
|
579
|
+
userId: ((_e = input.user_id) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
580
|
+
environment: input.environment,
|
|
581
|
+
runtimeConfig: input.runtimeConfig,
|
|
681
582
|
});
|
|
682
|
-
if (!response.ok) {
|
|
683
|
-
const errorMessage = await parseErrorMessage(response, 'Unable to create subscription checkout');
|
|
684
|
-
throw new Error(errorMessage);
|
|
685
|
-
}
|
|
686
|
-
return (await response.json());
|
|
687
583
|
}
|
|
688
584
|
export async function updateStripeSubscriptionCheckoutPlan(input) {
|
|
689
585
|
var _a, _b, _c, _d, _e;
|
|
@@ -691,61 +587,33 @@ export async function updateStripeSubscriptionCheckoutPlan(input) {
|
|
|
691
587
|
if (!recurring) {
|
|
692
588
|
throw new Error('Unable to resolve the recurring interval for the selected plan');
|
|
693
589
|
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
amountCents: input.plan.amountCents,
|
|
710
|
-
billingInterval: recurring.interval,
|
|
711
|
-
billingIntervalCount: recurring.intervalCount,
|
|
712
|
-
couponId: ((_c = input.couponId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
713
|
-
analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
|
|
714
|
-
customerEmail: ((_d = input.customerEmail) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
715
|
-
user_id: ((_e = input.user_id) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
716
|
-
environment: input.environment || undefined,
|
|
717
|
-
}),
|
|
590
|
+
return funnelSdkService.updateSubscriptionCheckoutPlan({
|
|
591
|
+
checkoutSessionId: input.checkoutSessionId.trim(),
|
|
592
|
+
planId: getPaywallPlanSelectionValue(input.plan),
|
|
593
|
+
providerPlanId: ((_a = input.plan.providerPlanId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
594
|
+
title: input.plan.title,
|
|
595
|
+
description: ((_b = input.plan.description) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
596
|
+
amountCents: input.plan.amountCents,
|
|
597
|
+
billingInterval: recurring.interval,
|
|
598
|
+
billingIntervalCount: recurring.intervalCount,
|
|
599
|
+
couponId: ((_c = input.couponId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
600
|
+
analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
|
|
601
|
+
customerEmail: ((_d = input.customerEmail) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
602
|
+
userId: ((_e = input.user_id) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
603
|
+
environment: input.environment,
|
|
604
|
+
runtimeConfig: input.runtimeConfig,
|
|
718
605
|
});
|
|
719
|
-
if (!response.ok) {
|
|
720
|
-
const errorMessage = await parseErrorMessage(response, 'Unable to update subscription checkout');
|
|
721
|
-
throw new Error(errorMessage);
|
|
722
|
-
}
|
|
723
|
-
return (await response.json());
|
|
724
606
|
}
|
|
725
607
|
export async function verifyStripeSubscriptionCheckoutPayment(input) {
|
|
726
608
|
const checkoutSessionId = input.checkoutSessionId.trim();
|
|
727
609
|
if (!checkoutSessionId) {
|
|
728
610
|
throw new Error('checkoutSessionId is required');
|
|
729
611
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
'Content-Type': 'application/json',
|
|
735
|
-
}),
|
|
736
|
-
body: JSON.stringify({
|
|
737
|
-
publishableKey: runtimeConfig.funnelSdkPublishableKey || undefined,
|
|
738
|
-
funnelId: runtimeConfig.funnelId || undefined,
|
|
739
|
-
funnelVersionId: runtimeConfig.funnelVersionId || undefined,
|
|
740
|
-
checkoutSessionId,
|
|
741
|
-
environment: input.environment || undefined,
|
|
742
|
-
}),
|
|
612
|
+
return funnelSdkService.verifySubscriptionCheckout({
|
|
613
|
+
checkoutSessionId,
|
|
614
|
+
environment: input.environment,
|
|
615
|
+
runtimeConfig: input.runtimeConfig,
|
|
743
616
|
});
|
|
744
|
-
if (!response.ok) {
|
|
745
|
-
const errorMessage = await parseErrorMessage(response, 'Unable to verify subscription checkout');
|
|
746
|
-
throw new Error(errorMessage);
|
|
747
|
-
}
|
|
748
|
-
return (await response.json());
|
|
749
617
|
}
|
|
750
618
|
export async function createStripeCheckoutSession(input) {
|
|
751
619
|
var _a, _b, _c, _d, _e;
|
|
@@ -753,37 +621,23 @@ export async function createStripeCheckoutSession(input) {
|
|
|
753
621
|
if (!recurring) {
|
|
754
622
|
throw new Error('Unable to resolve the recurring interval for the selected plan');
|
|
755
623
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
billingIntervalCount: recurring.intervalCount,
|
|
773
|
-
couponId: ((_c = input.couponId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
774
|
-
analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
|
|
775
|
-
successUrl: input.successUrl,
|
|
776
|
-
cancelUrl: input.cancelUrl,
|
|
777
|
-
customerEmail: ((_d = input.customerEmail) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
778
|
-
user_id: ((_e = input.user_id) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
779
|
-
environment: input.environment || undefined,
|
|
780
|
-
}),
|
|
624
|
+
return funnelSdkService.createHostedCheckoutSession({
|
|
625
|
+
planId: getPaywallPlanSelectionValue(input.plan),
|
|
626
|
+
providerPlanId: ((_a = input.plan.providerPlanId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
627
|
+
title: input.plan.title,
|
|
628
|
+
description: ((_b = input.plan.description) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
629
|
+
amountCents: input.plan.amountCents,
|
|
630
|
+
billingInterval: recurring.interval,
|
|
631
|
+
billingIntervalCount: recurring.intervalCount,
|
|
632
|
+
couponId: ((_c = input.couponId) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
633
|
+
analyticsMetadata: normalizeCheckoutAnalyticsMetadata(input.analyticsMetadata, input.plan),
|
|
634
|
+
successUrl: input.successUrl,
|
|
635
|
+
cancelUrl: input.cancelUrl,
|
|
636
|
+
customerEmail: ((_d = input.customerEmail) === null || _d === void 0 ? void 0 : _d.trim()) || undefined,
|
|
637
|
+
userId: ((_e = input.user_id) === null || _e === void 0 ? void 0 : _e.trim()) || undefined,
|
|
638
|
+
environment: input.environment,
|
|
639
|
+
runtimeConfig: input.runtimeConfig,
|
|
781
640
|
});
|
|
782
|
-
if (!response.ok) {
|
|
783
|
-
const errorMessage = await parseErrorMessage(response, 'Unable to create checkout session');
|
|
784
|
-
throw new Error(errorMessage);
|
|
785
|
-
}
|
|
786
|
-
return (await response.json());
|
|
787
641
|
}
|
|
788
642
|
export async function redirectToStripeCheckout(input) {
|
|
789
643
|
var _a;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnelsgrove/payments",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"test:run": "vitest run --passWithNoTests"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@funnelsgrove/analytics": "^0.1.
|
|
31
|
-
"@funnelsgrove/runtime": "^0.1.
|
|
30
|
+
"@funnelsgrove/analytics": "^0.1.28",
|
|
31
|
+
"@funnelsgrove/runtime": "^0.1.46",
|
|
32
32
|
"@stripe/react-stripe-js": "^5.6.0",
|
|
33
33
|
"@stripe/stripe-js": "^8.7.0",
|
|
34
34
|
"react": "19.2.3",
|