# Stripe Mode Switching Guide — LLMHosts.com

Everything you need to switch between Stripe test and live mode, with all keys, URLs, and steps.

## Your Stripe Account

- **Account ID**: `acct_1SHwnqCSrqBBklIn`
- **Dashboard (Live)**: https://dashboard.stripe.com
- **Dashboard (Test)**: https://dashboard.stripe.com/test

---

## All Keys Reference

### TEST MODE Keys

```env
STRIPE_SECRET_KEY=sk_test_51SHwnqCSrqBBklInjtQnzPPQvPOclTxcSJ2G9SeulRjYDgb8KE1MIjOseSE2pFDFziXuQoek9G4e21tPG1CNueoN00yRyH2F5k
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_51SHwnqCSrqBBklInUtXIU6UWWqxl7s0gbCyGL2f91PFZKgJajhZiscN6bFMOdtpJPAaDasBqeJvxiF3t8qdfUjem00aI8O4XBc
STRIPE_WEBHOOK_SECRET=whsec_pnTbJNNNdAlE0S1LGNObUln1Vyn8TOaZ
STRIPE_PRO_PRICE_ID=price_1T1bh4CSrqBBklInuGtQh72L
STRIPE_TEAM_PRICE_ID=price_1T1bh6CSrqBBklIn7oEvlBZj
STRIPE_ENTERPRISE_PRICE_ID=price_1T1bh7CSrqBBklInXTJjW96Y
```

- **Test card**: `4242 4242 4242 4242` | any future expiry | any CVC | any zip
- **Test card (decline)**: `4000 0000 0000 0002`
- **Test card (requires auth)**: `4000 0025 0000 3155`
- **API keys page**: https://dashboard.stripe.com/test/apikeys
- **Webhook**: https://dashboard.stripe.com/test/webhooks (endpoint: `we_1T3iaBCSrqBBklInZUf4JsrB`)
- **Products**: https://dashboard.stripe.com/test/products
- **Payments**: https://dashboard.stripe.com/test/payments
- **Customers**: https://dashboard.stripe.com/test/customers
- **Subscriptions**: https://dashboard.stripe.com/test/subscriptions

### LIVE MODE Keys

```env
STRIPE_SECRET_KEY=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
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_51SHwnqCSrqBBklInjWUiVlAKGrsHrR4MI2QBK2WCL39woZ55S2avj0fI0I7z5a2Fd0m36o1ZV5gJgAkiOwfmCAyW00HxyX9E5i
STRIPE_WEBHOOK_SECRET=whsec_lkGvwm6RFdLPYnIfUrMUdfL5Rf8RQ90z
STRIPE_PRO_PRICE_ID=price_1T2Lg8CSrqBBklInPeF9cCxF
STRIPE_TEAM_PRICE_ID=price_1T2Lg9CSrqBBklIn5bxjyacY
STRIPE_ENTERPRISE_PRICE_ID=price_1T2Lg9CSrqBBklInHNeAP9KD
```

- **Real cards only** — test card `4242...` will NOT work
- **API keys page**: https://dashboard.stripe.com/apikeys
- **Webhook**: https://dashboard.stripe.com/webhooks
- **Products**: https://dashboard.stripe.com/products
- **Payments**: https://dashboard.stripe.com/payments
- **Subscriptions**: https://dashboard.stripe.com/subscriptions

### Price Breakdown

| Plan | Test Price ID | Live Price ID | Price |
|------|--------------|---------------|-------|
| Pro | `price_1T1bh4CSrqBBklInuGtQh72L` | `price_1T2Lg8CSrqBBklInPeF9cCxF` | $29/mo |
| Team | `price_1T1bh6CSrqBBklIn7oEvlBZj` | `price_1T2Lg9CSrqBBklIn5bxjyacY` | $99/mo |
| Enterprise | `price_1T1bh7CSrqBBklInXTJjW96Y` | `price_1T2Lg9CSrqBBklInHNeAP9KD` | $299/mo |

---

## How to Switch Modes

### Switch to TEST MODE

1. Edit `/home/dev/projects/LLMHosts.com/.env`
2. Replace the 6 Stripe lines with the TEST keys from above
3. Restart the frontend:
   ```bash
   cd /home/dev/projects/LLMHosts.com
   docker compose -f docker-compose.prod.yml -f docker-compose.external-proxy.yml up -d frontend
   ```
4. Verify:
   ```bash
   docker exec llmhosts-frontend sh -c 'echo $STRIPE_SECRET_KEY' | head -c 15
   # Should show: sk_test_51SHwnq
   ```
5. Test at https://llmhosts.com/pricing with card `4242 4242 4242 4242`

### Switch to LIVE MODE

1. Edit `/home/dev/projects/LLMHosts.com/.env`
2. Replace the 6 Stripe lines with the LIVE keys from above
3. Restart the frontend:
   ```bash
   cd /home/dev/projects/LLMHosts.com
   docker compose -f docker-compose.prod.yml -f docker-compose.external-proxy.yml up -d frontend
   ```
4. Verify:
   ```bash
   docker exec llmhosts-frontend sh -c 'echo $STRIPE_SECRET_KEY' | head -c 15
   # Should show: sk_live_51SHwnq
   ```

### Quick One-Liner (ask Claude to run)

Switch to test:
```bash
sed -i 's/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/sk_test_51SHwnqCSrqBBklInjtQnzPPQvPOclTxcSJ2G9SeulRjYDgb8KE1MIjOseSE2pFDFziXuQoek9G4e21tPG1CNueoN00yRyH2F5k/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/pk_live_51SHwnqCSrqBBklInjWUiVlAKGrsHrR4MI2QBK2WCL39woZ55S2avj0fI0I7z5a2Fd0m36o1ZV5gJgAkiOwfmCAyW00HxyX9E5i/pk_test_51SHwnqCSrqBBklInUtXIU6UWWqxl7s0gbCyGL2f91PFZKgJajhZiscN6bFMOdtpJPAaDasBqeJvxiF3t8qdfUjem00aI8O4XBc/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/whsec_lkGvwm6RFdLPYnIfUrMUdfL5Rf8RQ90z/whsec_pnTbJNNNdAlE0S1LGNObUln1Vyn8TOaZ/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/price_1T2Lg8CSrqBBklInPeF9cCxF/price_1T1bh4CSrqBBklInuGtQh72L/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/price_1T2Lg9CSrqBBklIn5bxjyacY/price_1T1bh6CSrqBBklIn7oEvlBZj/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/price_1T2Lg9CSrqBBklInHNeAP9KD/price_1T1bh7CSrqBBklInXTJjW96Y/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/# Stripe (live mode)/# Stripe (TEST mode)/' /home/dev/projects/LLMHosts.com/.env && \
docker compose -f docker-compose.prod.yml -f docker-compose.external-proxy.yml up -d frontend
```

Switch to live:
```bash
sed -i 's/sk_test_51SHwnqCSrqBBklInjtQnzPPQvPOclTxcSJ2G9SeulRjYDgb8KE1MIjOseSE2pFDFziXuQoek9G4e21tPG1CNueoN00yRyH2F5k/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/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/pk_test_51SHwnqCSrqBBklInUtXIU6UWWqxl7s0gbCyGL2f91PFZKgJajhZiscN6bFMOdtpJPAaDasBqeJvxiF3t8qdfUjem00aI8O4XBc/pk_live_51SHwnqCSrqBBklInjWUiVlAKGrsHrR4MI2QBK2WCL39woZ55S2avj0fI0I7z5a2Fd0m36o1ZV5gJgAkiOwfmCAyW00HxyX9E5i/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/whsec_pnTbJNNNdAlE0S1LGNObUln1Vyn8TOaZ/whsec_lkGvwm6RFdLPYnIfUrMUdfL5Rf8RQ90z/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/price_1T1bh4CSrqBBklInuGtQh72L/price_1T2Lg8CSrqBBklInPeF9cCxF/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/price_1T1bh6CSrqBBklIn7oEvlBZj/price_1T2Lg9CSrqBBklIn5bxjyacY/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/price_1T1bh7CSrqBBklInXTJjW96Y/price_1T2Lg9CSrqBBklInHNeAP9KD/' /home/dev/projects/LLMHosts.com/.env && \
sed -i 's/# Stripe (TEST mode)/# Stripe (live mode)/' /home/dev/projects/LLMHosts.com/.env && \
docker compose -f docker-compose.prod.yml -f docker-compose.external-proxy.yml up -d frontend
```

---

## How to Tell Which Mode Is Active

```bash
# Quick check — shows first 15 chars of the secret key
docker exec llmhosts-frontend sh -c 'echo $STRIPE_SECRET_KEY' | head -c 15
# sk_test_... = TEST MODE
# sk_live_... = LIVE MODE
```

Or check the .env directly:
```bash
grep STRIPE_SECRET_KEY /home/dev/projects/LLMHosts.com/.env | head -c 30
```

---

## Webhook Details

Both modes point to the same URL: `https://llmhosts.com/api/stripe/webhook`

| Mode | Webhook ID | Secret | Events |
|------|-----------|--------|--------|
| Test | `we_1T3iaBCSrqBBklInZUf4JsrB` | `whsec_pnTbJNNNdAlE0S1LGNObUln1Vyn8TOaZ` | checkout.session.completed, customer.subscription.created/updated/deleted, invoice.payment_succeeded/failed |
| Live | (check dashboard) | `whsec_lkGvwm6RFdLPYnIfUrMUdfL5Rf8RQ90z` | checkout.session.completed, customer.subscription.updated/deleted, invoice.payment_failed |

**Manage webhooks**:
- Test: https://dashboard.stripe.com/test/webhooks
- Live: https://dashboard.stripe.com/webhooks

---

## Testing Cheat Sheet

### Test Cards

| Card Number | What It Does |
|-------------|-------------|
| `4242 4242 4242 4242` | Succeeds |
| `4000 0000 0000 0002` | Declines |
| `4000 0025 0000 3155` | Requires 3D Secure auth |
| `4000 0000 0000 9995` | Insufficient funds |
| `4000 0000 0000 3220` | 3DS2 authentication |

For all test cards: use any future expiry (e.g., `12/34`), any 3-digit CVC, any zip code.

Full list: https://docs.stripe.com/testing#cards

### Test the Full Billing Flow

1. Go to https://llmhosts.com/pricing
2. Click a plan (Pro recommended for testing)
3. Enter test card `4242 4242 4242 4242`, expiry `12/34`, CVC `123`
4. Complete checkout
5. Should redirect to dashboard with active subscription
6. Verify payment: https://dashboard.stripe.com/test/payments
7. Verify subscription: https://dashboard.stripe.com/test/subscriptions
8. Cancel subscription from dashboard or Stripe portal

### Clean Up Test Data

After testing, clean test customers/subscriptions:
- https://dashboard.stripe.com/test/customers — delete test customers
- Or leave them — test data doesn't affect live mode at all

---

## Backup Locations

| What | Where |
|------|-------|
| Live .env (full backup) | `/home/dev/shared/secure/credentials/llmhosts/production-live-backup.env` |
| Production .env (current) | `/home/dev/projects/LLMHosts.com/.env` |
| Infisical vault | `http://127.0.0.1:8084` → project `llmhosts` → env `prod` |

### Emergency Restore to Live

If .env is messed up:
```bash
cp /home/dev/shared/secure/credentials/llmhosts/production-live-backup.env /home/dev/projects/LLMHosts.com/.env
cd /home/dev/projects/LLMHosts.com
docker compose -f docker-compose.prod.yml -f docker-compose.external-proxy.yml up -d frontend
```

---

## Common Issues

**"Your card was declined"** in test mode → You're using a decline test card or typed the number wrong. Use `4242 4242 4242 4242`.

**Test card rejected in live mode** → You're in live mode. Switch to test mode first (see steps above).

**Webhook not firing** → Check the webhook is enabled in the correct mode's dashboard. Test: https://dashboard.stripe.com/test/webhooks / Live: https://dashboard.stripe.com/webhooks. Click "Send test webhook" to verify.

**Price not found error** → You're using test price IDs with live keys or vice versa. Each mode has its own price IDs. Always swap ALL 6 Stripe values together.

**"No such price" error** → Same as above. Test prices and live prices are completely separate objects even though the dollar amounts match.

---

*Last updated: 2026-02-22*
*Current mode: TEST*
