billing
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -4,6 +4,7 @@ export {
|
||||
requireTier,
|
||||
checkUsageLimit,
|
||||
withUsageTracking,
|
||||
withSubscription,
|
||||
requireSubscription,
|
||||
} from './middleware/billing.middleware';
|
||||
|
||||
|
||||
@@ -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',
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user