Files
mercadodevida/work/artifacts/F-023/architect.md
2026-08-17 22:23:10 +02:00

39 lines
1.9 KiB
Markdown

# Architect — F-023 Payments: provider interface + Stripe + webhooks
## Feature
F-023 introduces real payment processing without coupling domain to Stripe.
## Design
### Module boundaries
Create `project/src/modules/payments/` with domain/application/infrastructure/api/tests. Payments owns `payments_transactions`; domain code never imports the Stripe SDK.
### Data model
Add migration `017_payments.js`:
- `payments_transactions`: id, provider text, provider_event_id text unique per provider, provider_payment_id text, order_id uuid, amount_cents integer, currency text, status text, raw jsonb, created_at timestamptz.
- CHECK `status IN ('requires_payment','succeeded','failed','refunded','chargeback')`.
- UNIQUE `(provider, provider_event_id)` for idempotency.
### Payment provider interface
- `PaymentProvider.createIntent(input)` and `PaymentProvider.verifyWebhook(rawBody, signature)` returning a typed `PaymentEvent` or throwing.
- Domain never touches Stripe SDK; only the Stripe adapter does.
### Webhook flow
- `POST /payments/webhook` reads raw body + signature header.
- Verifies signature with `STRIPE_WEBHOOK_SECRET` (or env-derived) — invalid -> 400.
- Looks up `(provider, provider_event_id)` in transactions; if seen, return 200 without re-processing (idempotent).
- Maps Stripe events to `PaymentEvent` (`PaymentSucceeded`, `PaymentFailed`, `PaymentRefunded`, `ChargebackCreated`) and processes them: persist transaction, call `OrderService.transition` and emit event through `OrderEventPublisher`.
### API
- `POST /payments/webhook` public (signature-protected).
- Admin/dev `GET /payments/transactions/:orderId` for inspection.
### Domain events
- Emit `OrderPaid`/`OrderCancelled`/`OrderRefunded` via `OrderEventPublisher` already exposed by orders.
## Acceptance trace
- Domain code contains zero Stripe SDK imports.
- Bad signature -> 400, no DB row.
- Replayed event -> single processed transaction.
- PaymentSucceeded -> order state PAID, event emitted.