A simulated payment API designed to replicate real-world payment systems (e.g., IremboPay, Stripe, or mobile money APIs)
PaymentLater is a developer-friendly mock payment API that eliminates the barriers developers face when integrating payment systems into their projects. Built with Kotlin and Spring Boot, it provides comprehensive RESTful endpoints that simulate real-world payment provider behavior without the overhead of legal documentation, sandbox registration, or compliance requirements.
Perfect for prototyping, testing, learning, and building demos without the complexity of real payment integrations.
Most developers face common barriers when building payment-enabled applications:
- Complex registration processes requiring business documentation
- Lengthy approval workflows with government-issued documents
- Complicated sandbox environments with usage limitations
- Legal terms and compliance requirements for simple prototypes
PaymentLater solves these problems by providing:
- β Instant access - No paperwork or registration required
- β Simple integration - Standard RESTful API design
- β Real-world simulation - Webhooks, wallets, and transaction flows
- β Developer-focused - Built for learning and rapid prototyping
| Feature | Description |
|---|---|
| π Dual Authentication | JWT tokens for admins, API keys for merchants |
| π³ Payment Processing | Complete payment lifecycle simulation |
| π Webhook Support | Real-time event notifications |
| π° Multi-Currency | Support for multiple currency types |
| π Analytics Dashboard | Merchant and system analytics |
| β»οΈ Refund Management | Full refund processing workflow |
| π Transaction History | Comprehensive transaction tracking |
| π§ Email Notifications | Automated email alerts and confirmations |
| π Interactive API Docs | Swagger UI for easy testing |
| π‘οΈ Security Features | BCrypt hashing, JWT tokens, API key authentication |
- Backend: Kotlin + Spring Boot 3.5.3
- Database: MongoDB with auto-indexing
- Security: Spring Security with JWT & API Key authentication
- Documentation: OpenAPI 3 with Swagger UI
- Email: Spring Mail with SMTP integration
- Testing: JUnit 5, MockK, Spring Boot Test
src/main/kotlin/com/blaise/paymentlater/
βββ config/ # Application configurations
βββ controller/ # REST API controllers
βββ domain/ # Domain models and entities
β βββ enum/ # Enumerations
β βββ exception/ # Custom exceptions
β βββ extension/ # Kotlin extensions
β βββ model/ # Data models
βββ dto/ # Data Transfer Objects
β βββ request/ # Request DTOs
β βββ response/ # Response DTOs
βββ repository/ # MongoDB repositories
βββ security/ # Security configurations & filters
β βββ admin/ # Admin authentication
β βββ merchant/ # Merchant authentication
β βββ shared/ # Shared security components
βββ service/ # Business logic services
βββ v1/ # API version 1 services
- Java 21+
- MongoDB 4.4+
- SMTP Email Server (Gmail recommended)
-
Clone the repository
git clone https://github.com/yourusername/PaymentLaterAPI.git cd PaymentLaterAPI -
Set up environment variables
export MONGODB_URI="mongodb://localhost:27017" export MONGODB_DATABASE="paymentlater" export JWT_SECRET_BASE64="your-base64-encoded-jwt-secret" export MAIL_SERVER_EMAIL="your-email@gmail.com" export MAIL_SERVER_PASSWORD="your-app-password"
-
Run the application
./gradlew bootRun
-
Access the API
- API Base URL:
http://localhost:1010 - Swagger UI:
http://localhost:1010/swagger-ui.html - API Documentation:
http://localhost:1010/api-docs
- API Base URL:
# Register Admin
POST /api/v1/admin/auth/register
Content-Type: application/json
{
"username": "admin",
"email": "admin@example.com",
"password": "securepassword"
}
# Login
POST /api/v1/admin/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "securepassword"
}# Register Merchant
POST /api/v1/merchant/auth/register
Content-Type: application/json
{
"name": "My Business",
"email": "merchant@example.com",
"webhookUrl": "https://mybusiness.com/webhook"
}
# Use API Key in requests
GET /api/v1/merchant/auth/me
X-API-KEY: your-64-character-api-keyPOST /api/v1/payments
X-API-KEY: your-api-key
Content-Type: application/json
{
"items": [
{
"name": "Electricity & Water",
"description": "Monthly bills",
"unitAmount": 20,
"quantity": 2
}
],
"currency": "EUR",
"metadata": {
"referenceId": "123XXX",
"userId": "123",
"phone": "949784925244606",
"email": "customer@example.com",
"description": "Paying for bills"
}
}POST /api/v1/payments/{paymentIntentId}/confirm
X-API-KEY: your-api-key
Content-Type: application/json
{
"paymentMethod": "MOBILE_MONEY",
"metadata": {
"customerEmail": "alice@example.com",
"customerPhone": "+250788123456",
"customerName": "Alice Johnson",
"referenceId": "REF-1001",
"description": "Payment for order #1024",
"failureReason": null,
"refundReason": null,
"gatewayResponseCode": "00",
"extra": {
"network": "MTN Rwanda",
"transactionId": "MTN-TXN-78901",
"paymentSession": "SESSION-ABC123"
}
}
}POST /api/v1/merchant/auth/set-webhook
X-API-KEY: your-api-key
Content-Type: application/json
{
"webhookUrl": "https://mybusiness.com/webhook1"
}// Add to your build.gradle.kts
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
}
// API Client
interface PaymentLaterApiService {
@POST("payments")
suspend fun createPaymentIntent(
@Header("X-API-KEY") apiKey: String,
@Body request: PaymentIntentRequest
): PaymentIntentResponse
}
// Usage
class PaymentRepository {
private val api = // ... retrofit instance
suspend fun processPayment(amount: Long): PaymentIntentResponse {
val metadata = mapOf<String, Any>(...)
val items = listOf<Map<String, Any>>(...)
return api.createPaymentIntent(
apiKey = "your-api-key",
request = PaymentIntentRequest(
items = items,
metadata = metadata,
currency = "RWF"
)
)
}
}// Payment service
class PaymentLaterService {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'http://localhost:1010/api/v1';
}
async createPaymentIntent(paymentData) {
const response = await fetch(`${this.baseUrl}/payments/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': this.apiKey
},
body: JSON.stringify(paymentData)
});
return response.json();
}
}
// React component
function CheckoutForm() {
const paymentService = new PaymentLaterService('your-api-key');
const handlePayment = async (amount) => {
const metadata = {...}
const items = [...]
const intent = await paymentService.createPaymentIntent({
items: items,
metadata: metadata,
currency: 'RWF'
});
// Handle payment confirmation
console.log('Payment Intent:', intent);
};
}- Prototype e-commerce checkout flows
- Test payment integration in development
- Demo payment features to stakeholders
- University assignments requiring payment features
- Bootcamp projects demonstrating full-stack skills
- Teaching payment system architecture
- Quick payment integration for hackathon projects
- MVP development without payment provider delays
- Proof of concept demonstrations
- Frontend payment flow testing
- API integration testing
- Webhook handling development
GET /actuator/healthGET /api/v1/admin/analytics/system-health
Authorization: Bearer jwt-tokenGET /api/v1/merchant/analytics/overview
X-API-KEY: your-api-key- JWT Authentication with 15-hour access tokens and 30-day refresh tokens
- API Key Authentication with SHA-256 hashing
- BCrypt Password Hashing for admin accounts
- Role-Based Access Control (RBAC)
- Request Rate Limiting (planned)
- HTTPS Support (configure with SSL certificates)
# Run all tests
./gradlew test
# Run with coverage
./gradlew test jacocoTestReport
We welcome contributions from developers who want to:
- π§ Add new features or endpoints
- π± Build SDKs for other platforms (JavaScript, Flutter, Python)
- π Improve documentation and examples
- π§ͺ Write tests and improve code quality
- π Fix bugs and performance issues
- π‘ Suggest new use cases and improvements
- Fork the repository
- Create a feature branch (
git checkout -b fea/amazing-feature) - Follow coding standards (Kotlin conventions, comprehensive documentation)
- Add tests for new functionality
- Update documentation as needed
- Commit changes (
git commit -m 'fea(amazing-feature): Add amazing feature') - Push to branch (
git push origin fea/amazing-feature) - Open a Pull Request
# Clone your fork
git clone https://github.com/yourusername/PaymentLaterAPI.git
# Add upstream remote
git remote add upstream https://github.com/original/PaymentLaterAPI.git
# Create development branch
git checkout -b develop
# Install dependencies and run
./gradlew bootRun- Core REST API implementation
- JWT and API Key authentication
- Payment intent and confirmation flow
- Webhook system
- Email notifications
- MongoDB integration
- Comprehensive documentation
- Swagger UI integration
- Kotlin SDK
- Enhanced analytics and reporting
- Rate limiting and throttling
- Comprehensive testing suite
- SDK Development
- Kotlin/Android SDK
- JavaScript/TypeScript SDK
- Flutter/Dart SDK
- Python SDK
- Additional Features
- Subscription billing simulation
- Wallet Integration
- Multi-tenant support
- Payment method expansion
- Advanced fraud detection simulation
- DevOps & Deployment
- Docker containerization
- Kubernetes deployment configs
- CI/CD pipeline setup
- Monitoring and observability
- π« Not for Production: This is a mock service for testing and development only
- π° No Real Money: All transactions are simulated - no actual funds are processed
- π Educational Security: Security implementations are practical but not enterprise-grade
- π No Legal Compliance: Not intended for PCI-DSS, AML, or KYC compliance
This project is licensed under the MIT License - see the LICENSE file for details.
- Spring Boot Team for the excellent framework
- Kotlin Team for the amazing language
- MongoDB for reliable data persistence
- OpenAPI Initiative for standardized API documentation
- Contributors who make this project better
- π§ Email: blaiseendizeye@gmail.com
- π Issues: GitHub Issues
β If you find PaymentLater API helpful, please star this repository to support the project!