# Payments & Subscriptions

## Stack

Laravel Cashier (Stripe). Never implement custom billing logic — use Cashier methods.

## Stripe products

Three recurring subscription products (monthly):
- `basic` — £0.99/mo
- `plus`  — £2.49/mo
- `pro`   — £3.99/mo

Price IDs stored in `config/services.php` under `stripe.prices.*`, loaded from .env:
```
STRIPE_PRICES_BASIC=price_xxx
STRIPE_PRICES_PLUS=price_xxx
STRIPE_PRICES_PRO=price_xxx
```

## Tier helpers (SubscriptionService)

```php
public function tier(User $user): string
// Returns 'free' | 'basic' | 'plus' | 'pro'

public function canReceiveSms(User $user): bool
// true if tier is plus or pro

public function smsRemainingThisMonth(User $user): int
// checks alerts table count for current month
```

Never check tier inline in components or notification classes — always use SubscriptionService.

## Cashier conventions

- Billable model: `User` (add `use Billable` trait)
- Webhook route: `POST /stripe/webhook` — handled by Cashier automatically
- Webhook secret in `.env` as `STRIPE_WEBHOOK_SECRET`
- Always handle `customer.subscription.deleted` to downgrade user to free tier
- Trial: none for v1

## Upgrade / downgrade flow

- User upgrades in account settings Livewire component
- Swap plan with `$user->subscription()->swap($newPriceId)`
- Cashier handles proration automatically
- On downgrade to free: cancel subscription, remove WhatsApp/SMS notification preference

## Stripe test mode

Use Stripe test keys in local `.env`. Never commit real Stripe keys.
Test cards: 4242424242424242 (success), 4000000000000002 (decline).
