Files
myeasycms-v2/apps/web/config/billing.config.ts
Zaid Marzguioui 28188bb3a6
Some checks failed
Workflow / ʦ TypeScript (push) Failing after 6m3s
Workflow / ⚫️ Test (push) Has been skipped
fix(billing): wire up Stripe checkout with real price IDs and env vars
- Replace 8 placeholder price IDs (price_starter_monthly, etc.) with real
  Stripe test-mode price IDs created via API
- Add STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, NEXT_PUBLIC_BILLING_PROVIDER,
  and NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY to docker-compose.yml (build args + runtime)
- Add NEXT_PUBLIC_BILLING_PROVIDER ARG/ENV to Dockerfile
- Enable team and personal account billing (was 'false')
- Created Stripe webhook endpoint for production URL
- Created 4 Stripe products (Starter/Pro/Verband/Enterprise) with monthly+yearly prices

Checkout was crashing because:
1. STRIPE_SECRET_KEY was missing → Zod validation failed at createStripeClient()
2. STRIPE_WEBHOOK_SECRET was missing → same Zod schema rejection
3. NEXT_PUBLIC_BILLING_PROVIDER was unset → BillingProviderSchema.parse() failed
4. Price IDs were placeholders, not real Stripe price_xxx IDs
2026-04-02 23:34:30 +02:00

217 lines
6.1 KiB
TypeScript

/**
* MyEasyCMS Billing Configuration
*
* Four tiers based on club/organization size:
* Starter — 29 €/mo (up to 250 members)
* Pro — 59 €/mo (up to 1.000 members)
* Verband — 199 €/mo (up to 10.000 members, multi-level hierarchy)
* Enterprise — 349 €/mo (unlimited, dedicated support)
*
* Yearly plans get ~2 months free (billed annually).
*/
import { BillingProviderSchema, createBillingSchema } from '@kit/billing';
const provider = BillingProviderSchema.parse(
process.env.NEXT_PUBLIC_BILLING_PROVIDER,
);
export default createBillingSchema({
provider,
products: [
// ── Starter ──────────────────────────────────────────────
{
id: 'starter',
name: 'Starter',
description: 'Für kleine Vereine bis 250 Mitglieder',
currency: 'EUR',
badge: 'Einstieg',
plans: [
{
name: 'Starter Monatlich',
id: 'starter-monthly',
paymentType: 'recurring',
interval: 'month',
lineItems: [
{
id: 'price_1THsqKKttnWb7SsFttMu9VzG',
name: 'Starter',
cost: 29,
type: 'flat' as const,
},
],
},
{
name: 'Starter Jährlich',
id: 'starter-yearly',
paymentType: 'recurring',
interval: 'year',
lineItems: [
{
id: 'price_1THsqLKttnWb7SsFgvjsKXzs',
name: 'Starter',
cost: 290,
type: 'flat' as const,
},
],
},
],
features: [
'Bis zu 250 Mitglieder',
'Mitgliederverwaltung',
'SEPA-Lastschrifteinzug',
'Veranstaltungsmanagement',
'Vereins-Website (Baukasten)',
'Newsletter-Versand',
'Dokumenten-Generator',
'E-Mail-Support',
],
},
// ── Pro ───────────────────────────────────────────────────
{
id: 'pro',
name: 'Pro',
badge: 'Beliebt',
highlighted: true,
description: 'Für aktive Vereine bis 1.000 Mitglieder',
currency: 'EUR',
plans: [
{
name: 'Pro Monatlich',
id: 'pro-monthly',
paymentType: 'recurring',
interval: 'month',
lineItems: [
{
id: 'price_1THsqLKttnWb7SsFlWPf5IdP',
name: 'Pro',
cost: 59,
type: 'flat' as const,
},
],
},
{
name: 'Pro Jährlich',
id: 'pro-yearly',
paymentType: 'recurring',
interval: 'year',
lineItems: [
{
id: 'price_1THsqMKttnWb7SsFZq3A4QkU',
name: 'Pro',
cost: 590,
type: 'flat' as const,
},
],
},
],
features: [
'Bis zu 1.000 Mitglieder',
'Alles aus Starter',
'Kursverwaltung (VHS-Modus)',
'Buchungssystem (Räume & Gäste)',
'Rechnungswesen & Mahnungen',
'Unbegrenzte Benutzer',
'Benutzerdefinierte Module',
'Telefon-Support',
],
},
// ── Verband ──────────────────────────────────────────────
{
id: 'verband',
name: 'Verband',
badge: 'Verbände',
description: 'Für Verbände und Dachorganisationen',
currency: 'EUR',
plans: [
{
name: 'Verband Monatlich',
id: 'verband-monthly',
paymentType: 'recurring',
interval: 'month',
lineItems: [
{
id: 'price_1THsqNKttnWb7SsFGv7YskgJ',
name: 'Verband',
cost: 199,
type: 'flat' as const,
},
],
},
{
name: 'Verband Jährlich',
id: 'verband-yearly',
paymentType: 'recurring',
interval: 'year',
lineItems: [
{
id: 'price_1THsqNKttnWb7SsFhNl2bVn8',
name: 'Verband',
cost: 1990,
type: 'flat' as const,
},
],
},
],
features: [
'Bis zu 10.000 Mitglieder',
'Alles aus Pro',
'Mehrebenen-Verbandshierarchie',
'Verbandsweite Mitgliedersuche',
'Geteilte Vorlagen & Events',
'Verbands-Berichtswesen',
'Fischerei-Modul (optional)',
'Sitzungsprotokolle (optional)',
'Prioritäts-Support',
],
},
// ── Enterprise ───────────────────────────────────────────
{
id: 'enterprise',
name: 'Enterprise',
description: 'Für große Organisationen mit individuellen Anforderungen',
currency: 'EUR',
plans: [
{
name: 'Enterprise Monatlich',
id: 'enterprise-monthly',
paymentType: 'recurring',
interval: 'month',
lineItems: [
{
id: 'price_1THsqOKttnWb7SsFlLjfLw72',
name: 'Enterprise',
cost: 349,
type: 'flat' as const,
},
],
},
{
name: 'Enterprise Jährlich',
id: 'enterprise-yearly',
paymentType: 'recurring',
interval: 'year',
lineItems: [
{
id: 'price_1THsqOKttnWb7SsF8Sr12isW',
name: 'Enterprise',
cost: 3490,
type: 'flat' as const,
},
],
},
],
features: [
'Unbegrenzte Mitglieder',
'Alles aus Verband',
'Dedizierte Infrastruktur',
'Individuelle Modulentwicklung',
'SLA & Uptime-Garantie',
'Persönlicher Account-Manager',
'Onboarding & Schulung',
'API-Zugang',
'Datenmigration inklusive',
],
},
],
});