# Payment API Documentation

## Overview

The Payment API handles payment processing via Stripe for mobile customers. This endpoint completes the checkout flow by accepting a Stripe token and creating an order record.

**Base URL:** `https://missio.dev/api/catalog`

**Endpoint:** `POST /payment`

---

## Complete Checkout Flow

The full checkout process follows this sequence:

```
1. Create/Get Cart
   GET /api/catalog/cart
   Returns: cart_id, cart_token, items, totals

2. Add Items to Cart
   POST /api/catalog/cart/items
   Body: product_id, quantity, attributes

3. Save Checkout Data
   POST /api/catalog/checkout?cart_token=abc123
   Body: billing_*, shipping_*, form data

4. Process Payment
   POST /api/catalog/payment?cart_token=abc123
   Body: token (Stripe), payment_method
   Returns: order_id, transaction_id
```

---

## Payment Endpoint

### Request

**Method:** `POST`

**URL:** `/api/catalog/payment?cart_token={cart_token}`

**Required Headers:**

```
X-Company-Hash: {company_identifier}
Authorization: Bearer {token}              (optional, for authenticated users)
Content-Type: application/json
```

**Query Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `cart_token` | string | Yes | Cart token from previous cart operations |

**Request Body:**

```json
{
  "payment_method": "stripe",
  "token": "tok_visa"
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `payment_method` | string | Yes | Payment provider ("stripe") |
| `token` | string | Yes | Stripe token from Stripe.js or test token |

### Response - Success

**Status Code:** `200 OK`

```json
{
  "status": "success",
  "message": "Payment processed successfully",
  "data": {
    "order_id": 12345,
    "transaction_id": "ch_1A2B3C4D5E6F7G8H",
    "amount": "115.53",
    "status": "paid",
    "message": "Your order has been placed successfully"
  }
}
```

| Field | Type | Description |
|-------|------|-------------|
| `order_id` | integer | The created order ID |
| `transaction_id` | string | Stripe charge ID (ch_...) |
| `amount` | string | Total amount paid (as decimal) |
| `status` | string | Payment status ("paid") |
| `message` | string | Confirmation message |

### Response - Error

**Status Code:** `400, 404, 429, 503` (varies by error)

```json
{
  "status": "error",
  "message": "Your card was declined",
  "data": null
}
```

---

## Stripe Integration

### Test Credentials

For development/testing, use Stripe's test tokens:

| Card Type | Token | Result |
|-----------|-------|--------|
| Visa | `tok_visa` | Succeeds |
| Visa (debit) | `tok_visa_debit` | Succeeds |
| Card Declined | `tok_chargeDeclined` | Fails with decline |
| Lost Card | `tok_chargeLost` | Fails |
| Stolen Card | `tok_chargeStolen` | Fails |
| Processing Error | `tok_chargeProcessingError` | Fails |

### Generating Stripe Tokens

In a real mobile app, use Stripe.js library:

```javascript
// JavaScript example
const stripe = Stripe('pk_test_...');
const cardElement = elements.create('card');

stripe.createToken(cardElement).then(result => {
  if (result.error) {
    console.log(result.error.message);
  } else {
    // Send result.token.id as "token" to /payment endpoint
    fetch('/api/catalog/payment?cart_token=' + cartToken, {
      method: 'POST',
      headers: {
        'X-Company-Hash': companyHash,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        payment_method: 'stripe',
        token: result.token.id
      })
    });
  }
});
```

### Amount Calculation

Amounts are calculated automatically:

- **Subtotal:** Sum of (item price × quantity) for each item
- **Discount:** Applied per item or cart-wide
- **Total:** Subtotal - Discount (rounded to 2 decimals)
- **Stripe API:** Amount converted to cents (×100) automatically

Example:
```
Item 1: $50.00 × 2 = $100.00
Item 2: $25.00 × 1 = $25.00
Subtotal: $125.00
Discount: $10.00
Total: $115.00 (sent to Stripe as 11500 cents)
```

---

## Error Handling

### Card Errors

**Status:** `400`

```json
{
  "status": "error",
  "message": "Your card was declined"
}
```

**Possible Messages:**
- "Your card was declined"
- "Your card has expired"
- "Insufficient funds"
- "Lost or stolen card"
- "Processing error"

### Invalid Request

**Status:** `400`

```json
{
  "status": "error",
  "message": "Invalid Stripe token"
}
```

**Causes:**
- Missing or empty token
- Invalid payment_method
- Cart not found
- Checkout data missing

### Cart Not Found

**Status:** `404`

```json
{
  "status": "error",
  "message": "Cart not found"
}
```

**Cause:** Invalid cart_token parameter

### Rate Limit

**Status:** `429`

```json
{
  "status": "error",
  "message": "Too many requests to Stripe"
}
```

**Cause:** Too many requests to Stripe in short time

### Stripe Connection Error

**Status:** `503`

```json
{
  "status": "error",
  "message": "Unable to connect to Stripe"
}
```

**Cause:** Network issues with Stripe API

---

## Prerequisites

Before calling the Payment endpoint:

1. **Cart must exist**
   ```bash
   GET /api/catalog/cart?cart_token=abc123
   ```
   Response must include items with quantities

2. **Items must be in cart**
   ```bash
   POST /api/catalog/cart/items
   {
     "product_id": 1,
     "quantity": 2,
     "attributes": {...}
   }
   ```

3. **Checkout data must be saved**
   ```bash
   POST /api/catalog/checkout?cart_token=abc123
   {
     "billing_first_name": "John",
     "billing_last_name": "Doe",
     ...all other checkout fields
   }
   ```

4. **Valid Stripe token**
   - Generated from Stripe.js
   - Or test token from table above

---

## Complete Example

### Step 1: Create Cart
```bash
curl -X POST https://missio.dev/api/catalog/cart \
  -H "X-Company-Hash: abc123" \
  -H "Content-Type: application/json" \
  -d '{}'

# Response:
# {
#   "status": "success",
#   "data": {
#     "id": 5,
#     "cart_token": "cart_abc123xyz789",
#     "items": [],
#     "subtotal": 0,
#     "total": 0
#   }
# }
```

### Step 2: Add Item
```bash
curl -X POST https://missio.dev/api/catalog/cart/items \
  -H "X-Company-Hash: abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": 1,
    "quantity": 2,
    "attributes": {"color": "red", "size": "M"}
  }?cart_token=cart_abc123xyz789'

# Response includes updated cart with item added
```

### Step 3: Save Checkout
```bash
curl -X POST https://missio.dev/api/catalog/checkout \
  -H "X-Company-Hash: abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "billing_first_name": "John",
    "billing_last_name": "Doe",
    "billing_email": "john@example.com",
    "billing_phone": "(123) 456-7890",
    "billing_address": "123 Main St",
    "billing_city": "Boston",
    "billing_state": "MA",
    "billing_zip": "02101",
    "billing_country": "US",
    "shipping_first_name": "John",
    "shipping_last_name": "Doe",
    "shipping_email": "john@example.com",
    "shipping_phone": "(123) 456-7890",
    "shipping_address": "123 Main St",
    "shipping_city": "Boston",
    "shipping_state": "MA",
    "shipping_zip": "02101",
    "shipping_country": "US"
  }?cart_token=cart_abc123xyz789'

# Response:
# {
#   "status": "success",
#   "data": {
#     "cart_token": "cart_abc123xyz789",
#     "next_step": "payment"
#   }
# }
```

### Step 4: Process Payment
```bash
curl -X POST https://missio.dev/api/catalog/payment \
  -H "X-Company-Hash: abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_method": "stripe",
    "token": "tok_visa"
  }?cart_token=cart_abc123xyz789'

# Response:
# {
#   "status": "success",
#   "message": "Payment processed successfully",
#   "data": {
#     "order_id": 12345,
#     "transaction_id": "ch_1A2B3C4D5E6F7G8H",
#     "amount": "115.53",
#     "status": "paid",
#     "message": "Your order has been placed successfully"
#   }
# }
```

---

## Data Persistence

### What Happens on Success

1. **Order Created**
   - Order record inserted with:
     - order_id (auto-generated)
     - customer_id (from token or null)
     - company_id (from X-Company-Hash)
     - payment_status: "paid"
     - payment_method: "stripe"
     - transaction_id: Stripe charge ID
     - billing_data: All checkout data as JSON
     - amount: Total paid
     - created_at: Current timestamp

2. **Order Items Created**
   - One record per cart item:
     - order_id: Links to order
     - product_id: From cart
     - variant_id: From variant matching
     - quantity: From cart item
     - unit_price: Current product price
     - amount: unit_price × quantity
     - attributes: Variant attributes as JSON

3. **Cart Cleared**
   - All order_cart records deleted
   - Session cart data cleared
   - Cart no longer accessible

4. **Confirmation**
   - Order confirmation returned
   - order_id can be used to fetch order status

### Data Structure

**Order Record:**
```json
{
  "id": 12345,
  "customer_id": 1,
  "company_id": 5,
  "payment_status": "paid",
  "payment_method": "stripe",
  "transaction_id": "ch_1A2B3C4D5E6F7G8H",
  "billing_data": {
    "billing_first_name": "John",
    "billing_last_name": "Doe",
    "billing_email": "john@example.com",
    ...checkout data
  },
  "amount": 115.53,
  "created_at": "2024-01-15 10:30:45",
  "updated_at": "2024-01-15 10:30:45"
}
```

**Order Item Records:**
```json
[
  {
    "id": 1,
    "order_id": 12345,
    "product_id": 1,
    "variant_id": 5,
    "quantity": 2,
    "unit_price": 50.00,
    "amount": 100.00,
    "attributes": {
      "color": "red",
      "size": "M"
    }
  },
  {
    "id": 2,
    "order_id": 12345,
    "product_id": 2,
    "variant_id": 8,
    "quantity": 1,
    "unit_price": 25.00,
    "amount": 25.00,
    "attributes": {
      "color": "blue"
    }
  }
]
```

---

## Webhook Handling (Optional)

For production, consider implementing Stripe webhooks to handle:

- `charge.succeeded` - Confirm payment
- `charge.failed` - Handle failures
- `charge.refunded` - Process refunds
- `charge.dispute.created` - Handle disputes

Configure webhooks in Stripe Dashboard → Developers → Webhooks

Example endpoint: `https://missio.dev/api/stripe/webhook`

---

## Security Notes

1. **Token Handling**
   - Never log or store tokens
   - Tokens are one-time use only
   - Expired tokens cannot be reused

2. **HTTPS Required**
   - Always use HTTPS for payment requests
   - Never send tokens over HTTP

3. **PCI Compliance**
   - Stripe handles PCI compliance
   - Never directly access raw card numbers
   - Always use tokenization (Stripe.js)

4. **Company Hash**
   - Validates company ownership
   - Required for all requests
   - Controls multi-tenancy

5. **Cart Token**
   - Session-specific identifier
   - Expires after checkout
   - Prevents replay attacks

---

## Testing Checklist

- [ ] Cart created successfully
- [ ] Items added with attributes
- [ ] Checkout data saved with all fields
- [ ] Stripe test token accepted
- [ ] Order created in database
- [ ] Order items created for each cart item
- [ ] Cart cleared after payment
- [ ] Transaction ID returned
- [ ] Order ID returned
- [ ] Correct amount charged
- [ ] Failed card (tok_chargeDeclined) rejected
- [ ] Rate limit error handled
- [ ] Invalid token error handled
- [ ] Missing checkout data error handled

---

## Configuration

Ensure the following is set in `config/services.php`:

```php
'stripe' => [
    'secret' => env('STRIPE_SECRET'),
    'public' => env('STRIPE_PUBLIC_KEY'),
],
```

And in `.env`:

```
STRIPE_PUBLIC_KEY=pk_test_...
STRIPE_SECRET=sk_test_...
```

---

## Support

For issues with:
- **API Integration:** Contact development team
- **Stripe Errors:** See https://stripe.com/docs/error-codes
- **Cart Issues:** See CART_API.md
- **Checkout Issues:** See CHECKOUT_API.md
