xtablo-source/docs/STRIPE_FINAL_SETUP.md
Arthur Belleville 7bb90becb9
IA docs
2025-11-03 09:46:10 +01:00

6.4 KiB

🎉 Final Stripe Setup - Using Official Library

Overview

We're using the official @supabase/stripe-sync-engine library from Supabase.
This handles ALL webhook processing automatically - we just add custom profile integration on top!

Repository: https://github.com/supabase/stripe-sync-engine

📦 What's Implemented

Files That Matter

Backend:

  • api/src/stripe.ts - Webhook + action endpoints (uses StripeSync)
  • sql/35_stripe_wrappers.sql - Profile integration & RLS policies

Frontend:

  • apps/main/src/hooks/stripe.ts - React hooks (queries Supabase directly)
  • apps/main/src/components/SubscriptionCard.tsx - Ready-to-use UI

Documentation:

  • docs/STRIPE_WITH_SYNC_ENGINE.md - Main guide
  • docs/TESTING_WITH_FAKE_ACCOUNTS.md - Testing guide

Files Deleted (Not Needed Anymore)

  • api/src/stripe-webhook.ts - Library handles this!
  • sql/36_stripe_webhooks.sql - Library handles this!

🚀 Setup Steps

1. Install Library

cd api
npm install @supabase/stripe-sync-engine

Already done!

2. Run Library Migrations

The library needs to create its tables first. Either:

Option A: Via Code (recommended for first time)

import { runMigrations } from "@supabase/stripe-sync-engine";

await runMigrations({
  databaseUrl:
    "postgresql://postgres:[password]@db.[project].supabase.co:5432/postgres",
});

Option B: Manually Copy migrations from node_modules/@supabase/stripe-sync-engine/dist/migrations/*.sql and run in Supabase SQL Editor.

3. Run Custom SQL

After library migrations, run:

\i sql/35_stripe_wrappers.sql

This adds:

  • user_id columns for RLS
  • profiles.is_paying and subscription_tier fields
  • Automatic triggers
  • Helper functions

4. Configure Environment

API (.env):

STRIPE_SECRET_KEY=sk_test_xxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxx
DATABASE_URL=postgresql://postgres:[password]@db.[project].supabase.co:5432/postgres
FRONTEND_URL=http://localhost:5173

Frontend (apps/main/.env):

VITE_STRIPE_PUBLISHABLE_KEY=pk_test_xxxxx
VITE_STRIPE_STANDARD_MONTHLY_PRICE_ID=price_xxxxx

5. Create "Standard" Product in Stripe

  1. Stripe Dashboard → Test Mode → Products
  2. Add product: "Standard"
  3. Monthly price: €9.99/month
  4. Copy the price_id
  5. Add to frontend .env

6. Configure Webhook

  1. Stripe Dashboard → Developers → Webhooks
  2. Add endpoint: https://your-api.com/api/v1/stripe/webhook
  3. Select all events (library handles them all!)
  4. Copy signing secret → Add to API .env

7. Add UI to Settings

In apps/main/src/pages/settings.tsx:

import { SubscriptionCard } from "../components/SubscriptionCard";

// Add in your cards section:
<SubscriptionCard />;

🎯 How It Works

Webhook Flow

Stripe event → API webhook endpoint → StripeSync library → Database tables → Triggers → Profile updated

Read Flow (From Frontend)

Frontend → Supabase Client → RLS policies → stripe_subscriptions → User's data

No custom webhook code needed! The library handles everything.

🧪 Testing

Quick Test

  1. Start API: cd api && npm run dev

  2. Start Frontend: cd apps/main && npm run dev

  3. Start Webhook Forwarding:

    stripe listen --forward-to http://localhost:3000/api/v1/stripe/webhook
    
  4. Create test account: test@example.com

  5. Subscribe: Use card 4242 4242 4242 4242

  6. Verify: Check user.is_paying === true

📊 What Tables Are Created

By stripe-sync-engine Library:

  • stripe_customers
  • stripe_subscriptions
  • stripe_subscription_items
  • stripe_products
  • stripe_prices
  • stripe_invoices
  • stripe_charges
  • stripe_payment_intents
  • stripe_payment_methods
  • ... and 30+ more!

By Our SQL (35_stripe_wrappers.sql):

  • Adds user_id to customers/subscriptions
  • Adds is_paying to profiles
  • Adds subscription_tier to profiles
  • Creates RLS policies
  • Creates triggers
  • Creates helper functions

Key Advantages

Aspect Before After (with library)
Webhook code 267 lines ~15 lines
Event coverage 8 events 100+ events
Maintenance You Supabase
Schema updates Manual Automatic
Backfilling Custom scripts Built-in
Battle-tested No Yes

🎓 Using the Library Features

Backfill Historical Data

// Sync all existing Stripe data
await stripeSync.syncBackfill({ object: "all" });

// Or sync specific objects
await stripeSync.syncProducts();
await stripeSync.syncCustomers();
await stripeSync.syncSubscriptions();

Sync Single Entity

// Sync a specific customer
await stripeSync.syncSingleEntity("cus_xxxxx");

// Sync a specific subscription
await stripeSync.syncSingleEntity("sub_xxxxx");

Success Criteria

Your integration works when:

  1. Library installed: npm list @supabase/stripe-sync-engine
  2. Library migrations run
  3. Custom SQL (35) run
  4. Environment variables configured
  5. Webhook endpoint configured in Stripe
  6. Test subscription creates data in stripe_subscriptions
  7. profiles.is_paying updates automatically
  8. Frontend shows subscription status
  9. RLS policies work (users see only their data)

🐛 Troubleshooting

Library Not Found

cd api && npm install @supabase/stripe-sync-engine

Migrations Failing

Make sure to run library migrations first, then sql/35_stripe_wrappers.sql

user_id Not Populating

Ensure customer is created with metadata:

stripe.customers.create({
  email: user.email,
  metadata: { user_id: user.id }, // ← Important!
});

This is already handled in api/src/stripe.ts create-checkout-session endpoint.

📞 Support


Status: Fully Implemented
Complexity: Minimal (library does the heavy lifting)
Maintenance: Low (library handles updates)
Ready to Deploy: Yes!