A Spring Boot backend for the wallet platform. This service powers the companion Flutter app in wallet_mobile and handles authentication, wallet creation, funding, transfers, transaction history, and account-related profile updates.
This backend works together with the Flutter mobile client:
Across both repositories, the platform provides:
- Mobile wallet flows in Flutter
- REST APIs in Spring Boot
- JWT-secured authenticated routes
- Refresh-token support for app clients
- Automatic wallet creation during onboarding
- Wallet funding, transfers, ledger tracking, and transaction history
- Profile retrieval and account update operations
- Register new users
- Create a wallet during registration
- Authenticate users with email and password
- Issue JWT access tokens
- Issue refresh tokens for mobile clients
- Allow first-time transaction PIN creation
- Support forgot-password recovery with email and secret key
- Support password reset for authenticated users
- Return authenticated user profile, wallet summary, and security info
- Change email and phone number after password verification
- Search users for transfer recipients
- Return recent transfer contacts
- Fund wallets
- Transfer money between users
- Return paginated transaction history
- Check transactions by idempotency key
- Delete refresh tokens during logout
The Flutter app handles session storage and user interactions, while this backend is responsible for enforcing the rules that protect account access and money movement.
Spring SecurityProtects non-public routes and keeps wallet/profile endpoints behind authentication.JWT access tokensUsed by the mobile app for authenticated requests.Refresh tokensIssued for app clients so short-lived access tokens can be renewed without repeated login.Password hashingPasswords and transaction PINs are verified throughPasswordEncoderinstead of plain-text comparison.
@Transactional service methodsFunding and transfer flows run inside database transactions.Pessimistic wallet lockingWallet lookup uses pessimistic write locking to reduce concurrent balance-update conflicts.Idempotency protectionFunding and transfer requests use idempotency keys to prevent duplicate processing on retries.Ledger recordingTransfer activity creates debit and credit ledger entries for a clearer transaction trail.
Password re-verificationSensitive profile changes require the current password.First-time transaction PIN setupTransfer security includes a dedicated PIN created after onboarding.Forgot-password recovery with secret keyRecovery requires both email and the stored recovery secret.
config/Security, environment, and application configuration.controllers/Auth, user, and transaction endpoints.services/Business logic for auth, tokens, wallets, users, funding, and transfers.entities/JPA models for users, wallets, transactions, ledgers, and refresh tokens.repositories/Data access with Spring Data JPA.models/requestandmodels/responseContracts used by the mobile app.
POST /api/auth/registerPOST /api/auth/loginPOST /api/auth/set-pinPOST /api/auth/forgot-passwordPOST /api/auth/reset-passwordGET /api/auth/refreshPOST /api/auth/logout
GET /api/user/meGET /api/user/me/recent-contactPOST /api/user/email/changePOST /api/user/phone/changeGET /api/user/search?query=...
POST /api/fundPOST /api/transferGET /api/transactions?page=0&size=10GET /api/check/{idempotencyKey}
- Registration creates both the user and the wallet.
- Wallets start with
NGNcurrency and zero balance. - Funding uses an idempotency key so repeated requests do not create duplicate deposits.
- Transfers require a valid transaction PIN.
- Transfer processing records both sender and receiver ledger entries.
- Transaction history is returned from ledger records in descending order.
src/main/java/com/wallet_system/wallet/config/SecurityConfig.javaStateless security setup, route protection, JWT encoder/decoder, and password encoder configuration.src/main/java/com/wallet_system/wallet/controllers/AuthController.javaRegistration, login, PIN setup, refresh, forgot-password, reset-password, and logout endpoints.src/main/java/com/wallet_system/wallet/controllers/UserController.javaAuthenticated profile, recent contacts, user search, and sensitive profile update endpoints.src/main/java/com/wallet_system/wallet/controllers/TransactionsController.javaFunding, transfer, idempotency check, and transaction history endpoints.src/main/java/com/wallet_system/wallet/services/TransactionService.javaFunding and transfer business rules, ledger writes, and transaction retrieval.src/main/java/com/wallet_system/wallet/repositories/WalletRepository.javaPessimistic locking support for balance-changing operations.src/main/java/com/wallet_system/wallet/entities/TransactionEntity.javaTransaction persistence including unique idempotency key support.
- Java 21
- Spring Boot
- Spring Web
- Spring Security
- Spring OAuth2 Resource Server
- Spring Data JPA
- MySQL
- Gradle
- Jakarta Validation
spring-dotenv/java-dotenv
src/
main/
java/com/wallet_system/wallet/
config/
controllers/
entities/
enums/
exceptions/
models/
request/
response/
repositories/
services/
resources/
application.properties
test/
java/com/wallet_system/wallet/
- A user logs in with email and password.
- Spring Security authenticates the request.
- The backend issues an access token.
- App clients also receive a refresh token.
- Protected routes require a valid bearer token.
- The mobile app uses the refresh flow when the access token expires.
Database settings are loaded from environment variables through application.properties.
Required keys:
DB_URLDB_USERNAMEDB_PASSWORD
Current datasource configuration:
spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
spring.jpa.hibernate.ddl-auto=update- Java 21
- MySQL
- Gradle wrapper support enabled in your environment
Create or update src/main/resources/.env with your local database values:
DB_URL=jdbc:mysql://localhost:3306/walletdb
DB_USERNAME=your_username
DB_PASSWORD=your_password./gradlew bootRunThe mobile app currently points to:
http://192.168.0.164:8080/api
If your backend runs on another host or port, update the base URL in wallet_mobile/lib/src/core/network/api_endpoints.dart.
./gradlew test- Error responses are centralized in the global exception handler.
- The backend supports mobile app clients and also contains cookie-oriented login handling for non-app clients.
- Security and transaction guarantees described in the mobile README are enforced here on the server side.