Phase 2 of service consolidation (5→2 services). Moved modules: - subscriptions (9 tests) - usage (7 tests) - plans (9 tests) - licenses (7 tests) - stripe (0 tests — webhook signature verified at runtime) Changes: - Copied 5 modules + stripe.ts lib from billing-service - Added billing env vars to config schema (Stripe, internal key, etc.) - Scoped billing routes with internal key auth guard (Gap 3) - When BILLING_INTERNAL_KEY is set, billing routes require x-internal-key header - When unset, billing routes are open (dev mode) - Stripe routes always outside scope (own webhook signature check) - Removed billing-service directory Tests: 115 passing (83 + 32 from billing = 115) ✅ Build: clean ✅
42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
/**
|
|
* Stripe client for the Billing Service.
|
|
*
|
|
* Multi-tenant: supports per-product Stripe keys via env vars:
|
|
* STRIPE_SECRET_KEY — default key
|
|
* STRIPE_SECRET_KEY_<PRODUCTID> — product-specific key (uppercase)
|
|
*/
|
|
|
|
import Stripe from 'stripe';
|
|
|
|
const _cache = new Map<string, Stripe>();
|
|
|
|
/** Get a Stripe client, optionally per-product (falls back to default key). */
|
|
export function getStripeForProduct(productId?: string): Stripe {
|
|
const cacheKey = productId || 'default';
|
|
if (_cache.has(cacheKey)) return _cache.get(cacheKey)!;
|
|
|
|
// Try product-specific key first, then default
|
|
const envKey = productId ? `STRIPE_SECRET_KEY_${productId.toUpperCase()}` : 'STRIPE_SECRET_KEY';
|
|
const key = process.env[envKey] || process.env.STRIPE_SECRET_KEY;
|
|
if (!key) throw new Error(`Stripe key not configured (tried ${envKey})`);
|
|
|
|
const client = new Stripe(key);
|
|
_cache.set(cacheKey, client);
|
|
return client;
|
|
}
|
|
|
|
/** Alias for backward compatibility. */
|
|
export function getStripe(): Stripe {
|
|
return getStripeForProduct();
|
|
}
|
|
|
|
/** Get price IDs — configurable per product in the future. */
|
|
export function getPriceIds(): Record<string, string> {
|
|
return {
|
|
pro: process.env.STRIPE_PRICE_PRO || 'price_pro_placeholder',
|
|
enterprise: process.env.STRIPE_PRICE_ENTERPRISE || 'price_enterprise_placeholder',
|
|
};
|
|
}
|
|
|
|
export const PRICE_IDS: Record<string, string> = getPriceIds();
|