1.7 KiB
1.7 KiB
Implementer — F-023 Payments: provider interface + Stripe + webhooks
Summary
Implemented payments module with PaymentProvider interface, Stripe-style webhook signature verification, idempotent event recording via (provider, provider_event_id) unique constraint, and order state transitions on PaymentSucceeded/PaymentFailed. Domain code never imports the Stripe SDK; the adapter handles all signing.
Files changed
project/migrations/017_payments.jsproject/src/modules/payments/**project/src/app/build-app.ts
Acceptance evidence
- AC1 zero Stripe imports:
payments/tests/boundary.test.tsscans domain/application/api files forstripereferences in code; only the adapter mentions Stripe. - AC2 bad signature -> 400:
stripe-payment-provider.test.tscovers invalid signature, missing signature, expired timestamp and unsupported event type; the API mapsInvalidWebhookSignatureErrorto 400. - AC3 webhook processed exactly once:
payments-service.test.tsproves first event returns processed and replayed event returns duplicate with a single recorded transaction. - AC4 PaymentSucceeded -> order PAID:
PaymentsService.handleWebhookcallsordersAdapter.transitionto PAID. - AC5 frontend not trusted: webhook endpoint is unauthenticated and signature-validated; no client status fields are accepted.
Commands run
cd project && npm run lint/typecheck/build/testpassedcd project && TEST_DATABASE_URL='postgres://mdv:mdv_dev_only@localhost:5432/mdv_test' npm run test:integration -- migrations.itestpassed; 14 files, 53 tests./scripts/verify.shpassed
Notes
- No new runtime dependency: webhook signature is HMAC-SHA256 implemented in pure Node crypto.
- Provider is a stub for
createIntent; F-022 already uses the stub.