Skip to content

ayushmaanbhav/Payments-Management-System

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ’³ Payments Management System

Enterprise-Grade Payment Processing & Double-Entry Ledger Platform

Java Spring Boot MySQL Maven License

Build Status Code Coverage CodeFactor Last Commit

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


🌟 Features

πŸ’° Payment Processing

  • Multi-gateway support with pluggable architecture
  • Real-time payment tracking and status updates
  • Webhook handling for async payment confirmations
  • Payment expiry management with scheduled jobs
  • Idempotent operations preventing duplicate charges

πŸ“’ Double-Entry Ledger

  • GAAP-compliant double-entry bookkeeping
  • Multi-currency support with normalized amounts
  • Balanced transactions with automatic validation
  • Complete audit trail for all financial operations
  • Account type enforcement (Debit/Credit)

πŸ”Œ Gateway Integrations

  • SETU Payment Gateway (UPI, Bank Transfers)
  • Extensible factory pattern for new providers
  • Token refresh management for OAuth providers
  • Connection settings encryption for security
  • API event logging for debugging & audits

⚑ Event Processing

  • Asynchronous event handling for scalability
  • Retry mechanisms with configurable policies
  • Event status tracking (Pending β†’ Completed)
  • Workflow orchestration for complex operations
  • Dead letter handling for failed events

πŸ— Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              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)               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Module Dependency Graph

                                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                    β”‚  ayushmaanbhav   β”‚
                                    β”‚    -commons      β”‚
                                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                             β”‚
                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                         β–Ό                   β–Ό                   β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  commons-spring  β”‚ β”‚     client       β”‚ β”‚    database      β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚                    β”‚
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β–Ό             β–Ό             β–Ό             β–Ό             β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  payment   β”‚ β”‚   ledger   β”‚ β”‚  gateway   β”‚ β”‚   event    β”‚ β”‚  request   β”‚
β”‚            β”‚ β”‚            β”‚ β”‚  provider  β”‚ β”‚ processor  β”‚ β”‚ idempotencyβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
                              β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”
                              β–Ό           β–Ό
                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                       β”‚ gw-common β”‚ β”‚  gw-setu  β”‚
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Š Data Model

Entity Relationship Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              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                           β”‚     β”‚
β”‚                            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸš€ Quick Start

Prerequisites

  • Java 11 or higher
  • Maven 3.6+
  • MySQL 8.0+
  • Docker (optional, for containerized setup)

Installation

# 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:run

Configuration

Create 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=8080

Docker Compose (Recommended)

version: '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:

πŸ“– API Reference

Payment Service (/payment)

POST /payment/order Create Payment Order
Request Body
{
  "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"
    }
  ]
}
Response
{
  "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
Query Parameters
Parameter Type Description
orderId string Required. Order ID
Response
{
  "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"
      }
    ]
  }
}

Ledger Service (/ledger)

POST /account Create Account
Request Body
{
  "externalId": "acc_merchant_001",
  "requestId": "req_unique_123",
  "currency": "INR",
  "type": "CREDIT"
}
Response
{
  "success": true,
  "data": {
    "accountId": "ledger_acc_xyz",
    "externalId": "acc_merchant_001",
    "currency": "INR",
    "type": "CREDIT",
    "balance": 0
  }
}
POST /transaction Record Transaction
Request Body
{
  "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)

Health & Monitoring

Endpoint Description
GET /health Service health check
GET /actuator/health Spring Actuator health
GET /actuator/metrics Application metrics
GET /actuator/info Application info

πŸ§ͺ Testing

# 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

Test Coverage

Module Coverage
Payment Service 85%+
Ledger Service 80%+
Gateway Provider 75%+
Event Processor 80%+

πŸ”§ Design Patterns & Best Practices

Patterns Implemented

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

Data Integrity

  • 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_on and updated_on timestamps

Security Measures

  • 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

πŸ“ Project Structure

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

πŸ”„ Payment Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  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)   β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Guidelines

  • Follow Google Java Style Guide
  • Write unit tests for all new features
  • Update documentation for API changes
  • Ensure all tests pass before submitting PR

πŸ“œ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

πŸ“ž Support


⬆ Back to Top

Made with ❀️ by Ayushmaanbhav