Payment Service
@nx/payment is a thin orchestration layer that wires @nx/mq-pay (the multi-provider payment engine) into the BANA platform. It owns:
- Per-merchant payment provider credentials (encrypted in
Configurationtable). WebhookConfigregistry — outbound HTTP webhooks fired when MQ-Pay state changes.- The event-handler bridge that translates MQ-Pay events to webhook calls + WebSocket broadcasts.
It supports mode-based deployment via APP_ENV_MQ_PAY_MODE: FULL (single instance), API (REST + queue producer only), WORKER (queue consumer only).
1. Quick Reference
| Property | Value |
|---|---|
| Package | @nx/payment |
| Code | SVC-00040-PAYMENT |
| Type | Microservice (orchestration bridge) |
| Runtime | Bun |
| Base Class | VerifierApplication |
| Location | packages/payment |
| Base Path | /v1/api/payment |
| Dev Port | 31040 |
| Container Port | 3000 (external 31040) |
| Snowflake ID (FULL) | 4 |
| Snowflake ID (API) | 8 (production split) |
| Snowflake IDs (WORKER) | 91, 92, … (one per worker pod) |
| DB Schema | shared Configuration + WebhookConfig |
| Binding Namespace | @nx/payment |
2. Purpose & Scope
| Included | Excluded |
|---|---|
Wire @nx/mq-pay providers (VNPAY QR MMS / PhonePOS / SmartPOS, SYSTEM) | Direct provider integration code (lives in @nx/mq-pay) |
| Per-merchant credential management (AES-256-GCM encrypted) | Multi-currency conversion |
WebhookConfig CRUD (subscribers register their endpoints) | Payment UX / checkout flow (sale's job) |
| Event-handler bridge: MQ-Pay events → WebhookDispatcher + WebSocket | Token vault / card storage |
| Mode-based deployment for horizontal scaling | Cross-merchant settlement reconciliation |
| Real-time transaction/attempt WebSocket broadcasts |
3. Tech Stack
External:
| Library | Purpose |
|---|---|
@venizia/ignis | IoC + DI |
@venizia/ignis-helpers | Logger, Redis helper |
hono + @hono/zod-openapi | HTTP + OpenAPI |
@scalar/hono-api-reference | Scalar viewer at /doc |
drizzle-orm + pg | DB |
ioredis | Redis |
Internal:
| Package | Purpose |
|---|---|
@nx/core | Schemas, repositories, VerifierApplication, CryptoUtility, WebhookDispatcherService, MailComponent reuse |
@nx/mq-pay | Multi-provider payment engine — auto-registered via MQPayComponent |
4. Project Structure
packages/payment/
├── src/
│ ├── application.ts # VerifierApplication subclass
│ ├── index.ts # bootstrapApplication()
│ ├── migrate.ts # bootstrapMigration()
│ ├── common/
│ │ ├── keys.ts # BindingKeys (BASE = '@nx/payment')
│ │ ├── rest-paths.ts # 1 path: WEBHOOK_CONFIGS
│ │ ├── websocket.ts # PaymentWebSocketTopics + Rooms
│ │ └── types.ts
│ ├── components/
│ │ ├── payment.component.ts # ApplicationPaymentComponent — MQ-Pay wiring
│ │ ├── websocket.component.ts # ApplicationWebSocketComponent
│ │ └── index.ts
│ ├── controllers/
│ │ ├── webhook-config/ # WebhookConfigController + definitions
│ │ ├── permissions.ts # PaymentPermissions aggregate
│ │ └── index.ts
│ ├── helpers/
│ │ └── webhook-event-handler/ # WebhookEventHandlerHelper (the bridge)
│ ├── services/
│ │ ├── payment-configuration.service.ts # Encrypted provider creds load
│ │ ├── payment-socket-event.service.ts # WS broadcast for transactions/attempts
│ │ └── index.ts
│ ├── datasources/ # PostgresCoreDataSource
│ └── migrations/processes/ # 3 seeds (VNPAY QR, VNPAY PhonePOS, permissions)
├── package.json
└── tsconfig.json5. Architecture
Detail: see Architecture.
6. Domain Snapshot
Full ERD + per-entity tables: see Domain Model.
7. Surface Summary
REST controllers — full reference rendered live from /v1/api/payment/doc/openapi.json (live spec — Scalar viewer at /doc, gateway portal):
| Controller | Base path | Notes |
|---|---|---|
WebhookConfigController | /webhook-configs | merchant-scoped CRUD |
(from @nx/mq-pay — conditional on mode FULL/API) | various | 5 controllers: Transaction, TransactionItem, PaymentAttempt, PaymentResult, PaymentOperation |
Async surface — full reference in API Events:
| Direction | Channel | Notes |
|---|---|---|
| Inbound | HTTP IPN (provider → MQ-Pay) | VN Pay IPN endpoints (in @nx/mq-pay) |
| Outbound | HTTP webhook (per WebhookConfig) | Subscribers like sale receive event payloads |
| Outbound | WebSocket | Transaction + Attempt updates fanout to merchant rooms |
| Internal | BullMQ | scheduler / confirmation queues (via MQ-Pay) |
8. Components
| Component | File | Purpose |
|---|---|---|
ApplicationPaymentComponent | src/components/payment.component.ts | Main wiring — registers repos/services/controllers, conditionally loads MQ-Pay when RUN_MODE=startup; binds VNPAY configs + WebhookEventHandlerHelper |
ApplicationWebSocketComponent | src/components/websocket.component.ts | Redis-backed emitter for transaction/attempt updates |
9. Services
| Service | File | One-liner |
|---|---|---|
PaymentConfigurationService | services/payment-configuration.service.ts | Load encrypted provider configs/credentials from Configuration table; AES-256-GCM decrypt |
PaymentSocketEventService | services/payment-socket-event.service.ts | Broadcast transaction/attempt events to merchant + transaction rooms |
All other "payment services" (PaymentExecutionService, PaymentCancellationService, PaymentConfirmationService, PaymentRefundService, PaymentVerificationService, QueueProcessorService) live in
@nx/mq-payand are auto-registered by its component.
10. Helpers
| Helper | File | Purpose |
|---|---|---|
WebhookEventHandlerHelper | helpers/webhook-event-handler/helper.ts | The bridge: implements IPaymentEventHandler. On MQ-Pay event, queries subscribed WebhookConfig rows, calls WebhookDispatcherService, fires WebSocket broadcast. |
11. Repositories
| Repository | Source | Notes |
|---|---|---|
ConfigurationRepository | @nx/core | Per-merchant payment provider credentials (encrypted) |
WebhookConfigRepository | @nx/core | Webhook subscribers |
MigrationRepository | @nx/core | Migration state |
(from @nx/mq-pay — auto) | various | TransactionRepository, TransactionItemRepository, PaymentAttemptRepository, PaymentResultRepository |
PermissionRepository | @nx/core | Permission catalogue (used at boot for seeds) |
12. Entry Points
| File | Purpose |
|---|---|
src/index.ts | Service entry → bootstrapApplication() |
src/migrate.ts | Migration entry → bootstrapMigration() |
src/application.ts | Application extends VerifierApplication |
13. Configuration
Env vars + seeded data: see Configuration.
14. Operations
Deployment + observability + security + runbook: see Operations.
15. Related Pages
Concepts — why/how:
- Architecture
- Domain Model
- Integration — sale + MQ-Pay + webhook subscribers
Reference — lookup:
- API Events — webhooks + WebSocket
- Configuration
- Operations
- REST endpoints — live OpenAPI at
/v1/api/payment/doc/openapi.json(live spec — Scalar viewer at/doc, gateway portal)
Features — deep dives:
- Webhook Dispatch
- Provider Credentials — encrypted per-merchant configs
Decisions: