A mock credit card payment processing application built with Java 11, Spring Boot, and React.
-
REST API Endpoints:
POST /api/payments/authorize- Authorize a card transactionPOST /api/payments/capture- Capture an authorized transactionPOST /api/payments/refund- Refund a captured transactionGET /api/payments/{id}- Get transaction statusGET /api/payments/history- List recent transactions (last 20)POST /admin/cache/clear- Clear local cacheGET /actuator/health- Health check endpointGET /actuator/prometheus- Prometheus metrics
-
Technology Stack:
- In-memory H2 database
- Caffeine cache for transaction lookups
- Realistic processing delays (200-500ms)
- Random transaction declines (10% probability)
- Realistic response codes (approved, declined, insufficient funds, expired card)
- Payment form with card number, expiry, CVV, and amount fields
- Transaction history dashboard
- Status badges: Authorized (yellow), Captured (green), Declined (red), Refunded (gray)
- Capture and refund actions directly from the UI
- Visa:
4263970000005262 - MasterCard:
5425230000004415 - Amex:
374101000000608
Use any future expiry date (e.g., 12/25) and any 3-4 digit CVV.
- Java 11
- Maven 3.6+
cd payment-app-java11
mvn spring-boot:runThe application will start on http://localhost:8081
Open your browser and navigate to http://localhost:8081 to access the payment form.
curl -X POST http://localhost:8081/api/payments/authorize \
-H "Content-Type: application/json" \
-d '{
"cardNumber": "4263970000005262",
"cardExpiry": "12/25",
"cvv": "123",
"amount": 100.00
}'curl -X POST http://localhost:8081/api/payments/capture \
-H "Content-Type: application/json" \
-d '{"transactionId": 1}'curl -X POST http://localhost:8081/api/payments/refund \
-H "Content-Type: application/json" \
-d '{"transactionId": 1}'curl http://localhost:8081/api/payments/1curl http://localhost:8081/api/payments/historycurl -X POST http://localhost:8081/admin/cache/clearcurl http://localhost:8081/actuator/healthcurl http://localhost:8081/actuator/prometheusdocker build -t payment-app:latest .docker run -p 8081:8081 payment-app:latestThe application includes OpenShift deployment manifests with placeholder values.
${NAMESPACE}- Target namespace (e.g.,bob-demo-stagingorbob-demo-prod)${IMAGE_TAG}- Git SHA or version tag
# Set environment variables
export NAMESPACE=bob-demo-staging
export IMAGE_TAG=abc123def
# Replace placeholders and apply
envsubst < k8s/deployment.yaml | oc apply -f -The deployment uses the internal OpenShift image registry:
image-registry.openshift-image-registry.svc:5000/${NAMESPACE}/payment-app:${IMAGE_TAG}
At deploy time:
${NAMESPACE}→bob-demo-staging(orbob-demo-prod)${IMAGE_TAG}→ Git SHA
The CI job pushes images via the external registry route.
- 3 replicas with horizontal pod autoscaling (3-10 pods)
- Resource limits: 1Gi memory, 1 CPU
- Readiness and liveness probes
- PodDisruptionBudget (max 1 unavailable)
- TLS-enabled Route
- Non-root security context
- ServiceAccount with minimal RBAC
payment-app-java11/
├── src/
│ └── main/
│ ├── java/com/demo/payment/
│ │ ├── controller/ # REST controllers
│ │ │ ├── PaymentController.java
│ │ │ └── AdminController.java
│ │ ├── service/ # Business logic
│ │ │ └── PaymentService.java
│ │ ├── model/ # Entities and DTOs
│ │ │ ├── Transaction.java
│ │ │ ├── TransactionStatus.java
│ │ │ ├── TransactionType.java
│ │ │ ├── TransactionRepository.java
│ │ │ ├── PaymentRequest.java
│ │ │ └── PaymentResponse.java
│ │ ├── config/ # Configuration
│ │ │ └── CacheConfig.java
│ │ └── PaymentApplication.java
│ └── resources/
│ ├── static/ # React frontend
│ │ └── index.html
│ └── application.properties
├── pom.xml
├── Dockerfile
├── k8s/
│ └── deployment.yaml # OpenShift manifests
└── README.md
-
Authorize: Reserve funds on the card
- Status:
AUTHORIZED - Can be captured or will expire
- Status:
-
Capture: Settle the authorized transaction
- Status:
CAPTURED - Funds are transferred
- Can be refunded
- Status:
-
Refund: Return funds to the cardholder
- Status:
REFUNDED - Final state
- Status:
APPROVED- Transaction successfulDECLINED- Transaction declined by issuerINVALID_CARD- Invalid card numberEXPIRED_CARD- Card has expiredINSUFFICIENT_FUNDS- Amount exceeds limit (>$10,000)
curl http://localhost:8081/actuator/healthResponse:
{
"status": "UP",
"components": {
"db": {"status": "UP"},
"diskSpace": {"status": "UP"},
"ping": {"status": "UP"}
}
}Prometheus metrics are available at /actuator/prometheus for monitoring:
- JVM metrics
- HTTP request metrics
- Cache statistics
- Custom application metrics
mvn clean packagemvn testmvn spring-boot:run- This is a demo application for testing and development purposes only
- Uses in-memory H2 database (data is lost on restart)
- Simulates realistic payment processing delays and random declines
- Not suitable for production use without significant enhancements
- No actual payment processing or external API calls
This is a demo application for educational purposes.