@yannvr/billing 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/use-checkout.d.ts +33 -0
- package/dist/client/use-checkout.d.ts.map +1 -0
- package/dist/client/use-checkout.js +61 -0
- package/dist/client/use-checkout.js.map +1 -0
- package/dist/server/checkout.d.ts +16 -0
- package/dist/server/checkout.d.ts.map +1 -0
- package/dist/server/checkout.js +28 -0
- package/dist/server/checkout.js.map +1 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +4 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/stripe.d.ts +18 -0
- package/dist/server/stripe.d.ts.map +1 -0
- package/dist/server/stripe.js +60 -0
- package/dist/server/stripe.js.map +1 -0
- package/dist/server/webhook.d.ts +25 -0
- package/dist/server/webhook.d.ts.map +1 -0
- package/dist/server/webhook.js +48 -0
- package/dist/server/webhook.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
type Step = 'idle' | 'loading' | 'success' | 'error';
|
|
2
|
+
interface CheckoutState {
|
|
3
|
+
step: Step;
|
|
4
|
+
error: string | null;
|
|
5
|
+
}
|
|
6
|
+
interface CheckoutActions {
|
|
7
|
+
/**
|
|
8
|
+
* Start a subscription checkout for the given Stripe price ID.
|
|
9
|
+
* Redirects to Stripe Checkout on success.
|
|
10
|
+
*/
|
|
11
|
+
subscribe: (priceId: string, planName: string) => Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Start a one-time payment checkout for the given Stripe price ID.
|
|
14
|
+
*/
|
|
15
|
+
pay: (priceId: string, itemName: string) => Promise<void>;
|
|
16
|
+
reset: () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Headless hook for Stripe Checkout redirects.
|
|
20
|
+
* Mirrors the usePasskeyLogin pattern: manages loading/error state,
|
|
21
|
+
* delegates all UI decisions to the calling component.
|
|
22
|
+
*
|
|
23
|
+
* Requires NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY in the app's env.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const { step, error, subscribe } = useCheckout()
|
|
27
|
+
* <button onClick={() => subscribe(priceId, 'Pro')} disabled={step === 'loading'}>
|
|
28
|
+
* {step === 'loading' ? 'Redirecting…' : 'Upgrade to Pro'}
|
|
29
|
+
* </button>
|
|
30
|
+
*/
|
|
31
|
+
export declare function useCheckout(): CheckoutState & CheckoutActions;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=use-checkout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-checkout.d.ts","sourceRoot":"","sources":["../../src/client/use-checkout.ts"],"names":[],"mappings":"AAKA,KAAK,IAAI,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;AAEpD,UAAU,aAAa;IACrB,IAAI,EAAE,IAAI,CAAA;IACV,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,UAAU,eAAe;IACvB;;;OAGG;IACH,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D;;OAEG;IACH,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACzD,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,IAAI,aAAa,GAAG,eAAe,CA6D7D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useState, useCallback } from 'react';
|
|
3
|
+
import { loadStripe } from '@stripe/stripe-js';
|
|
4
|
+
/**
|
|
5
|
+
* Headless hook for Stripe Checkout redirects.
|
|
6
|
+
* Mirrors the usePasskeyLogin pattern: manages loading/error state,
|
|
7
|
+
* delegates all UI decisions to the calling component.
|
|
8
|
+
*
|
|
9
|
+
* Requires NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY in the app's env.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const { step, error, subscribe } = useCheckout()
|
|
13
|
+
* <button onClick={() => subscribe(priceId, 'Pro')} disabled={step === 'loading'}>
|
|
14
|
+
* {step === 'loading' ? 'Redirecting…' : 'Upgrade to Pro'}
|
|
15
|
+
* </button>
|
|
16
|
+
*/
|
|
17
|
+
export function useCheckout() {
|
|
18
|
+
const [step, setStep] = useState('idle');
|
|
19
|
+
const [error, setError] = useState(null);
|
|
20
|
+
const redirect = useCallback(async (endpoint, body) => {
|
|
21
|
+
var _a;
|
|
22
|
+
setStep('loading');
|
|
23
|
+
setError(null);
|
|
24
|
+
try {
|
|
25
|
+
const publishableKey = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY;
|
|
26
|
+
if (!publishableKey)
|
|
27
|
+
throw new Error('NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY is not set');
|
|
28
|
+
const stripe = await loadStripe(publishableKey);
|
|
29
|
+
if (!stripe)
|
|
30
|
+
throw new Error('Stripe failed to load');
|
|
31
|
+
const res = await fetch(endpoint, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: { 'Content-Type': 'application/json' },
|
|
34
|
+
body: JSON.stringify(body),
|
|
35
|
+
});
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
const data = await res.json().catch(() => ({}));
|
|
38
|
+
throw new Error((_a = data.error) !== null && _a !== void 0 ? _a : 'Failed to create checkout session');
|
|
39
|
+
}
|
|
40
|
+
const { sessionId } = await res.json();
|
|
41
|
+
const { error: stripeError } = await stripe.redirectToCheckout({ sessionId });
|
|
42
|
+
if (stripeError)
|
|
43
|
+
throw new Error(stripeError.message);
|
|
44
|
+
// If we reach here the tab is still open (e.g. popup mode) — mark success
|
|
45
|
+
setStep('success');
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
const msg = err instanceof Error ? err.message : 'Checkout failed';
|
|
49
|
+
setError(msg);
|
|
50
|
+
setStep('error');
|
|
51
|
+
}
|
|
52
|
+
}, []);
|
|
53
|
+
const subscribe = useCallback((priceId, planName) => redirect('/api/stripe/create-subscription', { priceId, planName }), [redirect]);
|
|
54
|
+
const pay = useCallback((priceId, itemName) => redirect('/api/stripe/create-payment', { priceId, itemName }), [redirect]);
|
|
55
|
+
const reset = useCallback(() => {
|
|
56
|
+
setStep('idle');
|
|
57
|
+
setError(null);
|
|
58
|
+
}, []);
|
|
59
|
+
return { step, error, subscribe, pay, reset };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=use-checkout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-checkout.js","sourceRoot":"","sources":["../../src/client/use-checkout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CheckoutOptions, PortalOptions } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a Stripe Checkout session.
|
|
4
|
+
* Returns { sessionId } for use with stripe.redirectToCheckout() on the client.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createCheckoutSession(options: CheckoutOptions): Promise<{
|
|
7
|
+
sessionId: string;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Creates a Stripe Billing Portal session so users can manage their subscription.
|
|
11
|
+
* Requires a Stripe customer ID (stored on the user record after first checkout).
|
|
12
|
+
*/
|
|
13
|
+
export declare function createPortalSession(options: PortalOptions): Promise<{
|
|
14
|
+
url: string;
|
|
15
|
+
}>;
|
|
16
|
+
//# sourceMappingURL=checkout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../src/server/checkout.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAE9D;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA4BpG;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAO1F"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getStripe } from './stripe';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a Stripe Checkout session.
|
|
4
|
+
* Returns { sessionId } for use with stripe.redirectToCheckout() on the client.
|
|
5
|
+
*/
|
|
6
|
+
export async function createCheckoutSession(options) {
|
|
7
|
+
var _a;
|
|
8
|
+
const stripe = getStripe();
|
|
9
|
+
const appUrl = (_a = process.env.NEXT_PUBLIC_APP_URL) !== null && _a !== void 0 ? _a : 'http://localhost:3000';
|
|
10
|
+
const { priceId, planName, successUrl = `${appUrl}/success?session_id={CHECKOUT_SESSION_ID}`, cancelUrl = `${appUrl}/plans`, mode = 'subscription', metadata = {}, } = options;
|
|
11
|
+
const session = await stripe.checkout.sessions.create(Object.assign({ mode, payment_method_types: ['card'], line_items: [{ price: priceId, quantity: 1 }], success_url: successUrl, cancel_url: cancelUrl, metadata: Object.assign({ planName }, metadata), allow_promotion_codes: true, billing_address_collection: 'auto' }, (mode === 'subscription' && {
|
|
12
|
+
subscription_data: { metadata: Object.assign({ planName }, metadata) },
|
|
13
|
+
})));
|
|
14
|
+
return { sessionId: session.id };
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Creates a Stripe Billing Portal session so users can manage their subscription.
|
|
18
|
+
* Requires a Stripe customer ID (stored on the user record after first checkout).
|
|
19
|
+
*/
|
|
20
|
+
export async function createPortalSession(options) {
|
|
21
|
+
const stripe = getStripe();
|
|
22
|
+
const session = await stripe.billingPortal.sessions.create({
|
|
23
|
+
customer: options.customerId,
|
|
24
|
+
return_url: options.returnUrl,
|
|
25
|
+
});
|
|
26
|
+
return { url: session.url };
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=checkout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout.js","sourceRoot":"","sources":["../../src/server/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAGpC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAwB;;IAClE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,MAAM,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,mBAAmB,mCAAI,uBAAuB,CAAA;IAEzE,MAAM,EACJ,OAAO,EACP,QAAQ,EACR,UAAU,GAAG,GAAG,MAAM,2CAA2C,EACjE,SAAS,GAAG,GAAG,MAAM,QAAQ,EAC7B,IAAI,GAAG,cAAc,EACrB,QAAQ,GAAG,EAAE,GACd,GAAG,OAAO,CAAA;IAEX,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,iBACnD,IAAI,EACJ,oBAAoB,EAAE,CAAC,MAAM,CAAC,EAC9B,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAC7C,WAAW,EAAE,UAAU,EACvB,UAAU,EAAE,SAAS,EACrB,QAAQ,kBAAI,QAAQ,IAAK,QAAQ,GACjC,qBAAqB,EAAE,IAAI,EAC3B,0BAA0B,EAAE,MAAM,IAC/B,CAAC,IAAI,KAAK,cAAc,IAAI;QAC7B,iBAAiB,EAAE,EAAE,QAAQ,kBAAI,QAAQ,IAAK,QAAQ,CAAE,EAAE;KAC3D,CAAC,EACF,CAAA;IAEF,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,CAAA;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAsB;IAC9D,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC;QACzD,QAAQ,EAAE,OAAO,CAAC,UAAU;QAC5B,UAAU,EAAE,OAAO,CAAC,SAAS;KAC9B,CAAC,CAAA;IACF,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAA;AAC7B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { getStripe, getStripeSecretKey, getStripePublishableKey, isStripeSandbox, getStripeStatus, resetStripeInstance } from './stripe';
|
|
2
|
+
export { createCheckoutSession, createPortalSession } from './checkout';
|
|
3
|
+
export { verifyAndParseWebhook, dispatchWebhookEvent } from './webhook';
|
|
4
|
+
export type { PlanConfig, CheckoutOptions, PortalOptions, WebhookHandlers } from '../types';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACxI,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AACvE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { getStripe, getStripeSecretKey, getStripePublishableKey, isStripeSandbox, getStripeStatus, resetStripeInstance } from './stripe';
|
|
2
|
+
export { createCheckoutSession, createPortalSession } from './checkout';
|
|
3
|
+
export { verifyAndParseWebhook, dispatchWebhookEvent } from './webhook';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACxI,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Stripe from 'stripe';
|
|
2
|
+
/**
|
|
3
|
+
* Stripe sandbox/production toggle.
|
|
4
|
+
* Set STRIPE_SANDBOX=false in .env for live mode. Defaults to sandbox.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isStripeSandbox(): boolean;
|
|
7
|
+
export declare function getStripeSecretKey(): string;
|
|
8
|
+
export declare function getStripePublishableKey(): string;
|
|
9
|
+
export declare function getStripe(): Stripe;
|
|
10
|
+
/** Reset cached instance — useful in tests */
|
|
11
|
+
export declare function resetStripeInstance(): void;
|
|
12
|
+
export declare function getStripeStatus(): {
|
|
13
|
+
sandbox: boolean;
|
|
14
|
+
secretKeyType: string;
|
|
15
|
+
publishableKeyType: string;
|
|
16
|
+
configured: boolean;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=stripe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripe.d.ts","sourceRoot":"","sources":["../../src/server/stripe.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAE3B;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAc3C;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAWhD;AAID,wBAAgB,SAAS,IAAI,MAAM,CAOlC;AAED,8CAA8C;AAC9C,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,wBAAgB,eAAe;;;;;EAS9B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import Stripe from 'stripe';
|
|
2
|
+
/**
|
|
3
|
+
* Stripe sandbox/production toggle.
|
|
4
|
+
* Set STRIPE_SANDBOX=false in .env for live mode. Defaults to sandbox.
|
|
5
|
+
*/
|
|
6
|
+
export function isStripeSandbox() {
|
|
7
|
+
return process.env.STRIPE_SANDBOX !== 'false';
|
|
8
|
+
}
|
|
9
|
+
export function getStripeSecretKey() {
|
|
10
|
+
const sandbox = isStripeSandbox();
|
|
11
|
+
if (sandbox && process.env.STRIPE_SECRET_KEY_TEST)
|
|
12
|
+
return process.env.STRIPE_SECRET_KEY_TEST;
|
|
13
|
+
if (!sandbox && process.env.STRIPE_SECRET_KEY_LIVE)
|
|
14
|
+
return process.env.STRIPE_SECRET_KEY_LIVE;
|
|
15
|
+
const key = process.env.STRIPE_SECRET_KEY;
|
|
16
|
+
if (!key)
|
|
17
|
+
throw new Error('STRIPE_SECRET_KEY is not configured');
|
|
18
|
+
const isTestKey = key.startsWith('sk_test_');
|
|
19
|
+
if (sandbox && !isTestKey)
|
|
20
|
+
console.warn('[billing] STRIPE_SANDBOX=true but using live secret key');
|
|
21
|
+
if (!sandbox && isTestKey)
|
|
22
|
+
console.warn('[billing] STRIPE_SANDBOX=false but using test secret key');
|
|
23
|
+
return key;
|
|
24
|
+
}
|
|
25
|
+
export function getStripePublishableKey() {
|
|
26
|
+
const sandbox = isStripeSandbox();
|
|
27
|
+
if (sandbox && process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY_TEST)
|
|
28
|
+
return process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY_TEST;
|
|
29
|
+
if (!sandbox && process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY_LIVE)
|
|
30
|
+
return process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY_LIVE;
|
|
31
|
+
const key = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY;
|
|
32
|
+
if (!key)
|
|
33
|
+
throw new Error('NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY is not configured');
|
|
34
|
+
return key;
|
|
35
|
+
}
|
|
36
|
+
let stripeInstance = null;
|
|
37
|
+
export function getStripe() {
|
|
38
|
+
if (!stripeInstance) {
|
|
39
|
+
stripeInstance = new Stripe(getStripeSecretKey(), {
|
|
40
|
+
apiVersion: '2025-05-28.basil',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return stripeInstance;
|
|
44
|
+
}
|
|
45
|
+
/** Reset cached instance — useful in tests */
|
|
46
|
+
export function resetStripeInstance() {
|
|
47
|
+
stripeInstance = null;
|
|
48
|
+
}
|
|
49
|
+
export function getStripeStatus() {
|
|
50
|
+
var _a, _b;
|
|
51
|
+
const secretKey = (_a = process.env.STRIPE_SECRET_KEY) !== null && _a !== void 0 ? _a : '';
|
|
52
|
+
const pubKey = (_b = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY) !== null && _b !== void 0 ? _b : '';
|
|
53
|
+
return {
|
|
54
|
+
sandbox: isStripeSandbox(),
|
|
55
|
+
secretKeyType: secretKey.startsWith('sk_test_') ? 'test' : secretKey.startsWith('sk_live_') ? 'live' : 'unknown',
|
|
56
|
+
publishableKeyType: pubKey.startsWith('pk_test_') ? 'test' : pubKey.startsWith('pk_live_') ? 'live' : 'unknown',
|
|
57
|
+
configured: !!secretKey && !!pubKey,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=stripe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../src/server/stripe.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAE3B;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO,CAAA;AAC/C,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,eAAe,EAAE,CAAA;IAEjC,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAA;IAC5F,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAA;IAE7F,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAA;IACzC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IAEhE,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAA;IAC5C,IAAI,OAAO,IAAI,CAAC,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAA;IAClG,IAAI,CAAC,OAAO,IAAI,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAA;IAEnG,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,MAAM,OAAO,GAAG,eAAe,EAAE,CAAA;IAEjC,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,uCAAuC;QAChE,OAAO,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAA;IAC5D,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,uCAAuC;QACjE,OAAO,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAA;IAE5D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAA;IAC1D,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;IACjF,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,IAAI,cAAc,GAAkB,IAAI,CAAA;AAExC,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,cAAc,GAAG,IAAI,MAAM,CAAC,kBAAkB,EAAE,EAAE;YAChD,UAAU,EAAE,kBAA6C;SAC1D,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,mBAAmB;IACjC,cAAc,GAAG,IAAI,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,eAAe;;IAC7B,MAAM,SAAS,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,mCAAI,EAAE,CAAA;IACrD,MAAM,MAAM,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,kCAAkC,mCAAI,EAAE,CAAA;IACnE,OAAO;QACL,OAAO,EAAE,eAAe,EAAE;QAC1B,aAAa,EAAE,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAChH,kBAAkB,EAAE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC/G,UAAU,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM;KACpC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Stripe from 'stripe';
|
|
2
|
+
import type { WebhookHandlers } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Verifies the Stripe webhook signature and returns the parsed event.
|
|
5
|
+
* Throws if the signature is invalid.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const rawBody = await request.text()
|
|
9
|
+
* const sig = request.headers.get('stripe-signature')!
|
|
10
|
+
* const event = verifyAndParseWebhook(rawBody, sig, process.env.STRIPE_WEBHOOK_SECRET!)
|
|
11
|
+
*/
|
|
12
|
+
export declare function verifyAndParseWebhook(payload: string, sig: string, secret: string): Stripe.Event;
|
|
13
|
+
/**
|
|
14
|
+
* Dispatches a verified Stripe event to the appropriate handler.
|
|
15
|
+
* Silently ignores unhandled event types.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const event = verifyAndParseWebhook(rawBody, sig, secret)
|
|
19
|
+
* await dispatchWebhookEvent(event, {
|
|
20
|
+
* onSubscriptionCreated: async (sub) => { ... },
|
|
21
|
+
* onCheckoutCompleted: async (session) => { ... },
|
|
22
|
+
* })
|
|
23
|
+
*/
|
|
24
|
+
export declare function dispatchWebhookEvent(event: Stripe.Event, handlers: WebhookHandlers): Promise<void>;
|
|
25
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/server/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAE3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE/C;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,KAAK,CAGd;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAoBf"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getStripe } from './stripe';
|
|
2
|
+
/**
|
|
3
|
+
* Verifies the Stripe webhook signature and returns the parsed event.
|
|
4
|
+
* Throws if the signature is invalid.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const rawBody = await request.text()
|
|
8
|
+
* const sig = request.headers.get('stripe-signature')!
|
|
9
|
+
* const event = verifyAndParseWebhook(rawBody, sig, process.env.STRIPE_WEBHOOK_SECRET!)
|
|
10
|
+
*/
|
|
11
|
+
export function verifyAndParseWebhook(payload, sig, secret) {
|
|
12
|
+
const stripe = getStripe();
|
|
13
|
+
return stripe.webhooks.constructEvent(payload, sig, secret);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Dispatches a verified Stripe event to the appropriate handler.
|
|
17
|
+
* Silently ignores unhandled event types.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* const event = verifyAndParseWebhook(rawBody, sig, secret)
|
|
21
|
+
* await dispatchWebhookEvent(event, {
|
|
22
|
+
* onSubscriptionCreated: async (sub) => { ... },
|
|
23
|
+
* onCheckoutCompleted: async (session) => { ... },
|
|
24
|
+
* })
|
|
25
|
+
*/
|
|
26
|
+
export async function dispatchWebhookEvent(event, handlers) {
|
|
27
|
+
var _a, _b, _c, _d, _e;
|
|
28
|
+
switch (event.type) {
|
|
29
|
+
case 'customer.subscription.created':
|
|
30
|
+
await ((_a = handlers.onSubscriptionCreated) === null || _a === void 0 ? void 0 : _a.call(handlers, event.data.object));
|
|
31
|
+
break;
|
|
32
|
+
case 'customer.subscription.updated':
|
|
33
|
+
await ((_b = handlers.onSubscriptionUpdated) === null || _b === void 0 ? void 0 : _b.call(handlers, event.data.object));
|
|
34
|
+
break;
|
|
35
|
+
case 'customer.subscription.deleted':
|
|
36
|
+
await ((_c = handlers.onSubscriptionDeleted) === null || _c === void 0 ? void 0 : _c.call(handlers, event.data.object));
|
|
37
|
+
break;
|
|
38
|
+
case 'invoice.payment_succeeded':
|
|
39
|
+
await ((_d = handlers.onPaymentSucceeded) === null || _d === void 0 ? void 0 : _d.call(handlers, event.data.object));
|
|
40
|
+
break;
|
|
41
|
+
case 'checkout.session.completed':
|
|
42
|
+
await ((_e = handlers.onCheckoutCompleted) === null || _e === void 0 ? void 0 : _e.call(handlers, event.data.object));
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/server/webhook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAGpC;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,GAAW,EACX,MAAc;IAEd,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,OAAO,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;AAC7D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAmB,EACnB,QAAyB;;IAEzB,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,+BAA+B;YAClC,MAAM,CAAA,MAAA,QAAQ,CAAC,qBAAqB,yDAAG,KAAK,CAAC,IAAI,CAAC,MAA6B,CAAC,CAAA,CAAA;YAChF,MAAK;QACP,KAAK,+BAA+B;YAClC,MAAM,CAAA,MAAA,QAAQ,CAAC,qBAAqB,yDAAG,KAAK,CAAC,IAAI,CAAC,MAA6B,CAAC,CAAA,CAAA;YAChF,MAAK;QACP,KAAK,+BAA+B;YAClC,MAAM,CAAA,MAAA,QAAQ,CAAC,qBAAqB,yDAAG,KAAK,CAAC,IAAI,CAAC,MAA6B,CAAC,CAAA,CAAA;YAChF,MAAK;QACP,KAAK,2BAA2B;YAC9B,MAAM,CAAA,MAAA,QAAQ,CAAC,kBAAkB,yDAAG,KAAK,CAAC,IAAI,CAAC,MAAwB,CAAC,CAAA,CAAA;YACxE,MAAK;QACP,KAAK,4BAA4B;YAC/B,MAAM,CAAA,MAAA,QAAQ,CAAC,mBAAmB,yDAAG,KAAK,CAAC,IAAI,CAAC,MAAiC,CAAC,CAAA,CAAA;YAClF,MAAK;QACP;YACE,MAAK;IACT,CAAC;AACH,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface PlanConfig {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
monthlyPrice: number;
|
|
5
|
+
annualPrice?: number;
|
|
6
|
+
/** Omit for free tiers */
|
|
7
|
+
monthlyPriceId?: string;
|
|
8
|
+
annualPriceId?: string;
|
|
9
|
+
features: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Required: explain, in one sentence, why this plan makes the app better for the user.
|
|
12
|
+
* Shown prominently on the pricing page — makes conversion copy a first-class concern.
|
|
13
|
+
*/
|
|
14
|
+
valueProposition: string;
|
|
15
|
+
popular?: boolean;
|
|
16
|
+
/** Human-readable usage limit, e.g. "3 CVs/month" or "10 reports/day" */
|
|
17
|
+
limitLabel?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface CheckoutOptions {
|
|
20
|
+
priceId: string;
|
|
21
|
+
planName: string;
|
|
22
|
+
/** Defaults to process.env.NEXT_PUBLIC_APP_URL + /success */
|
|
23
|
+
successUrl?: string;
|
|
24
|
+
/** Defaults to process.env.NEXT_PUBLIC_APP_URL + /plans */
|
|
25
|
+
cancelUrl?: string;
|
|
26
|
+
mode?: 'subscription' | 'payment';
|
|
27
|
+
/** Attach extra metadata to the Stripe session */
|
|
28
|
+
metadata?: Record<string, string>;
|
|
29
|
+
}
|
|
30
|
+
export interface PortalOptions {
|
|
31
|
+
customerId: string;
|
|
32
|
+
returnUrl: string;
|
|
33
|
+
}
|
|
34
|
+
export interface WebhookHandlers {
|
|
35
|
+
onSubscriptionCreated?: (subscription: import('stripe').Stripe.Subscription) => Promise<void>;
|
|
36
|
+
onSubscriptionUpdated?: (subscription: import('stripe').Stripe.Subscription) => Promise<void>;
|
|
37
|
+
onSubscriptionDeleted?: (subscription: import('stripe').Stripe.Subscription) => Promise<void>;
|
|
38
|
+
onPaymentSucceeded?: (invoice: import('stripe').Stripe.Invoice) => Promise<void>;
|
|
39
|
+
onCheckoutCompleted?: (session: import('stripe').Stripe.Checkout.Session) => Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0BAA0B;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,cAAc,GAAG,SAAS,CAAA;IACjC,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,qBAAqB,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,QAAQ,EAAE,MAAM,CAAC,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7F,qBAAqB,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,QAAQ,EAAE,MAAM,CAAC,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7F,qBAAqB,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,QAAQ,EAAE,MAAM,CAAC,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7F,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,QAAQ,EAAE,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChF,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3F"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yannvr/billing",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared Stripe billing (checkout, subscriptions, webhooks) for Next.js apps",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"exports": {
|
|
7
|
+
"./server": {
|
|
8
|
+
"types": "./dist/server/index.d.ts",
|
|
9
|
+
"default": "./dist/server/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./client": {
|
|
12
|
+
"types": "./dist/client/index.d.ts",
|
|
13
|
+
"default": "./dist/client/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": ["dist"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc --project tsconfig.build.json"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"next": ">=14",
|
|
22
|
+
"react": ">=18",
|
|
23
|
+
"stripe": ">=16"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@stripe/stripe-js": "^4",
|
|
27
|
+
"@types/node": "^20",
|
|
28
|
+
"@types/react": "^19",
|
|
29
|
+
"next": "^15",
|
|
30
|
+
"react": "^18",
|
|
31
|
+
"stripe": "^18",
|
|
32
|
+
"typescript": "^5"
|
|
33
|
+
}
|
|
34
|
+
}
|