feat: add Stripe checkout, order persistence, and webhook handling

Stripe-hosted Checkout integration with full order lifecycle:
- stripity_stripe ~> 3.2 with sandbox/prod config via env vars
- Order and OrderItem schemas with price snapshots at purchase time
- CheckoutController creates pending order then redirects to Stripe
- StripeWebhookController verifies signatures and confirms payment
- Success page with real-time PubSub updates from webhook
- Shop flash messages for checkout error feedback
- Cart cleared after successful payment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-07 08:30:17 +00:00
parent cff21703f1
commit ff1bc483b9
19 changed files with 931 additions and 69 deletions

View File

@@ -4,35 +4,14 @@
---
## Core MVP: Cart & Checkout
## Core MVP: Cart & Checkout
### Session-Based Cart
Store cart in Phoenix session (no separate table needed for MVP).
Session-based cart, Stripe-hosted Checkout, order persistence, and webhook handling are all complete. See [PROGRESS.md](PROGRESS.md) for details.
```elixir
defmodule SimpleshopTheme.Cart do
def get(session), do: Map.get(session, "cart", %{})
def add_item(session, variant_id, quantity \\ 1)
def remove_item(session, variant_id)
def update_quantity(session, variant_id, quantity)
def clear(session)
def to_line_items(cart)
def total(cart)
def item_count(cart)
end
```
### Stripe Checkout
Stripe Checkout (hosted payment page) integration.
**Dependencies:** `{:stripity_stripe, "~> 3.0"}`
**Routes:**
```elixir
post "/webhooks/stripe", StripeWebhookController, :handle
live "/checkout/success", ShopLive.CheckoutSuccess
live "/checkout/cancel", ShopLive.CheckoutCancel
```
### Orders & Fulfillment (next up)
- Submit paid orders to Printify for fulfillment
- Track fulfillment status updates via webhook
- Display order status to customers
### Cost Verification at Checkout
Verify Printify costs haven't changed before completing checkout to prevent selling at a loss.