xtablo-source/docs/STRIPE_README.md
2025-11-10 08:53:03 +01:00

6.2 KiB

💳 Stripe Integration for Xtablo

Complete Stripe subscription integration with a single "Standard" plan using your Node.js API.

📁 Files Created

Database (SQL)

  • sql/35_stripe_wrappers.sql - Database schema, tables, functions, triggers
  • sql/36_stripe_webhooks.sql - Webhook handler functions

Backend (Node.js API)

  • api/src/stripe.ts - API routes for Stripe operations
  • api/src/stripe-webhook.ts - Webhook event processor
  • api/src/routers.ts - Updated with Stripe routes

Frontend (React)

  • apps/main/src/hooks/stripe.ts - React hooks for Stripe
  • apps/main/src/components/SubscriptionCard.tsx - Ready-to-use subscription UI
  • packages/shared/src/types/stripe.types.ts - TypeScript types

Documentation

  • docs/STRIPE_SETUP.md - Complete setup guide
  • docs/STRIPE_IMPLEMENTATION_SUMMARY.md - Technical overview
  • docs/STRIPE_QUICK_REFERENCE.md - Quick reference guide
  • docs/STRIPE_README.md - This file

Quick Setup

1. Install Dependencies

cd apps/api && npm install stripe @stripe/stripe-js
cd ../apps/main && npm install @stripe/stripe-js

2. Run Database Migrations

Execute in Supabase SQL Editor:

\i sql/35_stripe_wrappers.sql
\i sql/36_stripe_webhooks.sql

3. Configure Stripe Dashboard

  1. Create product named "Standard"
  2. Add monthly/yearly pricing
  3. Save the price IDs
  4. Add webhook endpoint: https://your-api.com/api/v1/stripe/webhook
  5. Copy webhook signing secret

4. Set Environment Variables

API (.env):

STRIPE_SECRET_KEY=sk_test_xxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxx
SUPABASE_SERVICE_ROLE_KEY=your_key
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. Add Subscription Card to Settings

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

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

// Inside your settings page JSX, add:
<SubscriptionCard />

🎯 How It Works

User Journey

  1. Free User sees upgrade prompt in SubscriptionCard
  2. Clicks "Passer à Standard"
  3. Redirected to Stripe Checkout
  4. Completes payment
  5. Redirected back to settings with ?success=true
  6. Webhook updates database
  7. user.is_paying becomes true
  8. user.subscription_tier becomes 'standard'
  9. UI automatically updates

Data Sync

Stripe → Webhook → API → Database → Frontend
                           ↓
                    profiles.is_paying = true

🎨 Using Subscription Card

The SubscriptionCard component shows:

For Free Users:

  • "Plan Gratuit" badge
  • "Passer à Standard" button
  • Initiates Stripe Checkout

For Paying Users:

  • "Actif" badge
  • Current subscription details
  • Renewal date
  • "Gérer l'abonnement" button (opens Stripe portal)
  • "Annuler" button

For Canceling Users:

  • "Annulation en cours" warning
  • Access until period end
  • "Réactiver l'abonnement" button

🔍 Check Payment Status Anywhere

import { useUser } from '../providers/UserStoreProvider';

function PremiumFeature() {
  const user = useUser();
  
  if (!user.is_paying) {
    return <UpgradePrompt />;
  }
  
  return <PremiumContent />;
}

🎣 Available Hooks

// Get subscription details
const { data: subscription } = useSubscription();

// Check if paying (boolean)
const { data: isPaying } = useIsPayingUser();

// Get available prices
const { data: prices } = useStripePrices();

// Create checkout session
const { mutate: checkout } = useCreateCheckoutSession();
checkout({ priceId: 'price_xxxxx' });

// Open customer portal
const { mutate: portal } = useCreatePortalSession();
portal();

// Cancel subscription
const { mutate: cancel } = useCancelSubscription();
cancel();

// Reactivate subscription
const { mutate: reactivate } = useReactivateSubscription();
reactivate();

🧪 Testing

Test Cards

Success: 4242 4242 4242 4242
Decline: 4000 0000 0000 0002

Test Webhooks Locally

stripe listen --forward-to http://localhost:3000/api/v1/stripe/webhook

Trigger Events

stripe trigger customer.subscription.created
stripe trigger customer.subscription.updated
stripe trigger customer.subscription.deleted

🔐 Security Features

Webhook signature verification
Row Level Security on all tables
Users can only see their own subscriptions
API keys never exposed to frontend
Service role for database operations

📊 Database Schema

Tables

  • stripe_customers - Links Stripe customers to users
  • stripe_subscriptions - Subscription records
  • stripe_products - Product catalog
  • stripe_prices - Pricing information

Profile Fields

  • is_paying: boolean - Quick check for payment status
  • subscription_tier: 'free' | 'standard' - Current tier

Functions

  • is_paying_user(uuid) - Returns boolean
  • get_user_subscription_status(uuid) - Returns subscription details
  • get_user_stripe_customer_id(uuid) - Returns Stripe customer ID

🐛 Troubleshooting

Webhooks not working?

  1. Check API logs
  2. Verify webhook secret in .env
  3. Test with Stripe CLI
  4. Check Stripe Dashboard → Webhooks for delivery status

Subscription not showing?

  1. Check stripe_subscriptions table in Supabase
  2. Verify webhook was received
  3. Check profiles.is_paying field
  4. Ensure customer has user_id in metadata

Can't create checkout?

  1. Verify STRIPE_SECRET_KEY is set
  2. Check VITE_STRIPE_PUBLISHABLE_KEY in frontend
  3. Ensure price ID is correct
  4. Check browser console for errors

📞 Support

See detailed docs:

  • Setup Guide: docs/STRIPE_SETUP.md
  • Technical Details: docs/STRIPE_IMPLEMENTATION_SUMMARY.md
  • Quick Reference: docs/STRIPE_QUICK_REFERENCE.md

🎉 Next Steps

  1. Database schema created
  2. API endpoints implemented
  3. Frontend hooks ready
  4. UI component created
  5. Run migrations
  6. Configure Stripe
  7. Set environment variables
  8. Test with test cards
  9. Add SubscriptionCard to settings page

Status: Implementation Complete
Architecture: Node.js API + Supabase Database
Plan: Single "Standard" tier
Ready to Deploy: Yes, follow setup guide