A robust backend solution for core banking operations, built using ASP.NET Core 8, C#, and PostgreSQL, while following the Clean Architecture principles. This project demonstrates a modular, maintainable, and secure backend system suitable for financial applications.
- Overview
- Project Screenshots
- Features
- Architecture
- Folder Structure
- Tech Stack
- Live Link
- Deployment (Render + CloudAMQP)
- Installation & Setup
- Database Setup
- API Documentation
- How to Simulate Deposit & Transfer Between Accounts
- Example Requests & Responses
- Validation & Security
- Contributing
- License
- Author
The Core Banking Solution simulates user account creation, fund transfers, deposits, withdrawals and transaction history with authentication and authorization using ASP.NET Core while following the Clean Architecture Pattern, Microservices and the Repository Pattern.
It demonstrates:
- Clean architecture separation: Domain, Application, Infrastructure, Presentation
- Secure authentication & authorization with ASP.NET Core Identity and JWT
- RESTful APIs
- Automated validation pipelines and error handling
- Customer Management: Register, update, and retrieve customer information
- Bank Accounts: Create and manage accounts per customer
- Transactions: Deposit, withdrawal, transfer, and transaction history
- Role-based Access Control: Admin and Customer roles
- Validation Pipeline: Ensures input validation and domain rules
- Security: Password hashing, JWT authentication, and claims-based authorization
- Logging & Auditing: Tracks critical actions for accountability
flowchart TB
A[Presentation Layer: API Controllers] --> B[Application Layer: Services & Use Cases]
B --> C[Domain Layer: Entities & Interfaces]
C --> D[Infrastructure Layer: EF Core, Identity, Repositories]
D --> E[PostgreSQL Database]
CoreBankingSolution/
│
├─ src/
│ ├─ CoreBanking.Domain/ # Entities, Interfaces, Value Objects
│ ├─ CoreBanking.DTO/ # DTOs
│ ├─ CoreBanking.Application/ # Services, Use Cases, CQRS
│ ├─ CoreBanking.Infrastructure/ # EF Core, Repositories, Identity
│ └─ CoreBanking.API/ # Controllers, Program.cs
│
├─ docker/ # Docker configurations
└─ README.md
• .NET Core (C#)
• Entity Framework Core
• PostgreSQL
• ASP.NET Identity
• JWT Authentication
• Clean Architecture
• Repository Pattern & Dependency Injection
• Command Query Responsibility Segregation (CQRS)
• Unit of Work & Database Transactions
• Brevo HTTPS API (free-forever email service, works on Render free tier)
• Live Link (Swagger Docs): https://core-banking-solution.onrender.com/swagger/index.html
The API runs on Render. appsettings.json is git-ignored (see .gitignore), so every setting must come from environment variables in the Render dashboard.
RabbitMQ is optional:
- No broker configured → the API still starts on the in-memory MassTransit transport, and
POST /api/customerrsfalls back to in-process registration (RegisterCommand→ Identity user + bank account), so registration never breaks. - Broker configured but temporarily unreachable → errors are logged, the API keeps serving traffic (it is no longer stopped by background-service failures; the bus also starts in the background via
WaitUntilStarted = false).
- Create a free Little Lemur instance at cloudamqp.com.
- Copy the instance's AMQP URL — for example
amqps://user:pass@host/vhost(theamqpsscheme enables TLS automatically).
Want RabbitMQ on Render instead? Deploy render-examples/rabbitmq in the same region, then use the internal service hostname:
RabbitMq__Host=<service-slug>,RabbitMq__Port=5672,RabbitMq__User,RabbitMq__Password,RabbitMq__VirtualHost=/.
| Variable | Example | Notes |
|---|---|---|
RabbitMq__Url |
amqps://user:pass@host/vhost |
Recommended (CloudAMQP) |
RabbitMq__Host / RabbitMq__Port |
my-broker-host / 5672 |
Alternative to RabbitMq__Url |
RabbitMq__User / RabbitMq__Password |
guest / guest |
Alternative to RabbitMq__Url |
RabbitMq__VirtualHost |
/ |
Alternative to RabbitMq__Url |
RabbitMq__Enabled |
false |
Disables broker integration entirely |
RabbitMq__Queue / RabbitMq__Exchange / RabbitMq__RoutingKey |
registration.queue / corebank.exchange / registration.create |
Optional overrides |
RabbitMq__PrefetchCount |
10 |
Optional |
Because appsettings.json is not deployed, also verify the remaining variables: ConnectionStrings__DefaultConnection, Monnify__ApiKey/Monnify__SecretKey/Monnify__BaseUrl/Monnify__ContractCode, JwtSettings__Key/JwtSettings__Issuer/JwtSettings__Audience, Admin__Email/Admin__Password/Admin__UserName, Paystack__SecretKey/Paystack__PublicKey/Paystack__BaseUrl and the email variables below.
Email sending calls Brevo's transactional API over HTTPS/443 (free plan: 300 emails/day forever, no credit card). SMTP is deliberately not used: Render's free tier blocks outbound SMTP ports 25/465/587 (Render changelog, Sep 2025), so SMTP connections time out in production while working locally. The REST API on port 443 is not blocked.
- Sign up at brevo.com (free plan) →
Settings > Senders & IP→ add and verify your sender address. Settings > SMTP & API > API keys→ generate an API key (shown once, starts withxkeysib-). SMTP keys (xsmtpsib-) do not work with the HTTP API.- Set the Render environment variables:
| Variable | Example | Notes |
|---|---|---|
EmailConfiguration__From |
corebankingdemo@gmail.com |
Must be a verified Brevo sender |
EmailConfiguration__ApiKey |
xkeysib-... |
Brevo API key from Settings > SMTP & API > API keys |
EmailConfiguration__ApiUrl |
https://api.brevo.com/v3/smtp/email |
Optional — this is already the default |
If ApiKey is unset the API still starts — emails are only attempted when a send is triggered, and a clear configuration error is logged (EmailConfiguration:ApiKey is not configured...). When everything is set, startup logs show [Email] Brevo API configured: https://api.brevo.com/v3/smtp/email, From=....
| Situation | Log output |
|---|---|
| Broker configured and reachable | POST /api/customerrs publishes to registration.queue and returns 202 Accepted. |
| No broker configured | RabbitMQ is not configured — skipping publish and processing the registration in-process. — registration still succeeds, API still healthy |
| Broker temporarily down | Failed to publish the registration message to RabbitMQ — registration still succeeds in-process, API still healthy |
For local development, run the bundled broker with docker compose up -d rabbitmq and keep the RabbitMq:Host=localhost default in appsettings.json.
Before you begin, make sure you have the following installed:
- Clone the repository
git clone https://github.com/Yamuhammad01/Core-Banking-Solution.git- Restore dependencies
dotnet restore
- Create database migration
Add-Migration "InitialCreate"- Update Database
Update-Database- Run the API
dotnet run- Access API at https://localhost:yourport
• Database: CoreBankingDB
• Tables: AspNetUsers, AspNetUserTokens, AspNetUserRoles, AspNetUserLogins, AspNetUserClaims, AspNetRoles, AspNetRoleClaims, Accounts, Transactions, ConfirmationCodes
This section documents all the main endpoints of the Core Banking API, including sample requests, responses, and expected HTTP status codes.
| Endpoint | Method | Description | Status Codes |
|---|---|---|---|
/api/admin/get-all-customers |
GET | Get all customers | 200 OK |
/api/admin/get-customers-by-email |
GET | Get customer by Email | 200 OK, 404 Not Found |
/api/admin/deposit |
POST | Deposit into an account | 200 OK, 400 Bad Request |
/api/auth/customers/register |
POST | Register a new customer | 201 Created, 400 Bad Request |
/api/customer/auth/login |
POST | User login & JWT generation | 200 OK, 400 Bad Request, 401 Unauthorized |
/api/transactions/withdraw |
POST | Withdraw from an account | 200 OK, 400 Bad Request, 403 Forbidden |
/api/transactions/transfer-funds |
POST | Transfer between accounts | 200 OK, 400 Bad Request, 403 Forbidden |
/api/transactions/transaction-history |
GET | View transaction history | 200 OK, 400 Bad Request, 403 Forbidden |
This section explains how to test deposit and transfer operations inside the Core Banking Solution using the built-in simulation endpoints. These endpoints are strictly for development and testing purposes.
- Submit a registration request.
- A unique account number is automatically generated.
- Account details are sent to the registered email
(check Spam/Junk if not found).
Use the built-in admin credentials:
• Email: admin@corebanking.com
• Password: Admin@123@$
After login, a JWT token is generated.
Add it to your request (authorisation) header: Authorization: Bearer <YOUR_JWT_TOKEN>
Call the /api/admin/deposit endpoint using the account number of the customer you registered.
A credit alert is sent to the customer's email showing:
- Amount deposited
- Updated balance
- Transaction details
- Use the customer’s email and password.
- copy the generated token and add it to the authorisation header in this format (Bearer eyJhbGciOiJIUzI......)
You can now view:
-
Account balance
-
My account
-
Profile information
-
Transaction history e.t.c
Register another customer with a different email to generate a second account.
- Log in to the account with funds (Account A).
- Send a transfer request from Account A → Account B using
/api/transactions/transfer-funds.
- Account A receives a debit alert.
- Account B receives a credit alert.
Use the transaction history endpoint to confirm:
- Deposits
- Transfers
- Withdrawals
The deposit endpoint is available only for simulation/testing purposes only.
In a real-world core banking system:
- Admin deposits should not exist
- Funds should only be added through external bank integrations or real payment rails
- Deposits usually come via ACH, SWIFT, NIP, card transactions, or bank APIs, not through admin-triggered actions.
This simulation exists solely for testing account workflows during development.
POST /api/auth/login
Headers:
Content-Type: application/json
{
"email": "user@example.com",
"password": "Password123!"
}Content-Type: application/json
{
"token": "<JWT_TOKEN>",
"expiresIn": 3600
}• Passwords hashed using ASP.NET Core Identity
• JWT Authentication & Role-based Authorization
• Fork the repository
• Create a feature branch: git checkout -b feature/XYZ..Feature
• Commit your changes: git commit -m "Added xyz... feature"
• Push to branch: git push origin feature/XYZ..Feature
• Open a Pull Request
This project is licensed under the MIT License.
Muhammad Idris
• GitHub: https://github.com/Yamuhammad01
• LinkedIn: https://www.linkedin.com/in/muhammad-idrisb2/
• Email: idrismuhd814@gmail.com





