Commit bef2e24
authored
feat(gateway-arch): move Stripe webhook handling to financial-gateway (#1391)
* feat(financial-gateway): define PaymentCapturedEvent and PaymentFailedEvent protos
Adds financial_gateway_events/v1 proto package with PaymentCapturedEvent and
PaymentFailedEvent message types. Registers corresponding Kafka topics and
HTTP port constant.
Part of 033-gateway-architecture task 9: Move webhook handling to financial-gateway.
* feat(gateway-arch): move Stripe webhook handling from payment-order to financial-gateway
Moves Stripe webhook reception from payment-order to financial-gateway,
the correct architectural home for payment provider integration.
financial-gateway changes:
- Add HTTP webhook handler (adapters/http/webhook_handler.go) that validates
Stripe-Signature, maps payment_intent.succeeded → PaymentCapturedEvent and
payment_intent.payment_failed → PaymentFailedEvent, and publishes via
transactional outbox
- Extend ParsedWebhookEvent with AmountMinorUnits and Currency fields
- Add ManifestTenantConfigProvider and envTenantConfigProvider for per-tenant
webhook secrets (control-plane or env-var fallback)
- Wire HTTP server on port 8095 (/webhooks/stripe) alongside existing gRPC server
- Add outbox worker for Kafka publish (KAFKA_BOOTSTRAP_SERVERS or KAFKA_BROKERS)
- Add event_outbox migration and Atlas config
payment-order changes:
- Remove StripeWebhookHandler, StripeEventProcessor, and related tests
- Remove /webhook/stripe route from HTTP server
- Add PaymentEventConsumer that subscribes to financial-gateway Kafka topics and
calls UpdatePaymentOrder to transition orders to SETTLED or REJECTED
* fix(payment-order): rename unused ctx parameter in consumer test stub
Renames unused ctx parameter to _ to satisfy golangci-lint revive rule.
* fix: remove payment-order Stripe webhook e2e test referencing deleted types
The stripe e2e test file referenced StripeWebhookHandler, NewStripeEventProcessor,
and StripeWebhookHandlerConfig which were deleted as part of moving webhook
handling to financial-gateway. Since the Stripe webhook E2E tests no longer
apply to payment-order (which now receives events via Kafka from financial-gateway),
the file is removed.
* fix: remove unused withSagaOrchestration helper from payment-order e2e tests
withSagaOrchestration was only used by the deleted stripe_e2e_test.go.
Removing to fix golangci-lint unused function error.
* fix: register financial-gateway database mapping in migration runner
The migration runner's ServiceDatabases map did not include financial-gateway,
causing the unified binary --migrate flag to fail with "unknown service: no
database mapping" when encountering the new financial-gateway migrations.
* fix: add financial-gateway topics to topics.yaml and topics_test.go
TestAll_ContainsAllConstants and TestTopicsYAML_ConsistentWithGoConstants
both enforce that topics.go constants, topics.yaml, and topics.All() are
consistent. The new financial-gateway topics were added to the Go constants
and All() slice but were missing from topics.yaml and the test's knownConstants
list.
* fix: address CodeRabbit review comments for webhook migration
- Fix silent proto deserialization corruption: use two separate
kafka.ProtoConsumer instances (one per topic) with the correct
typed msgFactory, preventing PaymentFailedEvent bytes from being
decoded as PaymentCapturedEvent
- Fix missing tenant context: change route to POST /webhooks/stripe/{tenantID}
and extract tenant via r.PathValue("tenantID") instead of relying on
middleware that was never wired; inject into ctx via tenant.WithTenant
- Fix nil OutboxPublisher not validated: panic in NewWebhookHandler
when OutboxPublisher is nil, consistent with ClientFactory guard
- Fix gRPC listener resource leak: add listenerClosed flag with deferred
close so listener is not abandoned on startup failures after bind
- Fix serverErrors channel buffer too small: increase from 2 to 3
to accommodate gRPC + HTTP + payment event consumer goroutines
- Use static sentinel errors (ErrUnexpectedCapturedMessageType,
ErrUnexpectedFailedMessageType) for type assertion failures in
consumers to satisfy err113 linter
- Update webhook_handler_test.go to use r.SetPathValue("tenantID")
instead of tenant.WithTenant context injection, matching new handler
behaviour; remove unused tenant import
- Update payment-order/cmd/main.go to use new Start(capturedTopic,
failedTopic string) signature for PaymentEventConsumer
* fix: address remaining CodeRabbit review comments
- Validate payment_order_id before publishing to outbox: events missing
this metadata field (non-Meridian Stripe payments) are now acknowledged
with a warning log instead of returning 500 and causing infinite retries
- Add HTTP server timeouts (ReadHeaderTimeout/ReadTimeout/WriteTimeout/
IdleTimeout) to financial-gateway webhook server to prevent slowloris
connection exhaustion attacks
- Guard against nil PaymentOrderUpdater in both PaymentEventConsumer
constructors; NewPaymentEventConsumer panics, NewPaymentEventConsumerWithKafka
returns ErrNilPaymentOrderUpdater
- Move NewPaymentEventConsumerWithKafka construction before server start
goroutines so initialization failures return cleanly without leaving
active listeners/goroutines behind
* docs: clarify intentional insecure gRPC credentials for inter-service calls
Inter-service gRPC connections use insecure.NewCredentials() by design
across the Meridian platform. Network-layer security (mTLS via service mesh)
handles encryption for cluster-internal traffic. This matches the pattern
used in position-keeping, reconciliation, tenant, and other services.
---------
Co-authored-by: Ben Coombs <bjcoombs@users.noreply.github.com>1 parent 580b37b commit bef2e24
25 files changed
Lines changed: 1587 additions & 1996 deletions
File tree
- api/proto/meridian/financial_gateway_events/v1
- internal/migrations
- services
- financial-gateway
- adapters
- http
- stripe
- atlas
- cmd
- config
- migrations
- payment-order
- adapters
- http
- messaging
- cmd
- e2e
Lines changed: 101 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| 82 | + | |
82 | 83 | | |
83 | 84 | | |
84 | 85 | | |
| |||
0 commit comments