Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PayFlow

A production-grade Payment Processing Backend built with Java 21 and Spring Boot 3. Implements core financial system concepts - atomic transfers, fraud detection, double-entry ledger, and daily reconciliation.

Java Spring Boot MySQL Docker JWT Swagger


What is PayFlow?

Most payment systems fail under three conditions - concurrent requests, duplicate submissions, and fraudulent patterns. PayFlow handles all three through a strict, auditable pipeline.


Payment Pipeline

Incoming Request
      │
      ▼
┌─────────────────┐
│   JWT Auth      │──── Invalid Token ──── 401 Unauthorized
└────────┬────────┘
         │
         ▼
┌─────────────────────┐
│  Idempotency Check  │──── Already Processed ──── Return Same Response
└────────┬────────────┘
         │
         ▼
┌──────────────────────┐
│  Pessimistic Lock    │──── Row-level DB lock acquired
└────────┬─────────────┘
         │
         ▼
┌──────────────────────┐
│  Fraud Detection     │──── Rule Triggered ──── BLOCKED + Alert Saved
└────────┬─────────────┘
         │
         ▼
┌──────────────────────┐
│  Balance Check       │──── Insufficient ──── FAILED + Record Saved
└────────┬─────────────┘
         │
         ▼
┌──────────────────────┐
│  Atomic Debit+Credit │
└────────┬─────────────┘
         │
         ▼
┌──────────────────────┐
│  Double Entry Ledger │──── DEBIT entry + CREDIT entry saved
└────────┬─────────────┘
         │
         ▼
      Response

Core Features

1. Authentication and Account System

  • Stateless JWT authentication - no session, no state
  • BCrypt password encoding
  • Automatic SAVINGS account creation on registration - same @Transactional boundary as user creation
  • Account status management - ACTIVE, SUSPENDED, CLOSED

2. Payment Engine

  • Atomic transfers - debit and credit in one database transaction. Server crash mid-transfer rolls back everything
  • Pessimistic locking - SELECT ... FOR UPDATE before any balance change. Two concurrent requests are serialized
  • Idempotency - same idempotencyKey sent twice returns the same response. Implemented via MySQL unique constraint, no Redis needed
  • Failed payments are recorded, not discarded - full failure reason stored

3. Fraud Detection Rules Engine

  • Rules live in the database, not in code
  • AMOUNT_THRESHOLD - block transactions above a configured amount
  • FREQUENCY_LIMIT - block if N+ transactions in M minutes from same account
  • Add a new rule via POST request - zero code change, zero redeployment
  • Every blocked transaction creates a FraudAlert record

4. Double Entry Ledger

  • Every successful payment creates exactly two ledger entries - DEBIT and CREDIT
  • balanceAfter tracked on every entry
  • Point-in-time balance query - reconstruct balance at any historical date
  • Same accounting principle used in every bank globally

5. Reconciliation Engine

  • Scheduled daily at midnight via @Scheduled(cron = "0 0 0 * * *")
  • Verifies Total DEBIT == Total CREDIT across all ledger entries
  • Logs ERROR on mismatch - ready to connect to any alerting system
  • Every run saved as ReconciliationReport - permanent audit history
  • Manual trigger API available for testing

API Reference

Auth

Method Endpoint Auth Description
POST /api/auth/register No Register new user
POST /api/auth/login No Login, receive JWT

Accounts

Method Endpoint Auth Description
GET /api/accounts/my Yes Get own accounts

Payments

Method Endpoint Auth Description
POST /api/payments/transfer Yes Transfer money
GET /api/payments/history/{accountNumber} Yes Transaction history

Fraud Rules

Method Endpoint Auth Description
POST /api/fraud-rules Yes Create rule
GET /api/fraud-rules Yes List all rules
PUT /api/fraud-rules/{id}/deactivate Yes Deactivate rule

Ledger

Method Endpoint Auth Description
GET /api/ledger/{accountNumber} Yes Full ledger history
GET /api/ledger/{accountNumber}/balance-as-of Yes Point-in-time balance

Reconciliation

Method Endpoint Auth Description
POST /api/reconciliation/run Yes Trigger manually
GET /api/reconciliation/reports Yes All reports
GET /api/reconciliation/reports/mismatches Yes Mismatch reports only

Running Locally

Prerequisites: Docker Desktop installed

git clone https://github.com/ArpanC6/payflow.git
cd payflow
mvn clean package -DskipTests
docker-compose up --build
URL
Application http://localhost:8081
Swagger UI http://localhost:8081/swagger-ui.html

Key Engineering Decisions

Decision Reasoning
BigDecimal over double Floating point loses precision - 0.1 + 0.2 != 0.3 in Java. BigDecimal is exact
Pessimistic over optimistic locking Payment systems cannot retry on conflict - money must not be debited twice
Idempotency via MySQL, not Redis Same correctness guarantee, one less dependency
DB-driven fraud rules New rule = one API call. No code change, no redeploy, no downtime
Double-entry accounting Fundamental invariant: debits always equal credits. Violations caught daily
Immutable transaction log Never updated or deleted. Audit trail is permanent and tamper-proof

Project Structure

src/main/java/com/arpan/payflow/
├── config/         Security configuration
├── controller/     REST endpoints
├── dto/            Request and response objects
├── entity/         JPA entities
├── exception/      Global exception handler
├── job/            Scheduled reconciliation job
├── repository/     Database queries
├── security/       JWT filter and utility
└── service/        Business logic

Testing

Unit tests written with JUnit 5 and Mockito, covering critical business logic in isolation.

Test Class Coverage
PaymentServiceTest Successful transfer, insufficient balance, idempotent duplicate requests, fraud-blocked transactions, same-account transfer rejection, inactive account rejection
FraudDetectionServiceTest Amount threshold triggering, frequency limit triggering, transactions within limits, no active rules scenario
ReconciliationServiceTest Balanced ledger detection, mismatch detection, null-safe handling of empty ledger

Run tests:

mvn test

Entities

Entity Purpose
User Registered user with KYC status
Account Bank account linked to user
Transaction Payment record with idempotency key
FraudRule Configurable fraud detection rule
FraudAlert Alert created when a rule is triggered
LedgerEntry Individual debit or credit entry
ReconciliationReport Daily reconciliation run result

About

Production-grade payment processing backend - JWT auth, atomic transfers, fraud detection, double-entry ledger, reconciliation job. Built with Java 21 + Spring Boot 3 + MySQL + Docker.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages