Files
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00
..
2026-05-23 18:37:02 +07:00
2026-05-23 18:37:02 +07:00

Wallet Service .NET

Wallet and Point Account management service for GoodGo Platform.

Overview

The Wallet Service provides comprehensive wallet and loyalty points management with:

  • Wallet Management - Create, deposit, withdraw, transfer funds
  • Escrow Module - Hold, commit, and release funds (for Promotion Service)
  • Point Account - Earn, spend, and track loyalty points
  • Transaction History - Full audit trail of all transactions
  • Multi-Currency Support - VND, USD, PPoint with exchange capabilities
  • Currency Exchange - Convert between currencies with configurable rates
  • Admin Backoffice - Full admin APIs for wallet/points management
  • Domain-Driven Design - Clean Architecture with CQRS pattern

Tech Stack

Component Technology
Framework .NET 10
Database PostgreSQL (EF Core)
CQRS MediatR
Validation FluentValidation
API Docs Swagger/OpenAPI
Logging Serilog

Prerequisites

# Check .NET version
dotnet --version  # Should be 10.0.x

Quick Start

1. Configure Environment

cp .env.example .env
# Edit .env with your database connection

2. Run with Docker

cd deployments/local
docker-compose up wallet-service -d

3. Run Locally

cd services/wallet-service-net
dotnet restore
dotnet build
dotnet run --project src/WalletService.API

API Endpoints

Wallet APIs

Method Endpoint Description
POST /api/v1/wallets Create new wallet
GET /api/v1/wallets/{userId} Get wallet by user ID
POST /api/v1/wallets/{userId}/deposit Deposit funds
POST /api/v1/wallets/{userId}/withdraw Withdraw funds
GET /api/v1/wallets/{userId}/transactions Get transaction history

Escrow/Hold APIs

Method Endpoint Description
POST /api/v1/wallets/{walletId}/holds Create escrow hold
GET /api/v1/wallets/{walletId}/holds/{holdId} Get hold details
POST /api/v1/wallets/{walletId}/holds/{holdId}/execute Execute hold (deduct funds)
POST /api/v1/wallets/{walletId}/holds/{holdId}/release Release hold (return funds)
POST /api/v1/wallets/{walletId}/holds/{holdId}/cancel Cancel hold

Points APIs

Method Endpoint Description
POST /api/v1/points Create point account
GET /api/v1/points/{userId} Get point account
POST /api/v1/points/{userId}/earn Earn points
POST /api/v1/points/{userId}/spend Spend points
GET /api/v1/points/{userId}/transactions Get point transactions

Admin Wallet APIs

Method Endpoint Description
GET /api/v1/admin/wallets Get all wallets (paginated)
GET /api/v1/admin/wallets/{walletId} Get wallet details
POST /api/v1/admin/wallets/{walletId}/freeze Freeze wallet
POST /api/v1/admin/wallets/{walletId}/unfreeze Unfreeze wallet
POST /api/v1/admin/wallets/{walletId}/adjust Adjust balance
GET /api/v1/admin/wallets/statistics Get wallet statistics
GET /api/v1/admin/wallets/search Search wallets

Admin Points APIs

Method Endpoint Description
GET /api/v1/admin/points Get all point accounts
GET /api/v1/admin/points/{accountId} Get point account details
POST /api/v1/admin/points/{accountId}/adjust Adjust points
POST /api/v1/admin/points/{accountId}/bonus Grant bonus points
GET /api/v1/admin/points/statistics Get points statistics
GET /api/v1/admin/points/search Search point accounts

Health Endpoints

Endpoint Purpose
/health Full health status
/health/live Liveness probe (K8s)
/health/ready Readiness probe (K8s)

Multi-Currency Support

Wallet supports multiple currency types with exchange capabilities:

Currency Code Base Rate to VND
Vietnamese Dong VND 1
US Dollar USD 25,000
Loyalty Points PPoint 1,000

Currency Exchange

// Exchange USD to VND
wallet.Exchange(
    fromAmount: 100m, 
    fromCurrency: CurrencyType.USD,
    toCurrency: CurrencyType.VND
); // Returns 2,500,000 VND

// Exchange PPoints to VND
wallet.Exchange(
    fromAmount: 50m,
    fromCurrency: CurrencyType.PPoint,
    toCurrency: CurrencyType.VND
); // Returns 50,000 VND

Project Structure

wallet-service-net/
├── src/
│   ├── WalletService.API/           # API Layer
│   │   ├── Controllers/             # REST endpoints
│   │   │   └── Admin/               # Admin endpoints
│   │   └── Application/             # Commands & Queries
│   │       ├── Commands/            # Write operations
│   │       └── Queries/             # Read operations
│   │
│   ├── WalletService.Domain/        # Domain Layer 
│   │   ├── AggregatesModel/
│   │   │   ├── WalletAggregate/     # Wallet, HoldItem, CurrencyType
│   │   │   └── PointAccountAggregate/  # Points, PointTransaction
│   │   ├── Events/                  # Domain events
│   │   └── Exceptions/              # Domain exceptions
│   │
│   └── WalletService.Infrastructure/  # Infrastructure Layer
│       ├── EntityConfigurations/    # EF Core mappings
│       ├── Repositories/            # Data access
│       └── WalletServiceContext.cs  # DbContext
│
├── tests/
│   ├── WalletService.UnitTests/     # Domain & Logic tests
│   └── WalletService.FunctionalTests/  # API integration tests
│
├── docs/
│   ├── en/                          # English docs
│   └── vi/                          # Vietnamese docs
│
└── Dockerfile

Domain Model

Wallet Aggregate

// Create wallet
var wallet = new Wallet(userId, CurrencyType.VND);

// Deposit funds
wallet.Deposit(1000000m, CurrencyType.VND, "Salary", "REF001");

// Withdraw funds  
wallet.Withdraw(500000m, CurrencyType.VND, "Shopping", "REF002");

// Freeze/Unfreeze
wallet.Freeze();
wallet.Unfreeze();

// Escrow operations
var hold = wallet.Hold(100000m, CurrencyType.VND, "CAMPAIGN", campaignId, "Hold for campaign");
wallet.ExecuteHold(hold.Id, 50000m, "ORDER123"); // Commit 50k
wallet.ReleaseHold(hold.Id, 50000m); // Return 50k
wallet.CancelHold(hold.Id); // Cancel remaining

// Currency exchange
wallet.Exchange(100m, CurrencyType.USD, CurrencyType.VND);

Point Account Aggregate

// Create account
var account = new PointAccount(userId);

// Earn points
account.EarnPoints(100, "ORDER001", "Purchase reward", expiresAt);

// Spend points
account.SpendPoints(50, "ORDER002", "Redeem discount");

// Adjust points (admin)
account.AdjustPoints(10, "ADMIN", "Bonus adjustment");

Testing

# Run all tests
dotnet test

# Run with coverage
dotnet test /p:CollectCoverage=true

# Unit tests only
dotnet test tests/WalletService.UnitTests

# Functional tests only
dotnet test tests/WalletService.FunctionalTests

Test Results

  • 23 tests total
  • 20 unit tests (Wallet, PointAccount domain)
  • 3 functional tests (Health endpoints)

Configuration

Environment Variables

Variable Description Required
DATABASE_URL PostgreSQL connection Yes
ASPNETCORE_ENVIRONMENT Environment No (default: Development)
JWT_AUTHORITY JWT issuer URL Yes (for auth)

appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": "Host=localhost;Database=wallet_db;Username=postgres;Password=postgres"
  },
  "Jwt": {
    "Authority": "http://localhost:5001",
    "Issuer": "http://localhost:5001"
  }
}

Database Migrations

# Create migration
dotnet ef migrations add InitialCreate \
  --project src/WalletService.Infrastructure \
  --startup-project src/WalletService.API

# Apply migration
dotnet ef database update \
  --project src/WalletService.Infrastructure \
  --startup-project src/WalletService.API

Deployment

Docker Build

docker build -t goodgo/wallet-service:latest .

Docker Compose

Service is registered in deployments/local/docker-compose.yml with Traefik routing.

Resources

License

Proprietary - GoodGo Platform