# Frontend Integration Guide

This guide explains how to integrate the subscription system with your frontend application.

## 🔄 **Payment Flow Options**

### **Option 1: Frontend Collects Payment (Recommended)**
Frontend collects credit card details using Stripe Elements, then backend creates subscription.

### **Option 2: Backend Handles Everything**
Frontend sends payment method ID, backend creates subscription directly.

## 📦 **Required Frontend Dependencies**

```bash
npm install @stripe/stripe-js @stripe/react-stripe-js
```

## 🚀 **Frontend Implementation**

### **1. Initialize Stripe**

```javascript
import { loadStripe } from '@stripe/stripe-js';

const stripePromise = loadStripe('pk_test_your_publishable_key_here');
```

### **2. Create Customer (First Time)**

```javascript
const createCustomer = async (userData) => {
  const response = await fetch('/admin/payments/customer', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({
      email: userData.email,
      name: `${userData.firstName} ${userData.lastName}`,
      metadata: {
        userId: userData.id
      }
    })
  });
  
  const result = await response.json();
  return result.data.customerId;
};
```

### **3. Get Available Products and Prices**

```javascript
const getProducts = async () => {
  const response = await fetch('/admin/payments/products', {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  
  const result = await response.json();
  return result.data.products;
};

const getPrices = async (productId) => {
  const response = await fetch(`/admin/payments/products/${productId}/prices`, {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  
  const result = await response.json();
  return result.data.prices;
};
```

### **4. Create Setup Intent (for saving payment method)**

```javascript
const createSetupIntent = async (customerId) => {
  const response = await fetch('/admin/payments/setup-intent', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({
      customerId: customerId
    })
  });
  
  const result = await response.json();
  return result.data.clientSecret;
};
```

### **5. React Component Example**

```jsx
import React, { useState, useEffect } from 'react';
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';

const SubscriptionForm = () => {
  const stripe = useStripe();
  const elements = useElements();
  const [customerId, setCustomerId] = useState(null);
  const [products, setProducts] = useState([]);
  const [selectedProduct, setSelectedProduct] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    // Get products on component mount
    fetchProducts();
    // Create or get customer
    createOrGetCustomer();
  }, []);

  const fetchProducts = async () => {
    try {
      const productsData = await getProducts();
      setProducts(productsData);
    } catch (error) {
      console.error('Error fetching products:', error);
    }
  };

  const createOrGetCustomer = async () => {
    try {
      const customerId = await createCustomer({
        email: 'user@example.com',
        firstName: 'John',
        lastName: 'Doe',
        id: 1
      });
      setCustomerId(customerId);
    } catch (error) {
      console.error('Error creating customer:', error);
    }
  };

  const handleSubmit = async (event) => {
    event.preventDefault();
    setLoading(true);

    if (!stripe || !elements || !customerId || !selectedProduct) {
      setLoading(false);
      return;
    }

    try {
      // Create setup intent
      const setupIntentClientSecret = await createSetupIntent(customerId);

      // Confirm setup intent
      const { setupIntent, error } = await stripe.confirmCardSetup(
        setupIntentClientSecret,
        {
          payment_method: {
            card: elements.getElement(CardElement),
            billing_details: {
              name: 'John Doe',
              email: 'user@example.com',
            },
          },
        }
      );

      if (error) {
        console.error('Setup failed:', error);
        setLoading(false);
        return;
      }

      // Create subscription with payment method
      const subscriptionResponse = await fetch('/admin/payments/subscription', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({
          userId: 1,
          stripePriceId: selectedProduct.priceId,
          stripeProductId: selectedProduct.productId,
          paymentMethodId: setupIntent.payment_method,
          customerId: customerId,
          quantity: 1,
          trialDays: 7
        })
      });

      const subscriptionResult = await subscriptionResponse.json();
      
      if (subscriptionResult.success) {
        alert('Subscription created successfully!');
        // Redirect or update UI
      } else {
        alert('Failed to create subscription');
      }

    } catch (error) {
      console.error('Error creating subscription:', error);
      alert('An error occurred');
    }

    setLoading(false);
  };

  return (
    <div>
      <h2>Choose Your Plan</h2>
      
      {/* Product Selection */}
      <div>
        {products.map(product => (
          <div key={product.id}>
            <h3>{product.name}</h3>
            <p>{product.description}</p>
            <button onClick={() => setSelectedProduct(product)}>
              Select {product.name}
            </button>
          </div>
        ))}
      </div>

      {/* Payment Form */}
      {selectedProduct && (
        <form onSubmit={handleSubmit}>
          <h3>Payment Information</h3>
          <CardElement
            options={{
              style: {
                base: {
                  fontSize: '16px',
                  color: '#424770',
                  '::placeholder': {
                    color: '#aab7c4',
                  },
                },
                invalid: {
                  color: '#9e2146',
                },
              },
            }}
          />
          <button type="submit" disabled={loading}>
            {loading ? 'Processing...' : 'Subscribe'}
          </button>
        </form>
      )}
    </div>
  );
};

// Wrap with Stripe provider
const App = () => {
  return (
    <Elements stripe={stripePromise}>
      <SubscriptionForm />
    </Elements>
  );
};
```

## 📱 **Mobile/React Native Integration**

### **Using Stripe React Native SDK**

```bash
npm install @stripe/stripe-react-native
```

```javascript
import { StripeProvider, CardField, useStripe } from '@stripe/stripe-react-native';

const SubscriptionScreen = () => {
  const { createToken, confirmPayment } = useStripe();

  const handleSubscribe = async () => {
    try {
      // Create payment method
      const { paymentMethod, error } = await createPaymentMethod({
        type: 'Card',
        billingDetails: {
          email: 'user@example.com',
          name: 'John Doe',
        },
      });

      if (error) {
        console.error('Payment method creation failed:', error);
        return;
      }

      // Create subscription
      const response = await fetch('/admin/payments/subscription', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({
          userId: 1,
          stripePriceId: 'price_1234567890',
          stripeProductId: 'prod_1234567890',
          paymentMethodId: paymentMethod.id,
          customerId: 'cus_1234567890',
          quantity: 1,
          trialDays: 7
        })
      });

      const result = await response.json();
      console.log('Subscription result:', result);

    } catch (error) {
      console.error('Error:', error);
    }
  };

  return (
    <StripeProvider publishableKey="pk_test_your_key_here">
      <CardField
        postalCodeEnabled={true}
        placeholder={{
          number: "4242 4242 4242 4242",
        }}
        cardStyle={{
          backgroundColor: "#FFFFFF",
          textColor: "#000000",
        }}
        style={{
          width: "100%",
          height: 50,
          marginVertical: 30,
        }}
      />
      <button onPress={handleSubscribe}>Subscribe</button>
    </StripeProvider>
  );
};
```

## 🌐 **Vanilla JavaScript Integration**

```javascript
// Load Stripe
const stripe = Stripe('pk_test_your_publishable_key_here');

// Create subscription
const createSubscription = async (paymentMethodId, customerId) => {
  try {
    const response = await fetch('/admin/payments/subscription', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
      },
      body: JSON.stringify({
        userId: 1,
        stripePriceId: 'price_1234567890',
        stripeProductId: 'prod_1234567890',
        paymentMethodId: paymentMethodId,
        customerId: customerId,
        quantity: 1,
        trialDays: 7
      })
    });

    const result = await response.json();
    return result;
  } catch (error) {
    console.error('Error creating subscription:', error);
    throw error;
  }
};

// Handle form submission
document.getElementById('subscription-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  
  const { paymentMethod, error } = await stripe.createPaymentMethod({
    type: 'card',
    card: elements.getElement('card'),
    billing_details: {
      name: document.getElementById('name').value,
      email: document.getElementById('email').value,
    },
  });

  if (error) {
    console.error('Payment method creation failed:', error);
    return;
  }

  try {
    const result = await createSubscription(paymentMethod.id, customerId);
    if (result.success) {
      alert('Subscription created successfully!');
    }
  } catch (error) {
    alert('Failed to create subscription');
  }
});
```

## 🔐 **Security Best Practices**

1. **Never store credit card data** - Always use Stripe's secure elements
2. **Use HTTPS** - Always in production
3. **Validate on both frontend and backend** - Never trust frontend validation alone
4. **Use webhooks** - For reliable payment status updates
5. **Implement proper error handling** - Show user-friendly error messages

## 📊 **Testing**

### **Test Card Numbers**
- **Success**: `4242 4242 4242 4242`
- **Decline**: `4000 0000 0000 0002`
- **Requires Authentication**: `4000 0025 0000 3155`

### **Test CVC and Expiry**
- **CVC**: Any 3 digits
- **Expiry**: Any future date

## 🚨 **Error Handling**

```javascript
const handlePaymentError = (error) => {
  switch (error.code) {
    case 'card_declined':
      alert('Your card was declined. Please try another card.');
      break;
    case 'expired_card':
      alert('Your card has expired. Please update your payment method.');
      break;
    case 'incorrect_cvc':
      alert('The security code is incorrect. Please check and try again.');
      break;
    default:
      alert('An error occurred. Please try again.');
  }
};
```

## 📞 **Support**

For integration issues:
1. Check Stripe documentation
2. Verify API keys are correct
3. Test with Stripe's test mode first
4. Check browser console for errors
5. Verify webhook endpoints are accessible 