This commit is contained in:
2026-04-30 11:07:38 -04:00
parent 9fb5379b7a
commit 19c5a951fe
4 changed files with 47 additions and 10 deletions

View File

@@ -74,7 +74,7 @@ export const loadBillingConfig = (): BillingConfig => ({
darkWebScans: 12,
},
plus: {
priceId: process.env.STRIPE_PLUS_TIER_PRICE_ID!,
priceId: process.env.STRIPE_PLUS_TIER_PRICE_ID || 'price_plus',
monthlyPriceCents: 1999,
callMinutesLimit: 2000,
smsCountLimit: 10000,
@@ -82,7 +82,7 @@ export const loadBillingConfig = (): BillingConfig => ({
voiceCloning: true,
},
premium: {
priceId: process.env.STRIPE_PREMIUM_TIER_PRICE_ID!,
priceId: process.env.STRIPE_PREMIUM_TIER_PRICE_ID || 'price_premium',
monthlyPriceCents: 4999,
callMinutesLimit: 10000,
smsCountLimit: 50000,

View File

@@ -4,6 +4,7 @@ export {
requireTier,
checkUsageLimit,
withUsageTracking,
withSubscription,
requireSubscription,
} from './middleware/billing.middleware';

View File

@@ -7,7 +7,8 @@ const billingService = BillingService.getInstance();
export interface AuthenticatedRequest extends Request {
userId?: string;
tier?: SubscriptionTier;
usage?: { current: number; limit: number; remaining: number };
usage?: { current: number; limit: number; remaining: number; withinLimit: boolean };
subscriptionId?: string;
}
export function requireTier(
@@ -108,24 +109,52 @@ export function withUsageTracking(
};
}
export function withSubscription() {
return async (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): Promise<void> => {
const { userId, tier } = req;
if (!userId || !tier) {
next();
return;
}
try {
// Fetch subscription from database
// TODO: Replace with actual database query
const subscriptionId = (req as any).subscriptionId;
if (subscriptionId) {
req.subscriptionId = subscriptionId;
}
next();
} catch (error) {
res.status(500).json({
error: 'Failed to fetch subscription',
message: error instanceof Error ? error.message : 'Unknown error',
});
}
};
}
export function requireSubscription() {
return async (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): Promise<void> => {
const { userId } = req;
const { userId, subscriptionId } = req;
if (!userId) {
res.status(401).json({ error: 'Authentication required' });
return;
}
// Check if user has active subscription
// This would typically query the database
const hasSubscription = (req as any).subscriptionId != null;
if (!hasSubscription) {
if (!subscriptionId) {
res.status(402).json({
error: 'Active subscription required',
});

View File

@@ -132,7 +132,14 @@ export class BillingService {
): Promise<Stripe.Invoice> {
return await stripe.invoices.create({
customer: customerId,
metadata: { ...metadata, description },
line_items: [
{
amount_data: { currency: 'usd', unit_amount: amount },
description: description,
quantity: 1,
},
],
metadata: metadata,
});
}