A comprehensive Spring Boot REST API for financial transaction management with role-based access control, risk scoring, and automated payment approval workflows.
- User Authentication & Authorization: JWT-based authentication with role-based access control (USER, CHECKER, ADMIN)
- Account Management: Multi-currency account support (USD, CAD, EUR)
- Payment Processing: Internal and external transfers with automatic currency conversion
- Risk Scoring: Automatic risk calculation for payments with auto-approval for low-risk transactions
- Checker Workflow: Approval queue for checkers with risk-based prioritization
- Exchange Rates: Support for international transfers with automatic currency conversion
- n8n Integration: Webhook notifications for payment approvals
- Java 17 - Programming language
- Spring Boot 3.2.0 - Framework
- Maven - Build tool and dependency management
- PostgreSQL 15 - Database
- Docker & Docker Compose - Database containerization
- Spring Web - REST API endpoints
- Spring Data JPA - Database persistence
- Spring Security - Authentication and authorization
- JJWT 0.12.3 - JWT token generation and validation
- BCrypt - Password hashing
- Lombok - Code simplification
- Hibernate - ORM framework
- Java 17 or higher
- Docker Desktop (for PostgreSQL)
- Maven (or use Maven wrapper
mvnw.cmd)
Using Docker (Recommended):
-
Start Docker Desktop
-
Run:
docker-compose up -d
Or use the provided script:
.\start-postgres.ps1 -
Verify it's running:
docker ps
Database Credentials:
- Host:
localhost:5432 - Database:
transactiq_db - Username:
postgres - Password:
postgres
.\mvnw.cmd spring-boot:runWait for:
Tomcat started on port(s): 8080 (http)
Health Check:
curl http://localhost:8080/api/healthOr open in browser: http://localhost:8080/api/health
TransactIQ-backend/
βββ src/main/java/com/transactiq/backend/
β βββ config/ # Configuration classes
β β βββ CorsConfig.java # Global CORS configuration
β β βββ SecurityConfig.java # Spring Security & JWT setup
β β βββ RestTemplateConfig.java # RestTemplate bean
β β βββ ExchangeRateInitializer.java # Default exchange rates
β βββ controller/ # REST API endpoints
β β βββ AccountController.java # Account management APIs
β β βββ AuthController.java # Authentication APIs
β β βββ DashboardController.java # Dashboard data APIs
β β βββ PaymentController.java # Payment management APIs
β β βββ ExchangeRateController.java # Exchange rate APIs
β β βββ CheckerDashboardController.java # Checker dashboard APIs
β β βββ AdminController.java # Admin panel APIs
β β βββ HealthController.java # Health check endpoint
β βββ entity/ # Database entities
β β βββ Account.java # Account entity
β β βββ Payment.java # Payment entity
β β βββ User.java # User entity with roles
β β βββ ExchangeRate.java # Exchange rate entity
β βββ repository/ # Data access layer
β β βββ AccountRepository.java
β β βββ PaymentRepository.java
β β βββ UserRepository.java
β β βββ ExchangeRateRepository.java
β βββ service/ # Business logic layer
β β βββ AccountService.java
β β βββ PaymentService.java
β β βββ ExchangeRateService.java
β β βββ RiskScoreService.java # Risk calculation
β β βββ N8nNotifier.java # n8n webhook integration
β βββ filter/ # Security filters
β β βββ JwtAuthenticationFilter.java
β βββ util/ # Utility classes
β β βββ JwtUtil.java # JWT operations
β β βββ RoleUtil.java # Role-based access helpers
β β βββ SecurityUtil.java # Security context helpers
β βββ TransactIqBackendApplication.java
βββ src/main/resources/
β βββ application.yml # Application configuration
βββ docker-compose.yml # PostgreSQL container setup
βββ init.sql # Database initialization
βββ pom.xml # Maven dependencies
βββ README.md
id(BIGINT, PRIMARY KEY)username(VARCHAR, UNIQUE, NOT NULL)email(VARCHAR, UNIQUE, NOT NULL)password(VARCHAR, NOT NULL) - BCrypt hashedfirst_name(VARCHAR)last_name(VARCHAR)role(VARCHAR/ENUM) -USER,CHECKER,ADMIN(default:USER)is_active(BOOLEAN, default: true)created_at(TIMESTAMP)
id(BIGINT, PRIMARY KEY)account_number(VARCHAR, UNIQUE, NOT NULL) - Auto-generatedaccount_type(VARCHAR, NOT NULL) -CHECKING,SAVINGS,BUSINESSbalance(DECIMAL, NOT NULL, default: 0.00)currency(VARCHAR(3), NOT NULL) -USD,CAD,EUR(default:USD)is_active(BOOLEAN, default: true)user_id(BIGINT, FOREIGN KEY β users.id)created_at(TIMESTAMP)
id(BIGINT, PRIMARY KEY)transaction_id(VARCHAR, UNIQUE, NOT NULL) - Auto-generatedamount(DECIMAL, NOT NULL, min: 0.01)currency(VARCHAR(3), NOT NULL) - From account currencyconverted_amount(DECIMAL) - Converted amount for different currencyconverted_currency(VARCHAR(3)) - To account currencyexchange_rate(DECIMAL(19, 6)) - Exchange rate usedstatus(VARCHAR) -PENDING,APPROVED,REJECTED,COMPLETEDtransfer_type(VARCHAR) -INTERNAL,EXTERNALrisk_score(DECIMAL(5,2)) - Risk score 0-100risk_level(VARCHAR) -LOW,MEDIUM,HIGH,VERY_HIGHauto_approved(BOOLEAN) - True if auto-approveddescription(VARCHAR)from_account_id(BIGINT, FOREIGN KEY β accounts.id)to_account_id(BIGINT, FOREIGN KEY β accounts.id)created_at(TIMESTAMP)approved_at(TIMESTAMP)approved_by(BIGINT, FOREIGN KEY β users.id)
id(BIGSERIAL, PRIMARY KEY)from_currency(VARCHAR(3), NOT NULL)to_currency(VARCHAR(3), NOT NULL)rate(DECIMAL(19, 6), NOT NULL)is_active(BOOLEAN, default: true)created_at(TIMESTAMP)updated_at(TIMESTAMP)- UNIQUE(from_currency, to_currency)
-
USER (Default)
- Create and view own accounts
- Create payments
- View own payment history
- Cannot approve/reject payments
-
CHECKER
- All USER permissions
- View approval queue
- View risk statistics
- Approve/reject payments
- Cannot manage users
-
ADMIN
- All CHECKER permissions
- Manage users (view, update roles)
- View all accounts
- System administration
All protected endpoints require a JWT token in the Authorization header:
Authorization: Bearer <token>
Register a new user.
Request:
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123"
}Response:
{
"id": 1,
"email": "john@example.com",
"username": "johndoe",
"role": "user",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Login with email and password.
Request:
{
"email": "john@example.com",
"password": "password123"
}Response:
{
"id": 1,
"email": "john@example.com",
"username": "johndoe",
"role": "user",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Get current authenticated user details.
Headers: Authorization: Bearer <token>
Get all accounts for the authenticated user.
Headers: Authorization: Bearer <token>
Response:
[
{
"id": 1,
"accountNumber": "ACC123456789",
"accountType": "CHECKING",
"balance": 5000.00,
"currency": "USD",
"isActive": true,
"createdAt": "2025-01-01T00:00:00"
}
]Create a new account.
Request:
{
"name": "Savings Account",
"type": "savings",
"currency": "USD",
"balance": 1000.00
}Search for external accounts (for external transfers).
Query Parameters:
q(required): Search query (minimum 3 characters)
Get all payments for the authenticated user (or all payments for CHECKER/ADMIN).
Headers: Authorization: Bearer <token>
Response:
[
{
"id": 1,
"transactionId": "TXN123456789",
"amount": 100.00,
"currency": "USD",
"status": "APPROVED",
"riskScore": 5.00,
"riskLevel": "LOW",
"autoApproved": true,
"transferType": "internal",
"fromAccount": { ... },
"toAccount": { ... },
"conversion": { ... },
"createdAt": "2025-01-01T00:00:00"
}
]Create a new payment.
Request:
{
"fromAccountId": 1,
"toAccountId": 2,
"amount": 100.00,
"currency": "USD",
"description": "Payment description",
"transferType": "internal"
}Response:
{
"id": 1,
"amount": 100.00,
"currency": "USD",
"status": "PENDING",
"riskScore": 5.00,
"riskLevel": "LOW",
"autoApproved": false,
"conversion": null
}Approve a payment (CHECKER/ADMIN only).
Headers: Authorization: Bearer <token>
Reject a payment (CHECKER/ADMIN only).
Headers: Authorization: Bearer <token>
Get dashboard data for the authenticated user.
Headers: Authorization: Bearer <token>
Response:
{
"totalBalance": 10000.00,
"recentTransactions": 10,
"activeAccounts": 2,
"pendingPayments": 3,
"approvedPayments": 7,
"currencyBalances": [
{
"currency": "USD",
"balance": 8000.00,
"percentage": 80.0
},
{
"currency": "CAD",
"balance": 2000.00,
"percentage": 20.0
}
]
}Get pending payments sorted by risk score.
Headers: Authorization: Bearer <token>
Get risk statistics.
Headers: Authorization: Bearer <token>
Get complete checker dashboard.
Headers: Authorization: Bearer <token>
Get all users.
Headers: Authorization: Bearer <token>
Update user role.
Request:
{
"role": "checker"
}Get admin dashboard.
Headers: Authorization: Bearer <token>
Get all active exchange rates.
Headers: Authorization: Bearer <token>
Convert amount between currencies.
Query Parameters:
amount(required): Amount to convertfromCurrency(required): Source currency codetoCurrency(required): Target currency code
Health check endpoint (no authentication required).
Response:
{
"status": "UP",
"timestamp": "2025-01-01T00:00:00"
}The system automatically calculates a risk score (0-100) for each payment based on:
- Amount Risk (0-30 points): Higher amounts = higher risk
- Currency Risk (0-20 points): International transfers = higher risk
- Transfer Type Risk (0-15 points): External transfers = higher risk
- Time Risk (0-10 points): Unusual hours (2 AM - 6 AM) = higher risk
- Balance Risk (0-15 points): Low remaining balance = higher risk
- History Risk (0-10 points): First-time recipients = higher risk
- LOW (0-30): Auto-approved if amount is small
- MEDIUM (31-60): Requires manual approval
- HIGH (61-80): Requires manual approval, priority review
- VERY_HIGH (81-100): Requires manual approval, urgent review
Payments are automatically approved if:
- Risk score β€ 20 AND amount β€ $10,000
- OR Risk score β€ 30 AND amount β€ $1,000
Examples:
- $10 payment β Risk: 0 β Auto-approved β
- $500 payment β Risk: 0 β Auto-approved β
- $10,000 international transfer β Risk: 40+ β PENDING (manual approval)
β οΈ
- USD (US Dollar)
- CAD (Canadian Dollar)
- EUR (Euro)
The system initializes with default exchange rates on startup:
- USD β CAD: 1.350000
- USD β EUR: 0.920000
- CAD β USD: 0.740741
- EUR β USD: 1.086957
When creating a payment between accounts with different currencies:
- System detects currency difference
- Looks up exchange rate from database
- Calculates converted amount
- Stores both original and converted amounts
- On approval, deducts original amount and adds converted amount
Example:
- Transfer $100 USD to CAD account
- Exchange Rate: 1 USD = 1.35 CAD
- Deducts: $100 USD
- Adds: $135 CAD
The system sends webhook notifications to n8n when payments are approved.
Webhook URL: https://ancjainil.app.n8n.cloud/webhook/webhook/payment_approved
Payload:
{
"transactionId": "TXN123456789",
"amount": 100.00,
"currency": "USD",
"approvedBy": "admin",
"approvedAt": "2025-01-01T00:00:00",
"toEmail": "recipient@example.com"
}Note: Auto-approved payments do not trigger n8n notifications.
spring:
datasource:
url: jdbc:postgresql://localhost:5432/transactiq_db
username: postgres
password: postgres
jpa:
hibernate:
ddl-auto: update
show-sql: false
security:
jwt:
secret: your-secret-key-here
expiration: 86400000 # 24 hours
server:
port: 8080
cors:
allowed-origins: http://localhost:5173The backend is configured to allow requests from:
- Origin:
http://localhost:5173(React frontend) - Methods: GET, POST, PUT, DELETE, OPTIONS
- Headers: Authorization, Content-Type
- Credentials: Supported
curl http://localhost:8080/api/healthcurl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"test@example.com","password":"password123"}'curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"password123"}'curl http://localhost:8080/api/accounts \
-H "Authorization: Bearer <token>"docker-compose up -ddocker-compose downdocker-compose logs postgresdocker-compose down -v- Check if another PostgreSQL instance is running
- Stop it or change port in
docker-compose.yml
- Make sure PostgreSQL is running
- Check Docker Desktop is started
- Verify database credentials in
application.yml
- Tokens expire after 24 hours
- Login again to get a new token
- Check risk score (should be β€ 30 for small amounts)
- Verify sufficient balance in from account
- Check payment status in database
You can override configuration using environment variables:
$env:DB_USERNAME="your_username"
$env:DB_PASSWORD="your_password"
$env:JWT_SECRET="your_secret_key"- Password Hashing: BCrypt with salt
- JWT Tokens: Secure token-based authentication
- Role-Based Access Control: USER, CHECKER, ADMIN roles
- CORS Protection: Configured for specific origins
- Input Validation: Request validation using Jakarta Validation
- SQL Injection Protection: JPA/Hibernate parameterized queries
- Spring Boot Documentation: https://spring.io/projects/spring-boot
- PostgreSQL Documentation: https://www.postgresql.org/docs/
- JWT Documentation: https://jwt.io/
- Create a feature branch
- Make your changes
- Test thoroughly
- Commit and push
- Create a pull request
This project is part of the TransactIQ application.
Built with β€οΈ using Spring Boot