# Subscriptions Create Checkout API

**Path**: `/api/subscriptions/create-checkout`

## Overview

This endpoint creates a Stripe checkout session for **existing authenticated users** who want to subscribe or upgrade their plan. It differs from the signup checkout in that it requires authentication and uses the user's existing account information.

## Authentication

**Required**: User must be authenticated via NextAuth session or JWT token.

Uses `getAuthenticatedUser(request)` which supports both:

- NextAuth OAuth sessions
- Custom JWT tokens (from OTP login)

## Request

**Method**: `POST`

**Body**:

```json
{
  "tierId": "tier1" | "tier2" | "tier3" | "tier4" | "tier5",
  "billingPeriod": "monthly" | "yearly",
  "currency": "QAR",
  "language": "en" | "ar"
}
```

**Headers**:

- `Content-Type: application/json`
- Authentication cookie (either NextAuth or `auth_token`)

## Response

**Success (200)**:

```json
{
  "sessionUrl": "https://checkout.stripe.com/pay/cs_test_...",
  "sessionId": "cs_test_123",
  "success": true
}
```

**Error Responses**:

| Status | Code                       | Description                            |
| ------ | -------------------------- | -------------------------------------- |
| 401    | `UNAUTHENTICATED`          | User not authenticated                 |
| 400    | `VALIDATION_ERROR`         | Invalid input parameters               |
| 400    | `INVALID_CURRENCY`         | Non-QAR currency requested             |
| 404    | `PRICE_NOT_FOUND`          | Stripe price not found for tier/period |
| 500    | `CUSTOMER_CREATION_FAILED` | Failed to create Stripe customer       |
| 500    | `SESSION_CREATION_FAILED`  | Failed to create checkout session      |
| 429    | `RATE_LIMIT_EXCEEDED`      | Too many requests                      |

## Key Features

### 1. Authentication Required

- User must be logged in
- Supports both NextAuth and JWT authentication
- Returns 401 if not authenticated

### 2. Automatic Customer Management

- Checks if user has existing Stripe customer ID
- Creates new customer only if needed
- Updates user record with customer ID
- Syncs to both Prisma and Supabase

### 3. Setup Fee Logic

- **New Customers**: Setup fee is added to checkout
- **Existing Customers**: No setup fee (already paid)
- Uses pre-created Stripe price IDs for setup fees

### 4. 14-Day Free Trial

- All subscriptions include 14-day free trial
- Set via `trial_period_days: 14` in subscription data

### 5. Localization Support

- Success/cancel URLs include language parameter
- Error messages in English and Arabic
- Language defaults to 'en' if not provided

## Implementation Flow

1. **Rate Limiting**: Check if user has exceeded request limits
2. **Authentication**: Verify user is logged in
3. **Input Validation**: Validate tierId, billingPeriod, currency, language
4. **Price Fetching**: Get Stripe price ID from database/config
5. **Customer Management**: Get or create Stripe customer
6. **Setup Fee Calculation**: Add setup fee only for new customers
7. **Session Creation**: Create Stripe checkout session
8. **Response**: Return session URL and ID

## Stripe Checkout Session Configuration

```typescript
{
  mode: 'subscription',
  customer: customerId,
  line_items: [
    { price: stripePriceId, quantity: 1 },
    // Setup fee only for new customers:
    { price: setupFeePriceId, quantity: 1 }
  ],
  metadata: {
    user_id: user.id,
    tier_id: tierId,
    billing_period: billingPeriod,
    language: language,
    is_upgrade: 'true',
  },
  subscription_data: {
    trial_period_days: 14,
    metadata: { ... }
  },
  success_url: '/${language}/payment/success?session_id={CHECKOUT_SESSION_ID}',
  cancel_url: '/${language}/dashboard?payment=cancelled',
}
```

## URL Redirects

**Success**: `/${language}/payment/success?session_id={CHECKOUT_SESSION_ID}`

- User completes payment successfully
- Session ID included for verification

**Cancel**: `/${language}/dashboard?payment=cancelled`

- User cancels checkout
- Returns to dashboard with cancellation flag

## Differences from Signup Checkout

| Feature        | Signup Checkout   | Subscriptions Checkout        |
| -------------- | ----------------- | ----------------------------- |
| Authentication | Not required      | **Required**                  |
| User Info      | From request body | From authenticated user       |
| Setup Fee      | Always added      | Only for new Stripe customers |
| Success URL    | `/signup/success` | `/payment/success`            |
| Cancel URL     | `/signup`         | `/dashboard`                  |
| Use Case       | New signups       | Existing users upgrading      |

## Currency Support

**Currently Supported**: QAR only

Multi-currency support requires:

1. Database schema with currency-specific price IDs
2. Stripe products created for each currency/tier combination
3. Updated price validation logic

## Rate Limiting

- **Limit**: 10 requests per 15 minutes per IP
- **Limiter**: `rateLimiters.checkout`
- **Response**: 429 Too Many Requests

## Database Sync

Updates are saved to both databases:

- **Prisma** (PostgreSQL): Primary write
- **Supabase**: Synced for consistency

Fields synced:

- `stripeCustomerId`
- `updated_at`

## Security Features

1. **Authentication Required**: No anonymous checkouts
2. **Rate Limiting**: Prevents abuse
3. **Price Validation**: Server-side validation of tier/period/currency
4. **HTTPS Only**: Stripe checkout requires SSL
5. **Metadata Tracking**: All sessions tagged with user_id

## Testing

Run unit tests:

```bash
npm test __tests__/api/subscriptions/create-checkout.test.ts
```

Test coverage includes:

- Authentication validation
- Input validation
- Stripe customer creation
- Setup fee logic
- Checkout session creation
- Error handling
- Rate limiting

## Example Usage

```typescript
// Client-side code
const response = await fetch("/api/subscriptions/create-checkout", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    tierId: "tier2",
    billingPeriod: "yearly",
    currency: "QAR",
    language: "en",
  }),
});

const data = await response.json();

if (data.success) {
  // Redirect to Stripe checkout
  window.location.href = data.sessionUrl;
} else {
  // Handle error
  console.error(data.error);
}
```

## Environment Variables

Required:

- `STRIPE_SECRET_KEY`: Stripe API secret key
- `NEXT_PUBLIC_APP_URL`: Base URL for redirects (default: `http://localhost:9000`)
- `DATABASE_URL`: PostgreSQL connection string
- `NEXT_PUBLIC_SUPABASE_URL`: Supabase URL
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`: Supabase anonymous key
- `SUPABASE_SERVICE_ROLE_KEY`: Supabase service role key (for admin operations)

## Monitoring & Logging

All requests are logged with:

- Request ID (for tracking)
- User ID
- Tier/period/currency
- Authentication source
- Stripe customer creation
- Session creation
- Errors and failures

Log scope: `subscriptions:create-checkout:{requestId}`
