# WooCommerce Integration Guide

## Overview

This checkout system integrates with WooCommerce to provide a secure, Stripe-powered payment experience. This guide explains how to properly integrate it with your WooCommerce store.

---

## 🛒 Cart Management Flow

### The Problem
By default, WooCommerce empties the cart **immediately** when an order is created (status: "pending"). This can be problematic if:
- The customer abandons the checkout page
- The payment fails
- The customer closes the browser

### Our Solution
This checkout system implements **smart cart management**:

1. **Order Creation** → Cart is emptied by WooCommerce (standard behavior)
2. **Checkout Page** → Order remains "pending", cart stays empty
3. **Payment Success** → Order status → "processing", cart cleared permanently ✅
4. **Payment Failure** → Order stays "pending", customer can retry ✅
5. **Page Closed** → Order stays "pending", customer can return later ✅

### Cart States

| Scenario | Order Status | Cart State | Customer Can |
|----------|--------------|------------|--------------|
| Order created | `pending` | Empty (temporary) | Continue checkout |
| Payment successful | `processing` | Cleared permanently | See order in history |
| Payment failed | `pending` | Stays empty* | Retry payment |
| Page abandoned | `pending` | Stays empty* | Return to checkout |

**Note:** *For failed/abandoned payments, customers should return to their WooCommerce cart to create a new order. The pending order will remain in their order history for reference.

---

## 🔄 Order Flow

### Step 1: Create Order in WooCommerce

The order **MUST** be created in WooCommerce **BEFORE** the customer reaches this checkout page.

```php
// Example: Create order programmatically
$order = wc_create_order();
$order->add_product( $product, $quantity );
$order->set_address( $billing_address, 'billing' );
$order->set_address( $shipping_address, 'shipping' );
$order->calculate_totals();
$order->set_status( 'pending' );
$order->save();
```

**Important:** The order status MUST be `pending` for the checkout to work.

### Step 2: Generate Checkout Token

Use the provided token generation utility:

```php
// In your WooCommerce theme/plugin
$order_id = $order->get_id();
$checkout_url = generate_checkout_url( $order_id );

// Redirect customer to checkout
wp_redirect( $checkout_url );
exit;
```

### Step 3: Customer Completes Payment

The customer is redirected to:
```
https://your-checkout-domain.com/checkout?token=XXXXX
```

### Step 4: Payment Processing

1. Customer enters billing/shipping info
2. Customer submits payment
3. Stripe processes payment
4. Webhook updates order status to `processing`
5. **Cart is cleared** (for logged-in customers)
6. Customer sees success page
7. **Auto-redirect to WooCommerce orders page after 5 seconds**

---

## ✅ Success Page

When payment succeeds:

- ✨ Beautiful animated success message
- 📦 Order confirmation details
- ⏱️ 5-second countdown timer
- 🔄 Automatic redirect to: `{WC_BASE_URL}/my-account/orders/`
- 🧹 Cart is cleared permanently

**Environment Variable Required:**
```env
NEXT_PUBLIC_WC_BASE_URL=https://your-store.com
```

---

## ❌ Failure Page

When payment fails:

- 🚨 Clear failure message
- 🛡️ Reassurance that cart is safe
- 💡 Helpful troubleshooting tips
- ⏱️ 5-second countdown timer
- 🔄 Automatic redirect to: `{WC_BASE_URL}/my-account/orders/`
- 🛒 Order stays "pending" for retry

**Note:** Cart items are NOT restored automatically. Customer should return to their cart to create a new order if needed.

---

## 🔐 Customer Association

### Ensuring Orders Appear in Order History

The webhook automatically preserves customer association:

```typescript
// In webhook handler
if (order.customer_id > 0) {
  orderUpdate.customer_id = order.customer_id
}
```

**Requirements:**
1. Order must have `customer_id` set when created
2. For logged-in customers: `customer_id` = WooCommerce user ID
3. For guest customers: `customer_id` = 0

### Verifying Customer Association

```php
// In WooCommerce
$order = wc_get_order( $order_id );
$customer_id = $order->get_customer_id();

if ( $customer_id > 0 ) {
    // Order is associated with customer account
    // Will appear in My Account → Orders
}
```

---

## 📦 Shipping Data

### Capturing Shipping Information

Shipping data is captured in two ways:

1. **From WooCommerce Order** (when order is created)
2. **From Checkout Form** (when customer submits payment)

The checkout form updates the order with:
- Billing address
- Shipping address
- Contact email

```typescript
// Automatically updated via /api/payment-intent
await WooCommerce.updateOrder(order.id, {
  billing: billingAddress,
  shipping: shippingAddress,
  billing_email: email,
})
```

### Accessing Shipping Data

```php
// In WooCommerce
$order = wc_get_order( $order_id );

// Shipping address
$shipping_address = $order->get_address( 'shipping' );

// Shipping method
$shipping_methods = $order->get_shipping_methods();

// Shipping cost
$shipping_total = $order->get_shipping_total();
```

---

## 🔧 Required WooCommerce Setup

### 1. REST API Credentials

1. Go to **WooCommerce → Settings → Advanced → REST API**
2. Click **Add key**
3. Description: `Next.js Checkout`
4. User: Select admin user
5. Permissions: **Read/Write**
6. Copy **Consumer Key** and **Consumer Secret**

### 2. Environment Variables

```env
# WooCommerce Configuration
WC_BASE_URL=https://your-store.com
WC_CONSUMER_KEY=ck_xxxxxxxxxxxxx
WC_CONSUMER_SECRET=cs_xxxxxxxxxxxxx

# Public URL for redirects
NEXT_PUBLIC_WC_BASE_URL=https://your-store.com
```

### 3. Order Statuses

Ensure these order statuses exist:
- `pending` - Order created, awaiting payment
- `processing` - Payment successful
- `cancelled` - Payment abandoned (optional)

---

## 🎯 Token Generation (PHP)

Create a helper function in your WooCommerce theme:

```php
<?php
/**
 * Generate checkout token for an order
 * 
 * @param int $order_id WooCommerce order ID
 * @return string Checkout URL with token
 */
function generate_checkout_url( $order_id ) {
    $secret = getenv('CHECKOUT_TOKEN_SECRET'); // Same as Next.js
    $ttl = 900; // 15 minutes
    
    $payload = [
        'order_id' => $order_id,
        'exp' => time() + $ttl,
        'nonce' => wp_generate_uuid4(),
    ];
    
    $data = json_encode($payload);
    $signature = hash_hmac('sha256', $data, $secret);
    $token = base64_encode($data . '.' . $signature);
    
    // Store nonce in order meta
    update_post_meta( $order_id, '_checkout_nonce', $payload['nonce'] );
    
    $checkout_url = 'https://your-checkout-domain.com/checkout?token=' . urlencode($token);
    
    return $checkout_url;
}
```

---

## 🚀 Integration Example

### Complete WooCommerce Integration

```php
<?php
/**
 * Redirect to custom checkout after order creation
 */
add_action( 'woocommerce_thankyou', 'redirect_to_custom_checkout', 10, 1 );

function redirect_to_custom_checkout( $order_id ) {
    if ( ! $order_id ) return;
    
    $order = wc_get_order( $order_id );
    
    // Only redirect for pending orders
    if ( $order->get_status() !== 'pending' ) return;
    
    // Check if already redirected
    $redirected = get_post_meta( $order_id, '_custom_checkout_redirect', true );
    if ( $redirected ) return;
    
    // Mark as redirected
    update_post_meta( $order_id, '_custom_checkout_redirect', '1' );
    
    // Generate checkout URL
    $checkout_url = generate_checkout_url( $order_id );
    
    // Redirect
    wp_redirect( $checkout_url );
    exit;
}
```

---

## 🔍 Troubleshooting

### Cart is Empty After Order Creation

**This is normal.** WooCommerce empties the cart when an order is created. The order remains in "pending" status until payment is completed.

### Order Doesn't Appear in Customer's Order History

**Check:**
1. Order has `customer_id` set (not 0)
2. Customer is logged in when order is created
3. Webhook successfully updated order status to "processing"

**Fix:**
```php
// Manually associate order with customer
$order = wc_get_order( $order_id );
$order->set_customer_id( get_current_user_id() );
$order->save();
```

### Payment Succeeds but Order Still Pending

**Check:**
1. Webhook is properly configured in Stripe dashboard
2. Webhook secret is correct in `.env.local`
3. Check webhook logs in Stripe dashboard
4. Check server logs for errors

### Shipping Data Not Captured

**Ensure:**
1. Order has shipping method set when created
2. Checkout form includes shipping address fields
3. `/api/payment-intent` receives shipping_address in request

---

## 📊 Order Metadata

The system stores these metadata fields:

| Meta Key | Description | Set When |
|----------|-------------|----------|
| `_checkout_nonce` | One-time token nonce | Order creation |
| `_payment_intent_id` | Stripe PaymentIntent ID | Payment intent created |
| `_stripe_payment_intent_id` | Stripe PaymentIntent ID | Payment successful |
| `_stripe_charge_id` | Stripe Charge ID | Payment successful |
| `_paid_date` | Payment completion date | Payment successful |
| `_payment_method` | Payment method (stripe) | Payment successful |
| `_payment_method_title` | Display name | Payment successful |
| `_transaction_id` | Transaction ID | Payment successful |
| `_checkout_address_updated` | Address update timestamp | Address submitted |
| `_payment_failed_at` | Last failure timestamp | Payment failed |
| `_payment_error` | Last error message | Payment failed |

---

## 🎨 Customization

### Custom Redirect URLs

Override the redirect URL in environment variables:

```env
NEXT_PUBLIC_WC_BASE_URL=https://your-store.com
```

Redirects will go to: `{NEXT_PUBLIC_WC_BASE_URL}/my-account/orders/`

### Custom Success/Failure Messages

Edit the following files:
- `app/success/page.tsx` - Success page
- `app/payment-failed/page.tsx` - Failure page

### Countdown Timer Duration

Change the countdown duration (default: 5 seconds):

```typescript
// In app/success/page.tsx or app/payment-failed/page.tsx
const [countdown, setCountdown] = useState(5) // Change to desired seconds
```

---

## 🔒 Security Considerations

1. **Token Expiry**: Tokens expire after 15 minutes (configurable)
2. **Nonce Protection**: Each token can only be used once
3. **HMAC Signing**: Tokens are cryptographically signed
4. **Amount Validation**: Server validates all amounts
5. **Webhook Verification**: Stripe signatures verified
6. **Customer Association**: Orders tied to customer accounts

---

## 📞 Support

For issues or questions:

1. Check webhook logs in Stripe dashboard
2. Check server logs for errors
3. Verify environment variables are correct
4. Test with Stripe test cards first
5. Ensure WooCommerce REST API is accessible

---

## ✨ Features Summary

✅ **Cart Management**
- Cart preserved until payment succeeds
- Automatic cart clearing on success
- Order stays pending on failure for retry

✅ **Beautiful UI**
- Animated success page with countdown
- Clear failure page with troubleshooting
- Automatic redirect after 5 seconds

✅ **Customer Experience**
- Orders appear in order history
- Email confirmations sent
- Shipping data captured
- Retry on failure

✅ **Security**
- Token-based authentication
- Webhook verification
- Amount validation
- Customer association

---

## 🎯 Quick Start Checklist

- [ ] Set up WooCommerce REST API credentials
- [ ] Configure environment variables
- [ ] Set up Stripe webhook endpoint
- [ ] Test order creation flow
- [ ] Test successful payment
- [ ] Test failed payment
- [ ] Verify cart management
- [ ] Verify order history
- [ ] Test redirect URLs
- [ ] Test with logged-in customer
- [ ] Test with guest customer

---

**Last Updated:** December 2024
**Version:** 2.0






