# Quick Start Guide - React

Get up and running with the InflowPay React SDK in 5 minutes.

## Overview

The InflowPay React SDK is designed for **simple card data collection** in React applications. Your backend creates payments with all billing information, and the SDK focuses solely on collecting card data and completing the payment.

## 1. Installation

```bash
npm install inflowpay-js react react-dom
```

## 2. Basic Integration

### Step 1: Create Payment on Backend

Create the payment with all billing information on your backend:

```javascript
// Backend (using private API key)
const payment = await fetch('https://api.inflowpay.xyz/api/server/payment', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'X-Inflow-Api-Key': 'inflow_priv_xxx'  // Private key (backend only!)
  },
  body: JSON.stringify({
    products: [{ name: 'Premium Plan', price: 4999, quantity: 1 }],
    currency: 'EUR',
    customerEmail: 'customer@example.com',
    billingCountry: 'FR',
    postalCode: '75001',
    firstName: 'Jean',
    lastName: 'Dupont',
    purchasingAsBusiness: false,
    successUrl: 'https://yourdomain.com/success',
    cancelUrl: 'https://yourdomain.com/cancel'
  })
});

const { payment: { id: paymentId } } = await payment.json();
// Pass paymentId to your React app
```

### Step 2: Wrap Your App with InflowPayProvider

```tsx
import { InflowPayProvider } from 'inflowpay-js/react';

function App() {
  return (
    <InflowPayProvider config={{ apiKey: 'inflow_pub_xxx' }}>
      <YourComponents />
    </InflowPayProvider>
  );
}
```

### Step 3: Add CardElement Component

```tsx
import { CardElement } from 'inflowpay-js/react';
import type { PaymentResult } from 'inflowpay-js';

function CheckoutPage() {
  const paymentId = 'pay_xxx'; // From your backend

  const handleComplete = (result: PaymentResult) => {
    if (result.status === 'CHECKOUT_SUCCESS') {
      window.location.href = '/success';
    }
  };

  return (
    <CardElement
      paymentId={paymentId}
      onComplete={handleComplete}
      onError={(error) => {
        alert(`Payment failed: ${error.message}`);
      }}
    />
  );
}
```

**That's it!** User enters card and clicks button.

### Step 4: Handle Loading States (Optional)

Show a loading state while the card element is mounting:

```tsx
import { useState } from 'react';
import { CardElement } from 'inflowpay-js/react';

function CheckoutPage() {
  const [isLoading, setIsLoading] = useState(true);
  const paymentId = 'pay_xxx';

  return (
    <div>
      {isLoading && <p>Loading payment form...</p>}
      <div style={{ opacity: isLoading ? 0 : 1 }}>
        <CardElement
          paymentId={paymentId}
          onReady={() => setIsLoading(false)}
          onComplete={(result) => {
            if (result.status === 'CHECKOUT_SUCCESS') {
              window.location.href = '/success';
            }
          }}
        />
      </div>
    </div>
  );
}
```

The `onReady` callback fires once when the card element is fully mounted and ready to use.

## 3. Payment Status Flow

```
INITIATION
    ↓
CHECKOUT_PENDING (user paying)
    ↓
CHECKOUT_SUCCESS (payment confirmed) ← Success starts here
    ↓
PAYMENT_RECEIVED (fiat received)
    ↓
PAYMENT_SUCCESS (crypto sent)
```

**Success:** Any status from `CHECKOUT_SUCCESS` onwards is considered successful.

**Failed:** `PAYMENT_FAILED`, `CHECKOUT_CANCELED`, `CANCELED`

## 4. Using Without Provider (Standalone)

You can also use `CardElement` without `InflowPayProvider` by passing config directly:

```tsx
import { CardElement } from 'inflowpay-js/react';

function CheckoutPage() {
  return (
    <CardElement
      config={{ apiKey: 'inflow_pub_xxx' }}
      paymentId="pay_xxx"
      onComplete={(result) => {
        if (result.status === 'CHECKOUT_SUCCESS') {
          window.location.href = '/success';
        }
      }}
    />
  );
}
```

## 5. Using the Hook

Access the InflowPay instance anywhere within the provider:

```tsx
import { useInflowPay } from 'inflowpay-js/react';

function PaymentStatus() {
  const inflow = useInflowPay();
  const [status, setStatus] = useState(null);

  const checkStatus = async () => {
    const result = await inflow.getPaymentStatus('pay_xxx');
    setStatus(result);
  };

  return (
    <div>
      <button onClick={checkStatus}>Check Status</button>
      {status && <p>Status: {status.status}</p>}
    </div>
  );
}
```

## 6. TypeScript Usage

Full TypeScript support is included:

```tsx
import { InflowPayProvider, CardElement } from 'inflowpay-js/react';
import type { PaymentResult, PaymentError, PaymentStatus } from 'inflowpay-js';

function App() {
  return (
    <InflowPayProvider config={{ apiKey: 'inflow_pub_xxx' }}>
      <CardElement
        paymentId="pay_xxx"
        onComplete={(result: PaymentResult) => {
          // TypeScript knows the exact type of result.status
          if (result.status === PaymentStatus.CHECKOUT_SUCCESS) {
            // Type-safe success handling
          }
        }}
        onError={(error: PaymentError) => {
          console.error(error.code, error.message);
        }}
      />
    </InflowPayProvider>
  );
}
```

## 7. Error Handling

The SDK automatically converts raw error codes to user-friendly messages:

```tsx
<CardElement
  paymentId={paymentId}
  onComplete={(result) => {
    if (result.status === 'CHECKOUT_SUCCESS' ||
        result.status === 'PAYMENT_RECEIVED' ||
        result.status === 'PAYMENT_SUCCESS') {
      window.location.href = '/success';
    }
    else if (result.error) {
      // SDK automatically provides user-friendly messages
      alert(result.error.message);

      // Check if user can retry
      if (result.error.retryable) {
        console.log('User can try with a different card');
      }
    }
  }}
  onError={(error) => {
    // SDK-level errors (network, validation, etc.)
    console.error('SDK error:', error.code, error.message);
    alert(error.message);
  }}
/>
```

**What the SDK handles automatically:**
- ✅ Converts error codes like `card_declined` to "Your card was declined. Please try another payment method..."
- ✅ Checks multiple error sources (`payment.error` and `payment.lastDepositAttempt.error`)
- ✅ Detects errors during payment status polling
- ✅ Provides `retryable` flag for all errors
- ✅ Handles Stripe-specific errors (`test_mode_live_card`, `insufficient_funds`, etc.)

**Error structure:**
```typescript
{
  code: 'card_declined',           // Raw error code
  message: 'Your card was...',     // User-friendly message
  retryable: true                  // Can user try again?
}
```

## 8. Customization

### Styling

```tsx
<CardElement
  paymentId={paymentId}
  style={{
    // Input container (the box wrapping all inputs)
    inputContainer: {
      backgroundColor: '#F5F5F5',
      border: '1px solid #E0E0E0',
      borderRadius: '8px',
    },
    // Individual input fields
    input: {
      border: '1px solid #CECECE',
      borderRadius: '5px',
      color: '#333333',
      fontWeight: '400',
      placeholder: {
        color: '#999999',
      },
    },
    // Global font family
    fontFamily: "'Inter', sans-serif",
    // Dark mode overrides (optional)
    // Automatically applies when system is in dark mode
    dark: {
      inputContainer: { backgroundColor: '#2d2d2d' },
      input: { color: '#FFFFFF' },
    },
  }}
  buttonText="Pay Now"
  buttonStyle={{
    base: {
      backgroundColor: '#007bff',
      color: '#ffffff',
      borderRadius: '6px',
      padding: '12px 24px',
    },
    hover: {
      backgroundColor: '#0056b3',
    },
    disabled: {
      backgroundColor: '#cccccc',
      cursor: 'not-allowed',
    },
    loaderColor: '#ffffff',
  }}
  placeholders={{
    cardNumber: '1234 5678 9012 3456',
    expiry: 'MM/YY',
    cvc: '123'
  }}
/>
```

### Using Ref

Access CardElement methods via ref:

```tsx
import { useRef } from 'react';
import { CardElement, type CardElementRef } from 'inflowpay-js/react';

function CheckoutPage() {
  const cardElementRef = useRef<CardElementRef>(null);

  const handleSubmit = async () => {
    if (cardElementRef.current) {
      try {
        const result = await cardElementRef.current.submit();
        console.log('Payment result:', result);
      } catch (error) {
        console.error('Submit error:', error);
      }
    }
  };

  return (
    <>
      <CardElement
        ref={cardElementRef}
        paymentId="pay_xxx"
      />
      <button onClick={handleSubmit}>Submit Payment</button>
    </>
  );
}
```

## 9. Next Steps

- **Full Documentation:** [README.md](./README.md)
- **API Reference:** [README.md#api-reference](./README.md#api-reference)

## Production Checklist

Before going live:

- [ ] Use your production API key (`inflow_pub_xxx`)
- [ ] Set `debug: false` in InflowPayProvider config
- [ ] Implement proper error logging
- [ ] Add loading states and UX feedback
- [ ] Test 3DS flow
- [ ] Test on all target browsers
- [ ] Review security best practices in [SECURITY.md](./SECURITY.md)

## Need Help?

- **Email:** support@inflowpay.com
- **Documentation:** https://docs.inflowpay.com/v0/reference/createpayment
- **Repository:** https://github.com/inflowpay/sdk

---

**That's it!** You're ready to accept payments with InflowPay. 🎉
