Microservice responsible for payment transaction processing, PSP integration, and financial reconciliation.
This service handles:
- Transaction Processing — Create, authorize, capture and manage payment transactions
- PSP Integration — Communication with external Payment Service Provider for authorization and capture
- Webhook Handling — Process callbacks from PSP for async status updates
- Payment Splits — Split transaction amounts between sellers and platform
- Refunds — Full and partial refund processing
- Reconciliation — Async worker that reconciles local records with PSP data
- Node.js + TypeScript
- NestJS framework
- PostgreSQL (primary database)
- Redis (caching)
- AWS SQS (message queue for reconciliation)
- Docker + Docker Compose
- Docker and Docker Compose installed
- Node.js 20+ (for local development)
docker-compose up --buildThis will start:
- PostgreSQL on port 5432
- Redis on port 6379
- Payment Service API on port 3000
The service will automatically run migrations and seed sample data on first boot.
# Install dependencies
pnpm install
# Copy environment file
cp .env.example .env
# Start PostgreSQL and Redis (via Docker)
docker-compose up postgres redis -d
# Run migrations
pnpm run migration:run
# Seed sample data
pnpm run seed
# Start the service
pnpm run start:dev# Unit tests
pnpm test
# Watch mode
pnpm run test:watch
# Coverage
pnpm run test:covSwagger UI is available at:
http://localhost:3000/api/docs
| Method | Path | Description |
|---|---|---|
| POST | /api/transactions | Create a new transaction |
| GET | /api/transactions | List transactions |
| GET | /api/transactions/:id | Get transaction details |
| POST | /api/webhooks/psp | PSP webhook callback |
| POST | /api/refunds | Create a refund |
| GET | /api/refunds/transaction/:id | List refunds for transaction |
| GET | /api/splits/transaction/:id | Get splits for transaction |
Most endpoints require a Bearer JWT token in the Authorization header:
Authorization: Bearer <token>
To generate a valid token for development, use the JWT secret defined in your .env (JWT_SECRET):
# Using Node.js
node -e "console.log(require('jsonwebtoken').sign({ sub: 'user-1', role: 'admin' }, process.env.JWT_SECRET || 'super-secret-jwt-key', { expiresIn: '24h' }))"curl -H "Authorization: Bearer $TOKEN" http://localhost:3000/api/transactions
## Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| DB_HOST | PostgreSQL host | localhost |
| DB_PORT | PostgreSQL port | 5432 |
| DB_USERNAME | Database user | payment_user |
| DB_PASSWORD | Database password | - |
| DB_DATABASE | Database name | payment_service |
| REDIS_HOST | Redis host | localhost |
| REDIS_PORT | Redis port | 6379 |
| JWT_SECRET | JWT signing secret | - |
| PSP_BASE_URL | PSP API base URL | - |
| PSP_API_KEY | PSP API key | - |
| PSP_WEBHOOK_SECRET | PSP webhook HMAC secret | - |
| SQS_RECONCILIATION_QUEUE_URL | SQS queue URL | - |
| PORT | Service port | 3000 |
## Project Structure
src/ ├── config/ # Database and app configuration ├── common/ # Shared guards, interceptors, filters ├── modules/ │ ├── transactions/ # Transaction CRUD and processing │ ├── psp/ # PSP integration layer │ ├── webhooks/ # Webhook receiver and processor │ ├── splits/ # Payment split logic │ ├── refunds/ # Refund processing │ └── reconciliation/ # Async reconciliation worker ├── main.ts # Application bootstrap └── seed.ts # Database seed script
## Development
### Creating Migrations
```bash
pnpm run typeorm migration:generate -- -n MigrationName -d src/config/data-source.ts
pnpm run migration:run