# Stripe Subscription Integration

Complete Stripe subscription system for managing location-based subscriptions.

## 📋 Table of Contents
- [Setup](#setup)
- [Database Schema](#database-schema)
- [API Endpoints](#api-endpoints)
- [Webhook Events](#webhook-events)
- [Testing](#testing)
- [Frontend Integration](#frontend-integration)

---

## 🚀 Setup

### 1. Environment Variables

Add the following to your `.env` file:

```env
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxx
FRONTEND_URL=http://localhost:3000
```

### 2. Database Migration

Run Prisma migration to add the `stripe_price_id` field to the `plans` table:

```bash
npx prisma migrate dev --name add_stripe_price_id
```

### 3. Seed Plans Data

Ensure your `plans` table has the `stripe_price_id` populated:

```sql
UPDATE plans SET stripe_price_id = 'price_xxxxxxxxxxxxx' WHERE id = 2;
UPDATE plans SET stripe_price_id = 'price_xxxxxxxxxxxxx' WHERE id = 3;
```

### 4. Configure Stripe Webhook

1. Go to Stripe Dashboard → Developers → Webhooks
2. Add endpoint: `https://your-domain.com/api/stripe/webhook`
3. Select events to listen to:
   - `checkout.session.completed`
   - `customer.subscription.deleted`
4. Copy the webhook signing secret to `STRIPE_WEBHOOK_SECRET`

---

## 📊 Database Schema

### Plans Table
```prisma
model Plan {
  id              Int       @id @default(autoincrement())
  plan_code       String    @unique
  display_name    String
  description     String?
  price_per_month Decimal
  stripe_price_id String?   // Stripe Price ID for checkout
  created_at      DateTime  @default(now())
  updated_at      DateTime  @default(now())
}
```

### Subscriptions Table
```prisma
model Subscription {
  id                       Int                @id @default(autoincrement())
  location_id              Int
  plan_id                  Int?
  billing_source           BillingSource
  external_subscription_id String
  status                   SubscriptionStatus
  price_per_month          Decimal?
  started_at               DateTime?
  ended_at                 DateTime?
  created_at               DateTime           @default(now())
}
```

### Locations Table (Updated Fields)
```prisma
model Location {
  // ... other fields
  active_subscription_id String?
  plan_id                Int?
  price_per_month        Decimal?
  billing_source         BillingSource @default(stripe)
}
```

---

## 🔌 API Endpoints

### 1. Get All Plans

**GET** `/api/plans`

Get all available plans, optionally filtered by user type.

**Query Parameters:**
- `user_type` (optional): Filter plans by user type
  - If `user_type=direct_client`, returns only plans with `id` 2 and 3

**Response:**
```json
{
  "success": true,
  "data": [
    {
      "id": 2,
      "plan_code": "basic",
      "display_name": "Basic Plan",
      "description": "Perfect for small businesses",
      "price_per_month": 29.99,
      "stripe_price_id": "price_xxxxxxxxxxxxx"
    },
    {
      "id": 3,
      "plan_code": "pro",
      "display_name": "Pro Plan",
      "description": "For growing businesses",
      "price_per_month": 79.99,
      "stripe_price_id": "price_xxxxxxxxxxxxx"
    }
  ]
}
```

**Example:**
```bash
# Get all plans
curl http://localhost:5000/api/plans

# Get plans for direct clients only
curl http://localhost:5000/api/plans?user_type=direct_client
```

---

### 2. Create Checkout Session

**POST** `/api/stripe/create-checkout-session`

Create a Stripe Checkout session for a subscription.

**Request Body:**
```json
{
  "plan_id": 2,
  "location_id": 123
}
```

**Response:**
```json
{
  "success": true,
  "data": {
    "url": "https://checkout.stripe.com/c/pay/cs_test_xxxxxxxxxxxxx"
  }
}
```

**Example:**
```bash
curl -X POST http://localhost:5000/api/stripe/create-checkout-session \
  -H "Content-Type: application/json" \
  -d '{
    "plan_id": 2,
    "location_id": 123
  }'
```

**What Happens:**
1. Validates `plan_id` and `location_id`
2. Fetches plan from database
3. Verifies location exists
4. Creates Stripe Checkout session with:
   - Plan's `stripe_price_id`
   - Metadata: `plan_id`, `location_id`
   - Success/Cancel URLs
5. Returns checkout URL

---

### 3. Stripe Webhook

**POST** `/api/stripe/webhook`

Handles Stripe webhook events (called by Stripe, not your frontend).

**Headers:**
- `stripe-signature`: Webhook signature for verification

**Supported Events:**

#### `checkout.session.completed`
Triggered when a customer completes checkout.

**Actions:**
1. Creates a new record in `subscriptions` table:
   - `location_id`: From metadata
   - `plan_id`: From metadata
   - `external_subscription_id`: Stripe subscription ID
   - `status`: "active"
   - `billing_source`: "stripe"
   - `price_per_month`: From plan
   - `started_at`: Current timestamp

2. Updates `locations` table:
   - `active_subscription_id`: Stripe subscription ID
   - `plan_id`: Selected plan ID
   - `price_per_month`: From plan
   - `billing_source`: "stripe"

#### `customer.subscription.deleted`
Triggered when a subscription is canceled.

**Actions:**
1. Finds subscription in database by `external_subscription_id`
2. Updates `subscriptions` table:
   - `status`: "canceled"
   - `ended_at`: Current timestamp
3. Updates `locations` table:
   - `active_subscription_id`: null

---

## 🧪 Testing

### Test Checkout Flow

1. **Get available plans:**
```bash
curl http://localhost:5000/api/plans?user_type=direct_client
```

2. **Create checkout session:**
```bash
curl -X POST http://localhost:5000/api/stripe/create-checkout-session \
  -H "Content-Type: application/json" \
  -d '{
    "plan_id": 2,
    "location_id": 1
  }'
```

3. **Visit the returned URL** and complete checkout using Stripe test cards:
   - Success: `4242 4242 4242 4242`
   - Decline: `4000 0000 0000 0002`

### Test Webhook Locally

Use Stripe CLI to forward webhooks to your local server:

```bash
# Install Stripe CLI
# https://stripe.com/docs/stripe-cli

# Login
stripe login

# Forward webhooks
stripe listen --forward-to localhost:5000/api/stripe/webhook

# Trigger test events
stripe trigger checkout.session.completed
stripe trigger customer.subscription.deleted
```

---

## 🎨 Frontend Integration

### React Example

```jsx
import { useState } from 'react';

function SubscriptionPage() {
  const [plans, setPlans] = useState([]);
  const [loading, setLoading] = useState(false);

  // Fetch plans
  useEffect(() => {
    fetch('http://localhost:5000/api/plans?user_type=direct_client')
      .then(res => res.json())
      .then(data => setPlans(data.data));
  }, []);

  // Handle subscription
  const handleSubscribe = async (planId, locationId) => {
    setLoading(true);
    
    try {
      const response = await fetch('http://localhost:5000/api/stripe/create-checkout-session', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          plan_id: planId,
          location_id: locationId,
        }),
      });

      const data = await response.json();
      
      if (data.success) {
        // Redirect to Stripe Checkout
        window.location.href = data.data.url;
      }
    } catch (error) {
      console.error('Error:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <h1>Choose Your Plan</h1>
      {plans.map(plan => (
        <div key={plan.id}>
          <h2>{plan.display_name}</h2>
          <p>{plan.description}</p>
          <p>${plan.price_per_month}/month</p>
          <button 
            onClick={() => handleSubscribe(plan.id, YOUR_LOCATION_ID)}
            disabled={loading}
          >
            Subscribe
          </button>
        </div>
      ))}
    </div>
  );
}
```

### Success/Cancel Pages

Create these pages in your frontend:

1. **Success Page** (`/subscription/success`)
```jsx
function SubscriptionSuccess() {
  const searchParams = new URLSearchParams(window.location.search);
  const sessionId = searchParams.get('session_id');

  return (
    <div>
      <h1>Subscription Successful!</h1>
      <p>Your subscription is now active.</p>
      <p>Session ID: {sessionId}</p>
    </div>
  );
}
```

2. **Cancel Page** (`/subscription/cancel`)
```jsx
function SubscriptionCancel() {
  return (
    <div>
      <h1>Subscription Canceled</h1>
      <p>You can try again anytime.</p>
    </div>
  );
}
```

---

## 🔒 Security Notes

1. **Never expose `STRIPE_SECRET_KEY`** in frontend code
2. **Always verify webhook signatures** (handled automatically)
3. **Use HTTPS in production** for webhook endpoint
4. **Validate all inputs** before processing
5. **Store webhook secret securely** in environment variables

---

## 📝 File Structure

```
src/
├── services/
│   ├── plan.service.js       # Plan fetching logic
│   └── stripe.service.js     # Stripe checkout & webhook logic
├── controllers/
│   ├── plan.controller.js    # Plan API handlers
│   └── stripe.controller.js  # Stripe API handlers
├── routes/
│   ├── plan.routes.js        # Plan routes
│   └── stripe.routes.js      # Stripe routes
└── app.js                    # Express app with webhook middleware
```

---

## 🐛 Troubleshooting

### Webhook signature verification failed
- Ensure `STRIPE_WEBHOOK_SECRET` is correctly set
- Check that raw body parsing is enabled for webhook route
- Verify webhook endpoint URL in Stripe Dashboard

### Plan not found
- Ensure plans table has `stripe_price_id` populated
- Check that plan IDs match your database

### Location not found
- Verify location exists in database
- Check location_id is correct

---

## 📚 Additional Resources

- [Stripe Checkout Documentation](https://stripe.com/docs/payments/checkout)
- [Stripe Webhooks Guide](https://stripe.com/docs/webhooks)
- [Stripe Testing](https://stripe.com/docs/testing)
- [Prisma Documentation](https://www.prisma.io/docs)

---

## ✅ Checklist

Before going to production:

- [ ] Update `STRIPE_SECRET_KEY` to live key
- [ ] Update `STRIPE_WEBHOOK_SECRET` to live webhook secret
- [ ] Update `FRONTEND_URL` to production URL
- [ ] Configure production webhook endpoint in Stripe Dashboard
- [ ] Test all webhook events in production
- [ ] Enable HTTPS for webhook endpoint
- [ ] Set up monitoring for webhook failures
- [ ] Add error logging and alerting
