A microservices-based backend system for tuition payment via iBanking application, built with NestJS and Docker.
- Microservices Architecture: 7 independent services with API Gateway pattern
- Authentication & Authorization: JWT-based authentication with refresh tokens
- User Management: User profile and balance management
- Student Lookup: Search students by student code and retrieve tuition information
- Payment Processing: Saga pattern for distributed transaction management
- OTP Verification: Redis-based OTP system with email notifications
- Event-Driven Communication: RabbitMQ for asynchronous service communication
- Rate Limiting: API Gateway rate limiting for security
- Health Monitoring: Comprehensive health checks for all services
- Framework: NestJS (Microservices)
- Databases: PostgreSQL with TypeORM (Database per Service)
- Message Queue: RabbitMQ for event-driven communication
- Caching: Redis for OTP storage and session management
- Authentication: JWT with Passport (Access & Refresh tokens)
- Email: Nodemailer with SMTP
- Containerization: Docker & Docker Compose
- API Gateway: Request routing, authentication, rate limiting
- Validation: class-validator, class-transformer
- Documentation: Swagger/OpenAPI
- Docker & Docker Compose
- Node.js (v18 or higher) - for development
- pnpm (recommended) or npm
- Clone the repository:
git clone <repository-url>
cd ibanking-subsystem- Set up environment variables for each service:
# Copy environment examples for all services
cp services/api-gateway/env.example services/api-gateway/.env
cp services/auth-service/env.example services/auth-service/.env
cp services/notification-service/env.example services/notification-service/.env
cp services/otp-service/env.example services/otp-service/.env
cp services/payment-service/env.example services/payment-service/.env
cp services/tuition-service/env.example services/tuition-service/.env
cp services/users-service/env.example services/users-service/.env- Configure each service's
.envfile:
API Gateway (services/api-gateway/.env):
NODE_ENV=development
PORT=4000
JWT_SECRET=your-super-secret-jwt-key
JWT_EXPIRES_IN=24h
JWT_REFRESH_SECRET=your-super-secret-jwt-refresh-key
JWT_REFRESH_EXPIRES_IN=7d
ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3001Auth Service (services/auth-service/.env):
NODE_ENV=development
PORT=4001
JWT_SECRET=your-super-secret-jwt-key
JWT_EXPIRES_IN=24h
JWT_REFRESH_SECRET=your-super-secret-jwt-refresh-key
JWT_REFRESH_EXPIRES_IN=7d
DB_HOST=auth_postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=authdbNotification Service (services/notification-service/.env):
NODE_ENV=production
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password
RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672OTP Service (services/otp-service/.env):
NODE_ENV=development
PORT=4004
REDIS_HOST=redis
REDIS_PORT=6379
RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672Payment Service (services/payment-service/.env):
NODE_ENV=development
PORT=4007
DB_HOST=payment_postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=payment_db
RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
REDIS_HOST=redis
REDIS_PORT=6379Tuition Service (services/tuition-service/.env):
NODE_ENV=development
PORT=4006
DB_HOST=tuition_postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=tuition_dbUsers Service (services/users-service/.env):
NODE_ENV=development
PORT=4005
DB_HOST=users_postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_NAME=usersdb
RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672- Set
NODE_ENV=productionin notification service to enable real email sending - Replace
your-email@gmail.comandyour-app-passwordwith your actual Gmail credentials - Replace
your-super-secret-jwt-keywith a strong secret key - All database hosts use Docker service names (e.g.,
auth_postgres,payment_postgres)
- Start the entire system with Docker Compose:
# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop all services
docker-compose down- (Optional) Update tuition data using SQL script:
# Run tuition update script
docker exec -i tuition_postgres psql -U postgres -d tuition_db < scripts/insert_tuition.sql
# Or manually connect to database
docker exec -it tuition_postgres psql -U postgres -d tuition_dbOnce the application is running, visit:
- Swagger UI: http://localhost:4000/api
- API Base URL: http://localhost:4000
- RabbitMQ Management: http://localhost:15672 (guest/guest)
| Service | Port | Description | Database |
|---|---|---|---|
| API Gateway | 4000 | Entry point, routing, authentication | - |
| Auth Service | 4001 | Authentication & JWT management | PostgreSQL (5433) |
| Notification Service | 4003 | Email notifications | - |
| OTP Service | 4004 | OTP generation & validation | Redis |
| Users Service | 4005 | User profiles & balance management | PostgreSQL (5437) |
| Tuition Service | 4006 | Student & tuition data | PostgreSQL (5435) |
| Payment Service | 4007 | Payment orchestration & saga | PostgreSQL (5436) |
| Service | Port | Description |
|---|---|---|
| Redis | 6379 | OTP storage & caching |
| RabbitMQ | 5672 | Message queue |
| RabbitMQ Management | 15672 | Queue monitoring UI |
- Synchronous: HTTP/REST via API Gateway
- Asynchronous: RabbitMQ for event-driven communication
- Caching: Redis for OTP and session data
- Saga Pattern: Payment Service orchestrates distributed transactions
All endpoints are accessed through the API Gateway at http://localhost:4000
GET /health- Check health status of all services
POST /auth/signin- User sign inPOST /auth/signup- User registrationGET /auth/refresh- Refresh access token (uses refresh token from cookies)POST /auth/logout- User logout (clears refresh token)GET /auth/logout-all- Logout from all devices (requires JWT)GET /auth/me- Get current user profile (requires JWT)
GET /tuition/:studentId- Lookup student by student ID (requires JWT)GET /tuition- Get all students (requires JWT)
POST /payments- Start payment processing saga (requires JWT)GET /payments/history- Get user payment history (requires JWT)GET /payments/:paymentId- Get payment details by ID (requires JWT)GET /payments/:paymentId/saga- Get saga details for payment cancellation reason (requires JWT)
POST /otp/verify- Verify OTP code for payment (requires JWT)POST /payments/resend-otp/:paymentId- Resend OTP for payment (requires JWT)GET /otp/info/:paymentId- Get OTP information for payment (requires JWT)
Internal communication between services via RabbitMQ events
payment.created- Payment saga startedpayment.completed- Payment transaction completed successfullypayment.failed- Payment transaction failedpayment.cancelled- Payment cancelled (timeout, max attempts, etc.)
otp.generated- OTP code generated and stored in Redisotp.verified- OTP code verified successfullyotp.expired- OTP code expiredotp.max_attempts- Maximum OTP attempts exceeded
user.balance.updated- User balance updated after transactionuser.balance.insufficient- Insufficient balance for transaction
saga.step.completed- Saga step completed successfullysaga.step.failed- Saga step failedsaga.compensate- Saga compensation triggeredsaga.completed- Entire saga completed successfullysaga.failed- Entire saga failed
Success Response:
{
"success": true,
"data": { ... }
}Error Response:
{
"message": "Error description",
"errorCode": "ERROR_CODE",
"errorType": "ErrorType",
"details": "Additional error details",
"timestamp": "2025-10-27T14:30:00.000Z",
"service": "service-name"
}The application includes sample data seeded automatically:
- username:
nhandang02, password:123456, email:thanhnhandang.it@gmail.com - username:
admin, password:admin123, email:admin@example.com
- username:
nhandang02, fullName:Dang Thanh Nhan, balance: 1,998,500,000 VND - username:
admin, fullName:Admin User, balance: 20,000,000 VND
- 522H0006 - Dang Thanh Nhan (1,500,000 VND)
- 522H0051 - Nguyen Thanh Nhan (2,000,000 VND)
- Sign In -
POST /auth/signin - Lookup Student -
GET /tuition/:studentId - Start Payment Saga -
POST /payments - Verify OTP -
POST /otp/verify - View Payment History -
GET /payments/history - View Saga Details -
GET /payments/:paymentId/saga
- Payment Created -
payment.createdevent published - OTP Generation -
otp.generatedevent triggers email sending - Email Notification - Notification Service sends OTP email
- OTP Verified -
otp.verifiedevent triggers saga execution - Balance Update -
user.balance.updatedevent updates user balance - Payment Completed -
payment.completedevent triggers confirmation email - Saga Events -
saga.step.completed,saga.completedevents track progress
- Client calls
POST /payments→ API Gateway → Payment Service - Payment Service publishes
payment.createdevent - OTP Service receives event, generates OTP, publishes
otp.generated - Notification Service receives event, sends OTP email
- Client calls
POST /otp/verify→ API Gateway → OTP Service - OTP Service publishes
otp.verifiedevent - Payment Service receives event, executes saga steps
- Users Service receives
user.balance.updatedevent, updates balance - Payment Service publishes
payment.completedevent - Notification Service receives event, sends confirmation email
- JWT Authentication: Access and refresh token system
- Password Security: bcrypt hashing with salt rounds
- Rate Limiting: API Gateway rate limiting per IP/user
- Input Validation: class-validator for request validation
- SQL Injection Protection: TypeORM parameterized queries
- OTP Security: Redis-based with expiry and attempt limits
- CORS Protection: Configurable allowed origins
- Service Isolation: Each service has its own database
- Event Security: RabbitMQ authentication and authorization
- Health Monitoring: Comprehensive service health checks
- Global Exception Filters: Consistent error responses across all services
- Custom Error Messages: Business logic validation with clear messages
- HTTP Status Codes: Proper status codes for different error types
- Request/Response Logging: Comprehensive logging for debugging
- Saga Compensation: Automatic rollback for failed distributed transactions
- Circuit Breaker Pattern: Service failure isolation and recovery
- Retry Mechanisms: Automatic retry for transient failures
- Health Checks: Service availability monitoring
# Start infrastructure services only
docker-compose up -d auth-postgres users-postgres tuition-postgres payment-postgres redis rabbitmq
# Install dependencies for specific service
cd services/auth-service
npm install
# Run service in development mode
npm run start:dev# View service logs
docker-compose logs -f
# Check service health
curl http://localhost:4000/health
# Access RabbitMQ management
open http://localhost:15672