A production-ready, microservices-based payment processing system featuring double-entry bookkeeping, idempotent transactions, and extensible payment gateway integrations.
Features β’ Architecture β’ Quick Start β’ API Reference β’ Documentation β’ Contributing
|
|
|
|
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLIENT APPLICATIONS β
β (Web Apps, Mobile Apps, Third-party Services) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API GATEWAY β
β (Authentication, Rate Limiting) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββ
βΌ βΌ βΌ
βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββ
β PAYMENT SERVICE β β LEDGER SERVICE β β GATEWAY PROVIDER β
β (/payment) β β (/ledger) β β (/gatewayProvider) β
βββββββββββββββββββββββ€ βββββββββββββββββββββββ€ βββββββββββββββββββββββ€
β β’ Payment Orders β β β’ Account Mgmt β β β’ Provider Config β
β β’ Line Items β β β’ Transactions β β β’ Payment Execution β
β β’ Status Tracking β β β’ Balance Calc β β β’ Webhook Handling β
β β’ Expiry Jobs β β β’ Audit Trail β β β’ Token Refresh β
βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββ
β β β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββ
βΌ βΌ βΌ
βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββ
β EVENT PROCESSOR β β REQUEST IDEMPOTENCY β β SHARED COMMONS β
βββββββββββββββββββββββ€ βββββββββββββββββββββββ€ βββββββββββββββββββββββ€
β β’ Async Processing β β β’ Duplicate Detect β β β’ DTOs & Models β
β β’ Retry Logic β β β’ Request Mapping β β β’ Utilities β
β β’ Status Updates β β β’ Response Cache β β β’ Exception Handlingβ
βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MYSQL DATABASE β
β (Liquibase Migrations, Optimistic Locking) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββ
β ayushmaanbhav β
β -commons β
ββββββββββ¬ββββββββββ
β
βββββββββββββββββββββΌββββββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β commons-spring β β client β β database β
ββββββββββ¬ββββββββββ ββββββββββ¬ββββββββββ ββββββββββββββββββββ
β β
βββββββββββββββΌββββββββββββββ¬βββββββ΄βββββββ¬ββββββββββββββ
βΌ βΌ βΌ βΌ βΌ
ββββββββββββββ ββββββββββββββ ββββββββββββββ ββββββββββββββ ββββββββββββββ
β payment β β ledger β β gateway β β event β β request β
β β β β β provider β β processor β β idempotencyβ
ββββββββββββββ ββββββββββββββ βββββββ¬βββββββ ββββββββββββββ ββββββββββββββ
β
βββββββ΄ββββββ
βΌ βΌ
βββββββββββββ βββββββββββββ
β gw-common β β gw-setu β
βββββββββββββ βββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PAYMENT DOMAIN β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β PAYMENT_ORDER β β PAYMENT_ORDER_LINE_ITEM β β
β βββββββββββββββββββββββ€ βββββββββββββββββββββββββββββββββββ€ β
β β PK id βββββββββββ€ FK payment_order_id β β
β β external_id (UK) β 1:N β PK id β β
β β customer_id β β external_id (UK) β β
β β store_id β β normalised_amount β β
β β source β β currency β β
β β source_service β β status β β
β β status β β ledger_debit_account_id β β
β β type β β ledger_credit_account_id β β
β β version β β FK gateway_provider_config_id β β
β β created_on β β FK gateway_provider_payment_id β β
β β updated_on β β paid_date β β
β βββββββββββββββββββββββ β expired_date β β
β βββββββββββββββββββββββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β GATEWAY_PROVIDER_CONFIG β β GATEWAY_PROVIDER_PAYMENT_DETAILβ β
β βββββββββββββββββββββββββββββββ€ βββββββββββββββββββββββββββββββββββ€ β
β β PK id β β PK id β β
β β external_id (UK) β β order_id (IDX) β β
β β provider β β provider_order_id (IDX) β β
β β merchant_id β β type β β
β β FK connection_setting_id β β provider_status β β
β β disabled β β payment_web_url β β
β β disabled_reason β β payment_deep_link β β
β β disabled_date β β provider_transaction_id β β
β ββββββββββββββββ¬βββββββββββββββ β provider_session_id β β
β β β provider_payment_method β β
β β β provider_paid_date β β
β βΌ β provider_error_code β β
β βββββββββββββββββββββββββββββββ β provider_error_description β β
β β GATEWAY_CONNECTION_SETTING β βββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββββββββββ€ β
β β PK id β βββββββββββββββββββββββββββββββββββ β
β β external_id (UK) β β GATEWAY_PROVIDER_EVENT β β
β β provider β βββββββββββββββββββββββββββββββββββ€ β
β β connection_setting β β PK id β β
β β token_refresh_enabled β β order_id β β
β β retry_count β β api_client_class β β
β β last_token_refresh_date β β event_type β β
β βββββββββββββββββββββββββββββββ β http_method / http_status β β
β β request / response β β
β β headers / query_params β β
β βββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LEDGER DOMAIN β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββββββββ β
β β LEDGER_ACCOUNT β βββββββββββββββββββββββββββββββββββ β
β βββββββββββββββββββββββ€ β LEDGER_TRANSACTION β β
β β PK id β βββββββββββββββββββββββββββββββββββ€ β
β β external_id (UK) β β PK id β β
β β request_id (UK) β β transaction_ref_id (UK) β β
β β currency β β transaction_date β β
β β type (DEBIT/ β β version β β
β β CREDIT) β β created_on β β
β β version β β updated_on β β
β β created_on β ββββββββββββββββ¬βββββββββββββββββββ β
β β updated_on β β β
β ββββββββββββ¬βββββββββββ β 1:N β
β β βΌ β
β β βββββββββββββββββββββββββββββββββββββββββββ β
β β β LEDGER_TRANSACTION_LINE_ITEM β β
β β βββββββββββββββββββββββββββββββββββββββββββ€ β
β β β PK id β β
β ββββββββββββββββ€ FK account_id β β
β N:1 β FK transaction_id β β
β β normalised_amount β β
β β currency β β
β β operation_type (DEBIT/CREDIT) β β
β β transfer_entity_type β β
β β version β β
β β created_on β β
β β updated_on β β
β βββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Java 11 or higher
- Maven 3.6+
- MySQL 8.0+
- Docker (optional, for containerized setup)
# Clone the repository
git clone https://github.com/ayushmaanbhav/Payments-Management-System.git
cd Payments-Management-System
# Build all modules
mvn clean install
# Run database migrations
mvn -pl ayushmaanbhav-database spring-boot:run
# Start the payment service
mvn -pl ayushmaanbhav-payment spring-boot:run
# Start the ledger service (in another terminal)
mvn -pl ayushmaanbhav-ledger spring-boot:run
# Start the gateway provider service (in another terminal)
mvn -pl ayushmaanbhav-gateway-provider spring-boot:runCreate application-local.properties in each service module:
# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/payments_db
spring.datasource.username=your_username
spring.datasource.password=your_password
# JPA Configuration
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false
# Service Configuration
server.port=8080version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: payments_db
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
payment-service:
build: ./ayushmaanbhav-payment
ports:
- "8081:8080"
depends_on:
- mysql
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/payments_db
ledger-service:
build: ./ayushmaanbhav-ledger
ports:
- "8082:8080"
depends_on:
- mysql
gateway-provider:
build: ./ayushmaanbhav-gateway-provider
ports:
- "8083:8080"
depends_on:
- mysql
volumes:
mysql_data:POST /payment/order Create Payment Order
{
"customerId": "cust_123",
"storeId": "store_456",
"externalId": "order_789",
"source": "WEB",
"sourceService": "CHECKOUT",
"type": "CUSTOMER_ORDER_CHECKOUT_ONE_TIME_PAYMENT",
"lineItems": [
{
"externalId": "item_001",
"amount": 10000,
"currency": "INR",
"ledgerDebitAccountId": "acc_debit_123",
"ledgerCreditAccountId": "acc_credit_456",
"gatewayProviderConfigId": "gw_config_789"
}
]
}{
"success": true,
"data": {
"orderId": "pay_order_abc123",
"status": "PENDING",
"paymentUrl": "https://payment.gateway.com/pay/xyz",
"paymentDeepLink": "upi://pay?pa=merchant@upi",
"expiresAt": "2024-01-15T10:30:00Z"
}
}GET /payment/order Get Payment Order
| Parameter | Type | Description |
|---|---|---|
orderId |
string |
Required. Order ID |
{
"success": true,
"data": {
"orderId": "pay_order_abc123",
"customerId": "cust_123",
"status": "SUCCESS",
"lineItems": [
{
"externalId": "item_001",
"amount": 10000,
"currency": "INR",
"status": "PAID",
"paidDate": "2024-01-15T10:25:00Z"
}
]
}
}POST /account Create Account
{
"externalId": "acc_merchant_001",
"requestId": "req_unique_123",
"currency": "INR",
"type": "CREDIT"
}{
"success": true,
"data": {
"accountId": "ledger_acc_xyz",
"externalId": "acc_merchant_001",
"currency": "INR",
"type": "CREDIT",
"balance": 0
}
}POST /transaction Record Transaction
{
"transactionRefId": "txn_ref_001",
"transactionDate": "2024-01-15T10:30:00Z",
"lineItems": [
{
"accountId": "ledger_acc_001",
"amount": 10000,
"currency": "INR",
"operationType": "DEBIT",
"transferEntityType": "PAYMENT"
},
{
"accountId": "ledger_acc_002",
"amount": 10000,
"currency": "INR",
"operationType": "CREDIT",
"transferEntityType": "PAYMENT"
}
]
}Note: Transaction line items must balance (total debits = total credits)
| Endpoint | Description |
|---|---|
GET /health |
Service health check |
GET /actuator/health |
Spring Actuator health |
GET /actuator/metrics |
Application metrics |
GET /actuator/info |
Application info |
# Run all tests
mvn test
# Run tests for a specific module
mvn -pl ayushmaanbhav-payment test
# Run tests with coverage
mvn test jacoco:report
# Run integration tests
mvn verify -P integration-tests| Module | Coverage |
|---|---|
| Payment Service | 85%+ |
| Ledger Service | 80%+ |
| Gateway Provider | 75%+ |
| Event Processor | 80%+ |
| Pattern | Implementation | Purpose |
|---|---|---|
| Factory | GatewayProviderPaymentApiClientFactory |
Dynamic provider client creation |
| Strategy | Gateway Provider implementations | Pluggable payment providers |
| Repository | JPA Repositories | Data access abstraction |
| DAO | AbstractDao |
Common database operations |
| Mapper | *Mapper classes |
DTO β Entity transformations |
| Builder | Lombok @Builder |
Immutable object construction |
- Idempotency: All payment operations are idempotent via
RequestIdempotencyService - Optimistic Locking: Version-based concurrency control on all entities
- Double-Entry Validation: Ledger transactions must balance before persistence
- Audit Trail: Automatic
created_onandupdated_ontimestamps
- Encrypted Credentials: Gateway connection settings stored encrypted
- Input Validation: Bean validation on all API inputs
- SQL Injection Prevention: Parameterized queries via JPA
- Exception Sanitization: No stack traces in API responses
Payments-Management-System/
βββ ayushmaanbhav-commons/ # Shared utilities, DTOs, exceptions
βββ ayushmaanbhav-commons-spring/ # Spring-specific common components
βββ ayushmaanbhav-client/ # HTTP client abstractions
βββ ayushmaanbhav-database/ # Liquibase migrations
β βββ src/main/resources/
β βββ db/changelog/
β βββ migrations/ # SQL migration scripts
βββ ayushmaanbhav-payment/ # Payment order management
β βββ src/main/java/
β β βββ com/ayushmaanbhav/payment/
β β βββ controller/ # REST controllers
β β βββ service/ # Business logic
β β βββ repository/ # Data access
β β βββ entity/ # JPA entities
β β βββ mapper/ # Object mappers
β βββ src/test/ # Test suite
βββ ayushmaanbhav-ledger/ # Double-entry bookkeeping
βββ ayushmaanbhav-ledger-commons/ # Ledger API interfaces
βββ ayushmaanbhav-payment-common/ # Payment API interfaces
βββ ayushmaanbhav-gateway-provider/ # Payment gateway integration
βββ ayushmaanbhav-gateway-provider-common/ # Gateway abstractions
βββ ayushmaanbhav-gateway-provider-setu/ # SETU implementation
βββ ayushmaanbhav-event-processor/ # Async event handling
βββ ayushmaanbhav-request-idempotency/ # Idempotency management
βββ pom.xml # Parent Maven POM
ββββββββββββ βββββββββββββββ ββββββββββββββββ βββββββββββββ
β Client ββββββΆβ Payment ββββββΆβ Gateway ββββββΆβ External β
β β β Service β β Provider β β Gateway β
ββββββββββββ βββββββββββββββ ββββββββββββββββ βββββββββββββ
β β β
β Check β Create β
β Idempotency β Payment β
βΌ βΌ β
βββββββββββββββ ββββββββββββββββ β
β Idempotency β β Provider β β
β Service β β (SETU) β β
βββββββββββββββ ββββββββββββββββ β
β β
βββββββββββββββββββββ
β Webhook Callback
βΌ
βββββββββββββββ ββββββββββββββββ
β Ledger ββββββββ Event β
β Service β β Processor β
βββββββββββββββ ββββββββββββββββ
β
β Record Transaction
βΌ
βββββββββββββββ
β MySQL β
β (Ledger) β
βββββββββββββββ
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Google Java Style Guide
- Write unit tests for all new features
- Update documentation for API changes
- Ensure all tests pass before submitting PR
This project is licensed under the MIT License - see the LICENSE file for details.
- Spring Boot - Application framework
- Liquibase - Database version control
- Lombok - Boilerplate reduction
- SETU - Payment gateway integration
- Documentation: Wiki
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with β€οΈ by Ayushmaanbhav