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
This commit is contained in:
@@ -22,6 +22,7 @@ ARG NEXT_PUBLIC_ENABLE_FISCHEREI=true
|
||||
ARG NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS=true
|
||||
ARG NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG=true
|
||||
ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
||||
ARG NEXT_PUBLIC_BILLING_PROVIDER=stripe
|
||||
ENV NEXT_PUBLIC_CI=${NEXT_PUBLIC_CI}
|
||||
ENV NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL}
|
||||
ENV NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL}
|
||||
@@ -31,6 +32,7 @@ ENV NEXT_PUBLIC_ENABLE_FISCHEREI=${NEXT_PUBLIC_ENABLE_FISCHEREI}
|
||||
ENV NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS=${NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS}
|
||||
ENV NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG=${NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG}
|
||||
ENV NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
|
||||
ENV NEXT_PUBLIC_BILLING_PROVIDER=${NEXT_PUBLIC_BILLING_PROVIDER}
|
||||
RUN pnpm --filter web build
|
||||
|
||||
# --- Run ---
|
||||
|
||||
@@ -33,7 +33,7 @@ export default createBillingSchema({
|
||||
interval: 'month',
|
||||
lineItems: [
|
||||
{
|
||||
id: 'price_starter_monthly',
|
||||
id: 'price_1THsqKKttnWb7SsFttMu9VzG',
|
||||
name: 'Starter',
|
||||
cost: 29,
|
||||
type: 'flat' as const,
|
||||
@@ -47,7 +47,7 @@ export default createBillingSchema({
|
||||
interval: 'year',
|
||||
lineItems: [
|
||||
{
|
||||
id: 'price_starter_yearly',
|
||||
id: 'price_1THsqLKttnWb7SsFgvjsKXzs',
|
||||
name: 'Starter',
|
||||
cost: 290,
|
||||
type: 'flat' as const,
|
||||
@@ -82,7 +82,7 @@ export default createBillingSchema({
|
||||
interval: 'month',
|
||||
lineItems: [
|
||||
{
|
||||
id: 'price_pro_monthly',
|
||||
id: 'price_1THsqLKttnWb7SsFlWPf5IdP',
|
||||
name: 'Pro',
|
||||
cost: 59,
|
||||
type: 'flat' as const,
|
||||
@@ -96,7 +96,7 @@ export default createBillingSchema({
|
||||
interval: 'year',
|
||||
lineItems: [
|
||||
{
|
||||
id: 'price_pro_yearly',
|
||||
id: 'price_1THsqMKttnWb7SsFZq3A4QkU',
|
||||
name: 'Pro',
|
||||
cost: 590,
|
||||
type: 'flat' as const,
|
||||
@@ -130,7 +130,7 @@ export default createBillingSchema({
|
||||
interval: 'month',
|
||||
lineItems: [
|
||||
{
|
||||
id: 'price_verband_monthly',
|
||||
id: 'price_1THsqNKttnWb7SsFGv7YskgJ',
|
||||
name: 'Verband',
|
||||
cost: 199,
|
||||
type: 'flat' as const,
|
||||
@@ -144,7 +144,7 @@ export default createBillingSchema({
|
||||
interval: 'year',
|
||||
lineItems: [
|
||||
{
|
||||
id: 'price_verband_yearly',
|
||||
id: 'price_1THsqNKttnWb7SsFhNl2bVn8',
|
||||
name: 'Verband',
|
||||
cost: 1990,
|
||||
type: 'flat' as const,
|
||||
@@ -178,7 +178,7 @@ export default createBillingSchema({
|
||||
interval: 'month',
|
||||
lineItems: [
|
||||
{
|
||||
id: 'price_enterprise_monthly',
|
||||
id: 'price_1THsqOKttnWb7SsFlLjfLw72',
|
||||
name: 'Enterprise',
|
||||
cost: 349,
|
||||
type: 'flat' as const,
|
||||
@@ -192,7 +192,7 @@ export default createBillingSchema({
|
||||
interval: 'year',
|
||||
lineItems: [
|
||||
{
|
||||
id: 'price_enterprise_yearly',
|
||||
id: 'price_1THsqOKttnWb7SsF8Sr12isW',
|
||||
name: 'Enterprise',
|
||||
cost: 3490,
|
||||
type: 'flat' as const,
|
||||
|
||||
@@ -330,6 +330,9 @@ services:
|
||||
# Browser-side Supabase URL — goes through external domain (Traefik → Kong)
|
||||
NEXT_PUBLIC_SUPABASE_URL: ${API_EXTERNAL_URL:-http://localhost:8000}
|
||||
NEXT_PUBLIC_SUPABASE_PUBLIC_KEY: ${SUPABASE_ANON_KEY}
|
||||
# Stripe (build-time)
|
||||
NEXT_PUBLIC_BILLING_PROVIDER: stripe
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
supabase-kong:
|
||||
@@ -352,12 +355,17 @@ services:
|
||||
NEXT_PUBLIC_ENABLE_THEME_TOGGLE: 'true'
|
||||
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS: 'true'
|
||||
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION: 'true'
|
||||
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING: 'false'
|
||||
NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING: 'false'
|
||||
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING: 'true'
|
||||
NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING: 'true'
|
||||
NEXT_PUBLIC_ENABLE_NOTIFICATIONS: 'true'
|
||||
NEXT_PUBLIC_ENABLE_FISCHEREI: 'true'
|
||||
NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS: 'true'
|
||||
NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG: 'true'
|
||||
# Stripe (runtime)
|
||||
NEXT_PUBLIC_BILLING_PROVIDER: stripe
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
|
||||
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
|
||||
STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET}
|
||||
|
||||
volumes:
|
||||
supabase-db-data:
|
||||
|
||||
Reference in New Issue
Block a user