diff --git a/packages/shared-billing/src/services/billing.service.ts b/packages/shared-billing/src/services/billing.service.ts index 62b04c4..7eb93d7 100644 --- a/packages/shared-billing/src/services/billing.service.ts +++ b/packages/shared-billing/src/services/billing.service.ts @@ -1,21 +1,12 @@ import Stripe from 'stripe'; import { loadBillingConfig, SubscriptionTier } from '../config/billing.config'; +import { RedisService } from '@shieldsai/shared-notifications'; import type { Subscription, SubscriptionCreateSchema, SubscriptionUpdateSchema } from '../models/subscription.model'; const config = loadBillingConfig(); const stripe = new Stripe(config.stripe.apiKey, { apiVersion: '2023-10-16' }); - -const processedEvents = new Map(); -const IDEMPOTENCY_TTL_MS = 24 * 60 * 60 * 1000; - -function cleanupOldEvents(): void { - const now = Date.now(); - for (const [eventId, timestamp] of processedEvents.entries()) { - if (now - timestamp > IDEMPOTENCY_TTL_MS) { - processedEvents.delete(eventId); - } - } -} +const redis = RedisService.getInstance(); +const IDEMPOTENCY_TTL_SECONDS = 24 * 60 * 60; export class BillingService { private static instance: BillingService; @@ -266,15 +257,17 @@ export class BillingService { body: Buffer ): Promise { const event = stripe.webhooks.constructEvent(body, sig, config.stripe.webhookSecret); - - cleanupOldEvents(); - if (processedEvents.has(event.id)) { + const wasNew = await redis.setIfNotExists( + `stripe:event:${event.id}`, + '1', + IDEMPOTENCY_TTL_SECONDS + ); + + if (!wasNew) { return null; } - processedEvents.set(event.id, Date.now()); - return event; }