# Stripe Integration Setup Guide

This guide walks you through setting up Stripe payments integration for Xtablo with a single "Standard" plan.

## Table of Contents

1. [Prerequisites](#prerequisites)
2. [Database Setup](#database-setup)
3. [Stripe Configuration](#stripe-configuration)
4. [Backend API Setup](#backend-api-setup)
5. [Frontend Integration](#frontend-integration)
6. [Testing](#testing)
7. [Usage Examples](#usage-examples)

## Prerequisites

- Supabase project with database access
- Stripe account (test mode for development)
- Supabase Wrappers extension enabled
- Node.js API already running

## Database Setup

### 1. Run Migration Scripts

Execute the SQL migration files in your Supabase SQL Editor:

```sql
-- Execute these in order
\i sql/35_stripe_wrappers.sql  -- Creates tables, functions, RLS policies
\i sql/36_stripe_webhooks.sql  -- Creates webhook handler functions
```

These migrations create:

- ✅ Subscription tracking tables (`stripe_customers`, `stripe_subscriptions`, `stripe_products`, `stripe_prices`)
- ✅ Helper functions (`is_paying_user()`, `get_user_subscription_status()`)
- ✅ Automatic triggers to update `profiles.is_paying`
- ✅ Row Level Security policies
- ✅ Webhook handler functions

**No Wrappers needed!** This is a pure webhook-based integration.

## Stripe Configuration

### 1. Create Products and Prices

In your Stripe Dashboard:

1. Go to **Products**
2. Click **Add product**
3. Create your subscription tiers (e.g., "Premium", "Pro")
4. Add pricing (monthly, yearly, etc.)
5. Note the `price_id` (starts with `price_xxx`)

### 2. Create the "Standard" Plan

In your Stripe Dashboard:

1. Go to **Products**
2. Click **Add product**
3. Name: **"Standard"** (important: must match exactly)
4. Add your pricing:
   - Monthly: e.g., €9.99/month
   - Yearly: e.g., €99/year (optional)
5. **Save the price IDs** (e.g., `price_xxxxx`)

### 3. Set up Webhooks

1. Go to **Developers → Webhooks** in Stripe Dashboard
2. Click **Add endpoint**
3. URL: `https://YOUR_API_URL/api/v1/stripe/webhook`
4. Select events to listen to:
   - `customer.created`
   - `customer.updated`
   - `customer.deleted`
   - `customer.subscription.created`
   - `customer.subscription.updated`
   - `customer.subscription.deleted`
   - `product.created`
   - `product.updated`
   - `product.deleted`
   - `price.created`
   - `price.updated`
   - `price.deleted`
5. **Copy the webhook signing secret** (starts with `whsec_`)

## Backend API Setup

The backend API handlers are already implemented in:

- `api/src/stripe.ts` - Main Stripe routes
- `api/src/stripe-webhook.ts` - Webhook handler
- `api/src/routers.ts` - Router configuration

### 1. Install Stripe SDK

```bash
cd apps/api
npm install stripe @stripe/stripe-js
```

### 2. Configure Environment Variables

Add to your `.env` file:

```env
# Stripe
STRIPE_SECRET_KEY=sk_test_xxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxx

# For webhooks to work
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
```

### 3. Restart API Server

The Stripe routes are automatically registered at:

- `POST /api/v1/stripe/webhook` - Webhook endpoint
- `POST /api/v1/stripe/create-checkout-session` - Create checkout
- `POST /api/v1/stripe/create-portal-session` - Customer portal
- `GET /api/v1/stripe/subscription` - Get subscription status
- `GET /api/v1/stripe/is-paying` - Check if paying
- `GET /api/v1/stripe/prices` - Get available prices
- `POST /api/v1/stripe/cancel-subscription` - Cancel subscription
- `POST /api/v1/stripe/reactivate-subscription` - Reactivate subscription

## Frontend Integration

The frontend hooks are already implemented in `apps/main/src/hooks/stripe.ts`.

### 1. Install Stripe SDK

```bash
cd apps/main
npm install @stripe/stripe-js
```

### 2. Configure Environment Variable

Add to `apps/main/.env`:

```env
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_xxxxx
```

### 3. Available Hooks

All hooks are ready to use:

```typescript
import {
  // Direct Supabase queries (RLS-protected)
  useSubscription, // Get subscription from Supabase
  useIsPayingUser, // Check if paying (from user.is_paying)
  useStripePrices, // Get prices from Supabase

  // API calls (for actions)
  useCreateCheckoutSession, // Start checkout
  useCreatePortalSession, // Open customer portal
  useCancelSubscription, // Cancel subscription
  useReactivateSubscription, // Reactivate subscription
} from "../hooks/stripe";
```

**Architecture:**

- 📖 **Reads**: Direct Supabase queries (fast, RLS-protected)
- ✍️ **Writes**: API calls to Stripe → Webhooks update Supabase

## Usage Examples

### Check if User is Paying

```typescript
// In any component
const { data: isPaying } = useIsPayingUser();

if (!isPaying) {
  return <UpgradePrompt />;
}
```

### Get Subscription Details (Queries Supabase Directly)

```typescript
const { data: subscription } = useSubscription();

if (subscription) {
  console.log("Status:", subscription.status);
  console.log("Renews:", subscription.current_period_end);
  console.log("Will cancel?:", subscription.cancel_at_period_end);

  // Access related product/price via join
  console.log("Product:", subscription.price?.product?.name);
  console.log("Amount:", subscription.price?.unit_amount);
}
```

### Access Subscription Status from Profile

```typescript
// The user profile already has is_paying and subscription_tier fields
const user = useUser();

if (user.is_paying) {
  console.log("User is on:", user.subscription_tier);
}
```

### Create Checkout Session

```typescript
import { useCreateCheckoutSession } from "../hooks/stripe";

function UpgradeButton() {
  const { mutate: createCheckout, isPending } = useCreateCheckoutSession();

  return (
    <button
      onClick={() =>
        createCheckout({
          priceId: "price_xxxxx", // Your Standard plan price ID
        })
      }
      disabled={isPending}
    >
      {isPending ? "Loading..." : "Subscribe to Standard"}
    </button>
  );
}
```

### Manage Subscription (Customer Portal)

```typescript
import { useCreatePortalSession } from "../hooks/stripe";

function ManageSubscriptionButton() {
  const { mutate: openPortal, isPending } = useCreatePortalSession();

  return (
    <button
      onClick={() => openPortal(window.location.href)}
      disabled={isPending}
    >
      Manage Subscription
    </button>
  );
}
```

### Cancel Subscription

```typescript
import { useCancelSubscription } from "../hooks/stripe";

function CancelButton() {
  const { mutate: cancel, isPending } = useCancelSubscription();

  return (
    <button onClick={() => cancel()} disabled={isPending}>
      Cancel Subscription
    </button>
  );
}
```

## Testing

### 1. Use Stripe Test Mode

Use test cards from [Stripe Testing](https://stripe.com/docs/testing):

- Success: `4242 4242 4242 4242`
- Decline: `4000 0000 0000 0002`

### 2. Test Webhooks Locally

```bash
# Install Stripe CLI
brew install stripe/stripe-cli/stripe

# Login
stripe login

# Forward webhooks to local API
stripe listen --forward-to http://localhost:3000/api/v1/stripe/webhook
```

### 3. Trigger Test Events

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

## Security Checklist

- [ ] Stripe API keys stored in Supabase Vault
- [ ] Webhook signing secret configured
- [ ] Row Level Security (RLS) enabled on all tables
- [ ] Edge Function uses service role key
- [ ] Customer metadata includes user_id for mapping
- [ ] Test mode used for development

## Troubleshooting

### Webhooks Not Working

1. Check webhook endpoint URL is correct (`https://your-api/api/v1/stripe/webhook`)
2. Verify signing secret matches in `.env`
3. Check API logs for webhook errors
4. Ensure `SUPABASE_SERVICE_ROLE_KEY` is set in API environment
5. Test with Stripe CLI: `stripe trigger customer.subscription.created`

### Subscription Not Showing

1. Verify customer has `user_id` in metadata
2. Check webhook was received (Stripe Dashboard → Webhooks)
3. Query `stripe_subscriptions` table directly
4. Check `profiles.is_paying` was updated by trigger

### Foreign Tables Empty

1. Verify Stripe API key is correct
2. Check key_id in server configuration
3. Test with: `SELECT * FROM stripe.customers LIMIT 5;`
4. Ensure Wrappers extension is enabled

## Next Steps

1. Create pricing page component
2. Build subscription management UI
3. Implement usage-based billing (if needed)
4. Add customer portal for self-service
5. Set up email notifications for billing events

---

For more information, see:

- [Supabase Stripe Integration](https://supabase.com/docs/guides/integrations/stripe)
- [Stripe Documentation](https://stripe.com/docs)
- [Supabase Wrappers](https://supabase.github.io/wrappers/)
