# 📚 **Complete Stripe Integration Documentation**

## 🏗️ **System Architecture Overview**

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Admin Panel   │    │   Frontend      │    │   Backend       │
│                 │    │   Website       │    │   (Node.js)     │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Plan CRUD     │    │   User Flow     │    │   Database      │
│   Operations    │    │   Registration  │    │   (MySQL)       │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Stripe API    │    │   Payment       │    │   Webhooks      │
│   (Products/    │    │   Processing    │    │   (Real-time    │
│    Prices)      │    │                 │    │    Updates)     │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

---

## 📋 **Database Schema & Relationships**

### **1. `subscription_plans` Table**
```sql
CREATE TABLE subscription_plans (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  description TEXT,
  price DECIMAL(10,2) NOT NULL,
  currency VARCHAR(3) DEFAULT 'USD',
  interval VARCHAR(10) NULL, -- 'monthly', 'yearly', 'lifetime'
  type VARCHAR(10) NOT NULL, -- 'recurring', 'one-off', 'both'
  status VARCHAR(20) DEFAULT 'active',
  stripeProductId VARCHAR(255) NOT NULL,
  stripeRecurringPriceId VARCHAR(255) NULL,
  stripeOneOffPriceId VARCHAR(255) NULL,
  createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  deletedAt TIMESTAMP NULL,
  createdBy INT NULL,
  updatedBy INT NULL,
  deletedBy INT NULL
);
```

### **2. `subscription_plan_features` Table**
```sql
CREATE TABLE subscription_plan_features (
  id INT PRIMARY KEY AUTO_INCREMENT,
  subscriptionPlanId INT NOT NULL,
  name VARCHAR(255) NOT NULL,
  createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  deletedAt TIMESTAMP NULL,
  FOREIGN KEY (subscriptionPlanId) REFERENCES subscription_plans(id)
);
```

### **3. `customers` Table**
```sql
CREATE TABLE customers (
  id INT PRIMARY KEY AUTO_INCREMENT,
  firstName VARCHAR(255) NOT NULL,
  lastName VARCHAR(255) NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE,
  password VARCHAR(255) NULL,
  phoneNumber VARCHAR(20) NULL,
  status VARCHAR(50) DEFAULT 'pending',
  stripeCustomerId VARCHAR(255) NULL,
  stripeSubscriptionId VARCHAR(255) NULL,
  stripePaymentIntentId VARCHAR(255) NULL,
  subscriptionStatus VARCHAR(50) DEFAULT 'inactive',
  planId INT NULL,
  createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  deletedAt TIMESTAMP NULL,
  FOREIGN KEY (planId) REFERENCES subscription_plans(id)
);
```

### **4. `subscriptions` Table**
```sql
CREATE TABLE subscriptions (
  id INT PRIMARY KEY AUTO_INCREMENT,
  customerId INT NOT NULL,
  stripeCustomerId VARCHAR(255) NOT NULL,
  stripeSubscriptionId VARCHAR(255) NOT NULL UNIQUE,
  stripePriceId VARCHAR(255) NOT NULL,
  stripeProductId VARCHAR(255) NOT NULL,
  status VARCHAR(50) NOT NULL DEFAULT 'active',
  currentPeriodStart TIMESTAMP NOT NULL,
  currentPeriodEnd TIMESTAMP NOT NULL,
  cancelAtPeriodEnd BOOLEAN DEFAULT false,
  canceledAt TIMESTAMP NULL,
  trialStart TIMESTAMP NULL,
  trialEnd TIMESTAMP NULL,
  quantity INT DEFAULT 1,
  metadata JSON NULL,
  createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  deletedAt TIMESTAMP NULL,
  createdBy INT NULL,
  updatedBy INT NULL,
  deletedBy INT NULL,
  FOREIGN KEY (customerId) REFERENCES customers(id) ON DELETE CASCADE
);
```

## 📋 **Database Migration Files**

### **1. Create Subscription Plans Table**
```typescript
// migrations/20250701000100_create-plan.ts
export async function up(knex: Knex): Promise<void> {
  return knex.schema.createTable('subscription_plans', (table) => {
    table.increments('id').primary();
    table.string('name').notNullable();
    table.text('description');
    table.decimal('price', 10, 2).notNullable();
    table.string('currency', 3).defaultTo('USD');
    table.string('interval', 10); // 'monthly', 'yearly', 'lifetime'
    table.string('type', 10).notNullable(); // 'recurring', 'one-off', 'both'
    table.string('status', 20).defaultTo('active');
    table.string('stripeProductId').notNullable();
    table.string('stripeRecurringPriceId');
    table.string('stripeOneOffPriceId');
    table.timestamps(true, true);
    table.timestamp('deletedAt').nullable();
    table.integer('createdBy').nullable();
    table.integer('updatedBy').nullable();
    table.integer('deletedBy').nullable();
  });
}
```

### **2. Create Subscription Plan Features Table**
```typescript
// migrations/20250701000200_create-subscription-plan-features.ts
export async function up(knex: Knex): Promise<void> {
  return knex.schema.createTable('subscription_plan_features', (table) => {
    table.increments('id').primary();
    table.integer('subscriptionPlanId').notNullable();
    table.string('name').notNullable();
    table.timestamps(true, true);
    table.timestamp('deletedAt').nullable();
    
    // Foreign key
    table.foreign('subscriptionPlanId')
      .references('id')
      .inTable('subscription_plans')
      .onDelete('CASCADE');
  });
}
```

### **3. Create Customers Table**
```typescript
// migrations/20250701000300_create-customer.ts
export async function up(knex: Knex): Promise<void> {
  return knex.schema.createTable('customers', (table) => {
    table.increments('id').primary();
    table.string('firstName').notNullable();
    table.string('lastName').notNullable();
    table.string('email').notNullable().unique();
    table.string('password');
    table.string('phoneNumber', 20);
    table.string('status', 50).defaultTo('pending');
    table.string('stripeCustomerId');
    table.string('stripeSubscriptionId');
    table.string('stripePaymentIntentId');
    table.string('subscriptionStatus', 50).defaultTo('inactive');
    table.integer('planId').nullable();
    table.timestamps(true, true);
    table.timestamp('deletedAt').nullable();
    
    // Foreign key
    table.foreign('planId')
      .references('id')
      .inTable('subscription_plans');
  });
}
```

### **4. Create Subscriptions Table**
```typescript
// migrations/20250701000400_create-subscription.ts
export async function up(knex: Knex): Promise<void> {
  return knex.schema.createTable('subscriptions', (table) => {
    table.increments('id').primary();
    table.integer('customerId').notNullable();
    table.string('stripeCustomerId').notNullable();
    table.string('stripeSubscriptionId').notNullable().unique();
    table.string('stripePriceId').notNullable();
    table.string('stripeProductId').notNullable();
    table.string('status', 50).notNullable().defaultTo('active');
    table.timestamp('currentPeriodStart').notNullable();
    table.timestamp('currentPeriodEnd').notNullable();
    table.boolean('cancelAtPeriodEnd').defaultTo(false);
    table.timestamp('canceledAt').nullable();
    table.timestamp('trialStart').nullable();
    table.timestamp('trialEnd').nullable();
    table.integer('quantity').defaultTo(1);
    table.json('metadata');
    table.timestamps(true, true);
    table.timestamp('deletedAt').nullable();
    table.integer('createdBy').nullable();
    table.integer('updatedBy').nullable();
    table.integer('deletedBy').nullable();
    
    // Foreign key
    table.foreign('customerId')
      .references('id')
      .inTable('customers')
      .onDelete('CASCADE');
  });
}
```

---

## 🔄 **Complete Flow Documentation**

### **PHASE 1: ADMIN PLAN MANAGEMENT**

#### **1.1 Plan Creation Flow**
```
Admin Panel → Backend → Stripe → Database
```

**Step-by-Step Process:**

1. **Admin Input** (`POST /admin/plans`)
   ```json
   {
     "name": "Premium Plan",
     "description": "Best plan for businesses",
     "price": 99.99,
     "currency": "USD",
     "interval": "monthly",
     "status": "Active",
     "planType": "recurring", // Frontend sends planType
     "features": [
       "Unlimited access",
       "Priority support",
       "Advanced analytics"
     ]
   }
   ```

2. **Validation** (`plan.schema.ts`)
   - ✅ Required fields validation
   - ✅ Price must be positive
   - ✅ Currency validation
   - ✅ Interval validation ('monthly', 'yearly', 'lifetime')
   - ✅ Plan type validation ('recurring', 'one-off', 'both')
   - ✅ Features array validation

3. **Business Logic** (`plan.service.ts`)
   ```typescript
   // Database transaction starts
   await db.transaction(async (trx) => {
     const planType = data.planType; // Frontend sends planType
     const shouldCreateRecurring = planType === 'recurring' || planType === 'both';
     const shouldCreateOneOff = planType === 'one-off' || planType === 'both';

     // 1. Create Stripe Product
     const product = await createStripeProduct({
       name: data.name,
       description: data.description,
       active: data.status.toLowerCase() === 'active',
       metadata: { createdBy: createdBy ? String(createdBy) : null },
     });

     // 2. Create Recurring Plan (if needed)
     if (shouldCreateRecurring) {
       const recurringPrice = await createStripePrice({
         product: product.id,
         unit_amount: Math.round(Number(data.price) * 100),
         currency: data.currency,
         recurring: { interval: mapToStripeInterval(data.interval || 'monthly') },
         active: data.status.toLowerCase() === 'active',
       });

       const [planId] = await trx('subscription_plans').insert({
         name: data.name,
         description: data.description,
         price: data.price,
         currency: data.currency,
         interval: data.interval || 'monthly',
         type: 'recurring', // Database stores as 'type'
         stripeProductId: product.id,
         stripeRecurringPriceId: recurringPrice.id,
         stripeOneOffPriceId: null,
         status: data.status,
         createdBy: createdBy ?? null,
       });

       // Sync features
       if (data.features?.length > 0) {
         await syncPlanFeatures(trx, planId, data.features);
       }
     }

     // 3. Create One-off Plan (if needed)
     if (shouldCreateOneOff) {
       const oneOffPrice = await createStripePrice({
         product: product.id,
         unit_amount: Math.round(Number(data.price) * 100),
         currency: data.currency,
         active: data.status.toLowerCase() === 'active',
       });

       const [planId] = await trx('subscription_plans').insert({
         name: data.name,
         description: data.description,
         price: data.price,
         currency: data.currency,
         interval: data.interval || 'monthly',
         type: 'one-off', // Database stores as 'type'
         stripeProductId: product.id,
         stripeRecurringPriceId: null,
         stripeOneOffPriceId: oneOffPrice.id,
         status: data.status,
         createdBy: createdBy ?? null,
       });

       // Sync features
       if (data.features?.length > 0) {
         await syncPlanFeatures(trx, planId, data.features);
       }
     }
   });
   // Transaction commits or rolls back
   ```

4. **Response**
   ```json
   {
     "success": true,
     "message": "Plan(s) created successfully",
     "data": [
       {
         "id": 1,
         "name": "Premium Plan",
         "type": "recurring",
         "stripeProductId": "prod_1234567890",
         "stripeRecurringPriceId": "price_1234567890",
         "features": [
           { "id": 1, "name": "Unlimited access" },
           { "id": 2, "name": "Priority support" },
           { "id": 3, "name": "Advanced analytics" }
         ]
       }
     ]
   }
   ```

#### **1.2 Plan Update Flow**
```
Admin Panel → Backend → Stripe → Database
```

**Important Restrictions:**
- **Plan type cannot be changed after creation**
- Only price, currency, interval, status, name, description, and features can be updated

**Process:**
```typescript
// 1. Data mapping (frontend sends planType, backend expects type)
// Note: In update, planType is ignored since type cannot be changed
data.type = data.planType; // This line exists but planType is ignored
delete data.planType;

// 2. Product updates (name, description, status)
const productUpdates: any = {};
if (data.name && data.name !== currentPlan.name) productUpdates.name = data.name;
if (data.description && data.description !== currentPlan.description) productUpdates.description = data.description;
if (data.status !== currentPlan.status) {
  productUpdates.active = data.status === 'Active';
}
if (Object.keys(productUpdates).length > 0) {
  await updateStripeProduct(currentPlan.stripeProductId, productUpdates);
}

// 3. Price updates (creates new Stripe prices, deactivates old ones)
if (currentPlan.type === 'recurring' && currentPlan.stripeRecurringPriceId) {
  const { newPriceId } = await updateStripePriceIfNeeded(
    currentPlan.stripeRecurringPriceId, currentPlan, data, 'recurring'
  );
  if (newPriceId !== currentPlan.stripeRecurringPriceId) {
    data.stripeRecurringPriceId = newPriceId;
  }
}

// 4. Database update (type field is ignored/not updated)
const updateData = { ...data, updatedBy: updatedBy ?? null, updatedAt: trx.fn.now() };
delete updateData.features;
delete updateData.type; // Ensure type is not updated
await trx('subscription_plans').where({ id }).update(updateData);

// 5. Features sync
if (data.features) {
  await syncPlanFeatures(trx, id, data.features);
}
```

#### **1.3 Plan Deletion Flow**
```
Admin Panel → Backend → Stripe → Database
```

**Process:**
1. **Soft Delete**: Mark as deleted in DB (`deletedAt` timestamp)
2. **Deactivate Stripe Resources**: 
   - Deactivate Stripe product if no other plans use it
   - Deactivate Stripe prices
3. **Preserve**: Existing subscriptions remain unaffected

---

### **PHASE 2: FRONTEND USER FLOW**

#### **2.1 Plan Display**
```
Frontend → Backend → Database
```

**API Call:**
```javascript
// Frontend
const response = await fetch('/web/plans');
const plans = await response.json();
```

**Backend Response:**
```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "Premium Plan",
      "description": "Best plan for businesses",
      "price": 99.99,
      "currency": "USD",
      "interval": "monthly",
      "type": "recurring",
      "status": "active",
      "stripeProductId": "prod_1234567890",
      "stripeRecurringPriceId": "price_1234567890",
      "stripeOneOffPriceId": null,
      "features": [
        { "id": 1, "name": "Unlimited access" },
        { "id": 2, "name": "Priority support" },
        { "id": 3, "name": "Advanced analytics" }
      ]
    }
  ]
}
```

**Frontend Display:**
```html
<!-- Each plan shown once with payment options -->
<div class="plan-card">
  <h3>Premium Plan</h3>
  <p>$99.99/month</p>
  <ul>
    <li>Unlimited access</li>
    <li>Priority support</li>
    <li>Advanced analytics</li>
  </ul>
  <div class="payment-options">
    <button onclick="register('recurring')">Subscribe Monthly</button>
    <button onclick="register('one-off')">Pay Once</button>
  </div>
</div>
```

#### **2.2 Customer Registration with Plan**
```
Frontend → Backend → Database → Stripe
```

**Frontend Call:**
```javascript
const registrationData = {
  firstName: "John",
  lastName: "Doe",
  email: "john@example.com",
  password: "password123",
  planId: 1,
  isRecurring: true
};

const response = await fetch('/admin/customers/register-with-plan', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(registrationData)
});
```

**Backend Process:**
```typescript
// 1. Validation
const { firstName, lastName, email, password, planId, isRecurring } = req.body;

// 2. Plan validation
const plan = await getPlanById(planId);
if (!plan || plan.status !== 'active') {
  return next(new ErrorResponse(404, 'Plan not found or inactive'));
}

// 3. Customer uniqueness check
const existingCustomer = await db('customers').where({ email }).whereNull('deletedAt').first();
if (existingCustomer) {
  return next(new ErrorResponse(409, 'Email already exists'));
}

// 4. Payment type validation
const priceId = isRecurring ? plan.stripeRecurringPriceId : plan.stripeOneOffPriceId;
if (!priceId) {
  return next(new ErrorResponse(400, 'Payment type not available for this plan'));
}

// 5. Create customer in DB
const customer = await createCustomer({
  firstName, lastName, email, password, planId, status: 'pending'
});

// 6. Create Stripe customer
const stripeCustomer = await createStripeCustomer({
  email,
  name: `${firstName} ${lastName}`,
  metadata: { customerId: customer.id.toString() }
});

// 7. Update customer with Stripe ID
await updateCustomer(customer.id, { stripeCustomerId: stripeCustomer.id });
```

**Response:**
```json
{
  "success": true,
  "message": "Registration successful. Proceed to payment.",
  "data": {
    "customerId": 1,
    "stripeCustomerId": "cus_1234567890",
    "planId": 1,
    "priceId": "price_1234567890",
    "isRecurring": true,
    "email": "john@example.com"
  }
}
```

#### **2.3 Payment Processing**
```
Frontend → Backend → Stripe → Database
```

**Frontend Payment Collection:**
```javascript
// 1. Collect payment method with Stripe Elements
const { paymentMethod } = await stripe.createPaymentMethod({
  type: 'card',
  card: cardElement,
});

// 2. Submit payment
const paymentData = {
  customerId: 1,
  planId: 1,
  priceId: "price_1234567890",
  isRecurring: true,
  paymentMethodId: paymentMethod.id
};

const response = await fetch('/admin/customers/subscribe-or-pay', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(paymentData)
});
```

**Backend Payment Process:**
```typescript
// 1. Validation
const { customerId, planId, priceId, isRecurring, paymentMethodId } = req.body;

// 2. Plan and customer validation
const plan = await getPlanById(planId);
const customer = await db('customers').where({ id: customerId }).whereNull('deletedAt').first();

// 3. Price ID validation
const expectedPriceId = isRecurring ? plan.stripeRecurringPriceId : plan.stripeOneOffPriceId;
if (priceId !== expectedPriceId) {
  return next(new ErrorResponse(400, 'Price ID does not match the selected plan and payment type'));
}

// 4. Attach payment method
await attachStripePaymentMethod(paymentMethodId, { 
  customer: customer.stripeCustomerId 
});

// 5. Process payment based on type
if (isRecurring) {
  // Create subscription
  const subscription = await createStripeSubscription({
    customer: customer.stripeCustomerId,
    items: [{ price: priceId }],
    expand: ['latest_invoice.payment_intent']
  });
  
  // Store subscription in DB
  await db('subscriptions').insert({
    customerId,
    stripeCustomerId: customer.stripeCustomerId,
    stripeSubscriptionId: subscription.id,
    stripePriceId: priceId,
    stripeProductId: plan.stripeProductId,
    status: subscription.status,
    currentPeriodStart: new Date(subscription.current_period_start * 1000),
    currentPeriodEnd: new Date(subscription.current_period_end * 1000),
    // ... other fields
  });
} else {
  // Create payment intent
  const paymentIntent = await createStripePaymentIntent({
    customer: customer.stripeCustomerId,
    amount: Math.round(plan.price * 100),
    currency: plan.currency,
    payment_method: paymentMethodId,
    confirm: true,
    metadata: { customerId: customerId.toString(), planId: planId.toString() }
  });
}

// 6. Update customer status
await updateCustomer(customerId, {
  subscriptionStatus: isRecurring ? subscription.status : paymentIntent.status,
  stripeSubscriptionId: isRecurring ? subscription.id : null,
  stripePaymentIntentId: !isRecurring ? paymentIntent.id : null,
  planId
});
```

**Response:**
```json
{
  "success": true,
  "message": "Payment/subscription successful",
  "data": {
    "customerId": 1,
    "planId": 1,
    "stripeSubscriptionId": "sub_1234567890",
    "stripePaymentIntentId": null,
    "status": "active"
  }
}
```

---

### **PHASE 3: STRIPE WEBHOOK PROCESSING**

#### **3.1 Webhook Event Handling**
```
Stripe → Backend → Database
```

**Webhook Endpoint:** `POST /web/stripe/webhook`

**Event Types Handled:**
```typescript
switch (event.type) {
  case 'customer.subscription.created':
    await handleSubscriptionCreated(event.data.object);
    break;
  case 'customer.subscription.updated':
    await handleSubscriptionUpdated(event.data.object);
    break;
  case 'customer.subscription.deleted':
    await handleSubscriptionDeleted(event.data.object);
    break;
  case 'invoice.payment_succeeded':
    await handleInvoicePaymentSucceeded(event.data.object);
    break;
  case 'invoice.payment_failed':
    await handleInvoicePaymentFailed(event.data.object);
    break;
}
```

**Subscription Update Process:**
```typescript
async function handleSubscriptionUpdated(subscription: Stripe.Subscription) {
  // 1. Find subscription in DB
  const existingSubscription = await getSubscriptionByStripeId(subscription.id);
  
  if (existingSubscription) {
    // 2. Update subscription status
    await db('subscriptions')
      .where({ stripeSubscriptionId: subscription.id })
      .update({
        status: subscription.status,
        currentPeriodStart: new Date(subscription.current_period_start * 1000),
        currentPeriodEnd: new Date(subscription.current_period_end * 1000),
        cancelAtPeriodEnd: subscription.cancel_at_period_end,
        canceledAt: subscription.canceled_at ? new Date(subscription.canceled_at * 1000) : null,
        updatedAt: db.fn.now()
      });
  }
}
```

---

## 🔧 **API Endpoints Reference**

### **Admin Endpoints**
| Method | Endpoint | Description | Validation |
|--------|----------|-------------|------------|
| `POST` | `/admin/plans` | Create plan | `createPlanSchema` |
| `PUT` | `/admin/plans/:id` | Update plan | `updatePlanSchema` |
| `DELETE` | `/admin/plans/:id` | Delete plan | None |
| `DELETE` | `/admin/plans/delete-by-name` | Delete plans by name and type | None |
| `GET` | `/admin/plans` | List all plans with pagination | None |
| `GET` | `/admin/plans/:id` | Get plan details | None |
| `POST` | `/admin/customers/register-with-plan` | Register customer | `registerCustomerWithPlanSchema` |
| `POST` | `/admin/customers/subscribe-or-pay` | Process payment | `customerSubscribeOrPaySchema` |

### **Public Endpoints**
| Method | Endpoint | Description | Validation |
|--------|----------|-------------|------------|
| `GET` | `/web/plans` | Get active plans | None |

### **Payment Endpoints**
| Method | Endpoint | Description | Validation |
|--------|----------|-------------|------------|
| `POST` | `/payment/create-payment-intent` | Create payment intent | None |
| `POST` | `/payment/create-setup-intent` | Create setup intent | None |
| `POST` | `/payment/create-or-get-customer` | Customer management | None |

### **Webhook Endpoints**
| Method | Endpoint | Description | Validation |
|--------|----------|-------------|------------|
| `POST` | `/web/stripe/webhook` | Stripe webhooks | Signature verification |

---

## 🛡️ **Security & Validation**

### **Authentication & Authorization**
```typescript
// All admin endpoints protected with:
adminRouter.use('/plans', verifyAccessToken, verifyUserRole, planRouter);
adminRouter.use('/customers', verifyAccessToken, verifyUserRole, customerRouter);
```

### **Input Validation**
```typescript
// Plan creation validation
export const createPlanSchema = Joi.object({
  name: Joi.string().required(),
  description: Joi.string().required(),
  price: Joi.number().positive().required(),
  currency: Joi.string().default('USD').required(),
  interval: Joi.string().valid('monthly', 'yearly', 'lifetime').optional(),
  status: Joi.string().valid('Active', 'Inactive').default('Active'),
  planType: Joi.string().valid('recurring', 'one-off', 'both').required(),
  features: Joi.array().items(Joi.string()).min(1).required(),
});

// Plan update validation
export const updatePlanSchema = Joi.object({
  name: Joi.string().optional(),
  description: Joi.string().optional(),
  price: Joi.number().positive().optional(),
  currency: Joi.string().optional(),
  interval: Joi.string().valid('monthly', 'yearly', 'lifetime').optional(),
  status: Joi.string().valid('Active', 'Inactive').optional(),
  features: Joi.array().items(Joi.string()).min(1).optional(),
  // Note: planType cannot be changed after creation
});

// Customer registration validation
export const registerCustomerWithPlanSchema = Joi.object({
  firstName: Joi.string().trim().required(),
  lastName: Joi.string().trim().required(),
  email: Joi.string().email().required(),
  password: Joi.string().min(6).required(),
  planId: Joi.number().integer().positive().required(),
  isRecurring: Joi.boolean().required(),
});
```

### **Error Handling**
```typescript
// Comprehensive error responses
{
  "success": false,
  "message": "Plan not found",
  "statusCode": 404,
  "error": "NOT_FOUND"
}
```

---

## 📊 **Data Flow Diagrams**

### **Plan Creation Flow**
```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Admin     │───▶│  Backend    │───▶│   Stripe    │───▶│  Database   │
│   Input     │    │ Validation  │    │   API       │    │   Insert    │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
```

### **Plan Update Flow**
```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Admin     │───▶│  Backend    │───▶│   Stripe    │───▶│  Database   │
│   Update    │    │ Validation  │    │ New Prices  │    │   Update    │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
```

### **Customer Registration Flow**
```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  Frontend   │───▶│  Backend    │───▶│  Database   │───▶│   Stripe    │
│ Registration│    │ Validation  │    │ Customer    │    │ Customer    │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
```

### **Payment Processing Flow**
```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  Frontend   │───▶│  Backend    │───▶│   Stripe    │───▶│  Database   │
│   Payment   │    │ Validation  │    │ Processing  │    │   Update    │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
```

### **Webhook Processing Flow**
```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Stripe    │───▶│  Backend    │───▶│  Database   │
│  Webhook    │    │ Validation  │    │   Update    │
└─────────────┘    └─────────────┘    └─────────────┘
```

---

## 📊 **State Management**

### **Plan States**
- `active`: Plan is available for purchase
- `inactive`: Plan is not available (soft deleted)

### **Plan Types**
- `recurring`: Monthly/yearly subscription plans
- `one-off`: One-time payment plans
- `both`: Plans that support both recurring and one-off payments

### **Customer States**
- `pending`: Customer registered but not paid
- `active`: Customer has active subscription
- `inactive`: Customer has no active subscription
- `past_due`: Payment failed, subscription past due
- `canceled`: Subscription canceled

### **Subscription States**
- `active`: Subscription is active and billing
- `trialing`: Subscription in trial period
- `past_due`: Payment failed
- `canceled`: Subscription canceled
- `unpaid`: Payment failed, subscription unpaid

---

## 📝 **Configuration Requirements**

### **Environment Variables**
```env
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Database Configuration
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=password
DB_NAME=your_database

# JWT Configuration
JWT_SECRET=your_jwt_secret
```

### **Stripe Webhook Events**
Configure these events in Stripe Dashboard:
- `customer.subscription.created`
- `customer.subscription.updated`
- `customer.subscription.deleted`
- `invoice.payment_succeeded`
- `invoice.payment_failed`

---

## 🚀 **Deployment Checklist**

### **Pre-deployment**
- [ ] Run database migrations
- [ ] Configure environment variables
- [ ] Set up Stripe webhook endpoints
- [ ] Test all API endpoints
- [ ] Verify error handling
- [ ] Test plan type restrictions
- [ ] Verify price update logic

### **Post-deployment**
- [ ] Monitor webhook delivery
- [ ] Check database connections
- [ ] Verify Stripe API connectivity
- [ ] Test payment flows
- [ ] Monitor error logs
- [ ] Test plan creation and updates

---

## 📞 **Support & Troubleshooting**

### **Common Issues**
1. **Webhook failures**: Check signature verification
2. **Payment failures**: Verify payment method format
3. **Database errors**: Check transaction rollbacks
4. **Stripe API errors**: Verify API key and permissions
5. **Plan type change errors**: Plan type cannot be changed after creation
6. **Price update issues**: New Stripe prices are created, old ones deactivated

### **Debugging**
- Check application logs for detailed error messages
- Verify Stripe Dashboard for webhook delivery status
- Monitor database transaction logs
- Test with Stripe test mode first
- Verify plan type restrictions in update operations

---

## 🔄 **Complete Integration Summary**

### **Key Features Implemented**
- ✅ **Admin Plan Management**: Full CRUD with automatic Stripe sync
- ✅ **Plan Features Management**: Dynamic feature addition/removal
- ✅ **Plan Type Support**: Recurring, one-off, and both types
- ✅ **Plan Type Restrictions**: Cannot change type after creation
- ✅ **Automatic Stripe Integration**: Products and prices created automatically
- ✅ **Price Update Logic**: New prices created, old ones deactivated
- ✅ **Customer Registration**: With plan selection
- ✅ **Payment Processing**: Both recurring and one-off
- ✅ **Webhook Handling**: Real-time subscription updates
- ✅ **Centralized Stripe Service**: All Stripe logic in one place
- ✅ **Comprehensive Validation**: Input and business logic validation
- ✅ **Error Handling**: Proper error responses and rollbacks
- ✅ **Security**: Authentication, authorization, and input validation

### **Architecture Benefits**
- **Scalable**: Clean separation of concerns
- **Maintainable**: Centralized Stripe logic
- **Secure**: Multiple layers of protection
- **Reliable**: Transaction safety and error handling
- **Flexible**: Supports both recurring and one-off payments
- **Restrictive**: Prevents plan type changes after creation
- **Automated**: Automatic Stripe resource creation

---

**This documentation covers the complete Stripe integration flow from admin plan management to frontend payment processing, including all validations, security measures, error handling, and the latest plan service features.** 🎉 