9.0 KiB
9.0 KiB
Kiến Trúc Wallet Service
Tổng Quan
Wallet Service quản lý ví điện tử và tài khoản điểm thưởng cho GoodGo Platform.
flowchart TB
subgraph API["🌐 API Layer"]
Controllers["Controllers"]
Commands["Commands"]
Queries["Queries"]
end
subgraph Domain["💎 Domain Layer"]
Wallet["Wallet Aggregate"]
PointAccount["PointAccount Aggregate"]
end
subgraph Infra["⚙️ Infrastructure Layer"]
Repos["Repositories"]
EF["EF Core"]
end
subgraph DB["💾 PostgreSQL"]
Tables["Tables"]
end
API --> Domain
Domain --> Infra
Infra --> DB
style API fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
style Domain fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
style Infra fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
style DB fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
Các Pattern Kiến Trúc
Domain-Driven Design (DDD)
- Aggregates: Wallet, PointAccount
- Entities: WalletTransaction, PointTransaction, HoldItem, WalletItem
- Value Objects: Money, CurrencyType
- Domain Events: WalletCreated, BalanceChanged, PointsEarned, EscrowHeld, EscrowExecuted
CQRS Pattern
flowchart LR
subgraph Commands["Commands (Ghi)"]
C1["CreateWallet"]
C2["Deposit/Withdraw"]
C3["Exchange"]
C4["Hold/Execute/Release"]
C5["EarnPoints/SpendPoints"]
C6["Admin Commands"]
end
subgraph Queries["Queries (Đọc)"]
Q1["GetWallet"]
Q2["GetTransactions"]
Q3["GetPointAccount"]
Q4["GetStatistics"]
Q5["Admin Queries"]
end
style Commands fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
style Queries fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px
Domain Model
Wallet Aggregate
classDiagram
class Wallet {
+Guid Id
+Guid UserId
+WalletStatus Status
+CurrencyType DefaultCurrency
+List~WalletItem~ Items
+List~HoldItem~ Holds
+Deposit(amount, currency, desc, ref)
+Withdraw(amount, currency, desc, ref)
+Exchange(fromAmount, fromCurrency, toCurrency)
+Hold(amount, currency, refType, refId, desc)
+ExecuteHold(holdId, amount, ref)
+ReleaseHold(holdId, amount)
+Freeze()
+Unfreeze()
}
class WalletItem {
+Guid Id
+CurrencyType Currency
+decimal Balance
+decimal HeldBalance
+decimal AvailableBalance
}
class HoldItem {
+Guid Id
+decimal OriginalAmount
+decimal RemainingAmount
+decimal ExecutedAmount
+decimal ReleasedAmount
+HoldStatus Status
+string ReferenceType
+Guid ReferenceId
+Execute(amount, ref)
+Release(amount)
+Cancel()
}
class WalletTransaction {
+Guid Id
+TransactionType Type
+decimal Amount
+CurrencyType Currency
+decimal BalanceAfter
+string Description
+DateTime CreatedAt
}
class CurrencyType {
+int Id
+string Name
+decimal BaseExchangeRate
+VND
+USD
+PPoint
+GetExchangeRateTo(currency)
+ConvertTo(amount, currency)
}
Wallet "1" --> "*" WalletItem
Wallet "1" --> "*" HoldItem
Wallet "1" --> "*" WalletTransaction
WalletItem --> CurrencyType
HoldItem --> CurrencyType
PointAccount Aggregate
classDiagram
class PointAccount {
+Guid Id
+Guid UserId
+long TotalPoints
+long AvailablePoints
+long PendingPoints
+EarnPoints(points, source, desc, expires)
+SpendPoints(points, source, desc)
+AdjustPoints(points, source, desc)
}
class PointTransaction {
+Guid Id
+PointTransactionType Type
+long Points
+long BalanceAfter
+string Source
+DateTime? ExpiresAt
}
PointAccount "1" --> "*" PointTransaction
Database Schema
Các Bảng
| Bảng | Mô Tả |
|---|---|
Wallets |
Tài khoản ví người dùng |
WalletItems |
Số dư tiền tệ mỗi ví |
WalletTransactions |
Lịch sử giao dịch ví |
HoldItems |
Các lệnh ký quỹ |
PointAccounts |
Tài khoản điểm người dùng |
PointTransactions |
Lịch sử giao dịch điểm |
Indexes Chính
IX_Wallets_UserId- Tra cứu theo userIX_WalletItems_WalletId_CurrencyTypeId- Số dư theo tiền tệIX_WalletTransactions_WalletId- Lịch sử giao dịchIX_HoldItems_WalletId_Status- Các hold đang hoạt độngIX_PointAccounts_UserId- Tra cứu theo user
API Flow
Luồng Nạp Tiền
sequenceDiagram
participant C as Client
participant API as Controller
participant H as Handler
participant W as Wallet
participant DB as Database
C->>API: POST /wallets/{userId}/deposit
API->>H: DepositCommand
H->>W: wallet.Deposit(amount)
W->>W: Tạo Transaction
W->>W: Raise DomainEvent
H->>DB: SaveChanges
DB-->>API: Thành công
API-->>C: Số dư cập nhật
Luồng Escrow
sequenceDiagram
participant C as Client
participant API as Controller
participant W as Wallet
participant H as HoldItem
C->>API: POST /holds (Tạo)
API->>W: wallet.Hold(amount)
W->>H: Tạo HoldItem
W-->>C: HoldId
C->>API: POST /holds/{id}/execute
API->>W: wallet.ExecuteHold(id, amount)
W->>H: hold.Execute(amount)
H-->>C: Số tiền đã thực thi
C->>API: POST /holds/{id}/release
API->>W: wallet.ReleaseHold(id, amount)
W->>H: hold.Release(amount)
H-->>C: Số tiền đã giải phóng
Luồng Quy Đổi Tiền Tệ
sequenceDiagram
participant C as Client
participant API as Controller
participant W as Wallet
participant CT as CurrencyType
C->>API: POST /exchange
API->>W: wallet.Exchange(100 USD, VND)
W->>CT: GetExchangeRate(USD → VND)
CT-->>W: Tỷ giá = 25000
W->>W: Rút 100 USD
W->>W: Nạp 2.500.000 VND
W->>W: Raise WalletExchangedEvent
W-->>C: Kết quả quy đổi
Domain Events
| Event | Kích Hoạt | Dữ Liệu |
|---|---|---|
WalletCreatedDomainEvent |
Tạo ví | WalletId, UserId |
WalletBalanceChangedDomainEvent |
Nạp/Rút | WalletId, Amount, Type |
WalletExchangedDomainEvent |
Quy đổi tiền tệ | FromCurrency, ToCurrency, Rate |
EscrowHeldDomainEvent |
Tạo hold | HoldId, Amount, RefType |
EscrowExecutedDomainEvent |
Thực thi hold | HoldId, Amount |
EscrowReleasedDomainEvent |
Giải phóng hold | HoldId, Amount |
PointsEarnedDomainEvent |
Tích điểm | AccountId, Points |
PointsSpentDomainEvent |
Tiêu điểm | AccountId, Points |
Tích Hợp Giữa Các Service
Tích Hợp IAM Service
flowchart LR
WS["🔐 Wallet Service"] --> IAM["👤 IAM Service"]
IAM --> UV["Xác thực User"]
IAM --> JV["Kiểm tra JWT"]
style WS fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px
style IAM fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
style UV fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
style JV fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
Luồng Xác Thực
- Client gửi JWT token trong Authorization header
- Wallet Service xác thực JWT với IAM Service
- Trích xuất userId từ JWT claims
- Xử lý thao tác ví cho user
Triển Khai
Cấu Hình Docker Compose
wallet-service:
build:
context: ../..
dockerfile: services/wallet-service-net/Dockerfile
environment:
- DATABASE_URL=${WALLET_DATABASE_URL}
- JWT_AUTHORITY=${IAM_SERVICE_URL}
labels:
- traefik.http.routers.wallet.rule=PathPrefix(`/api/v1/wallets`)
Health Checks
| Endpoint | Kiểm Tra |
|---|---|
/health/live |
Service đang chạy |
/health/ready |
Database kết nối |
/health |
Trạng thái đầy đủ |
Bảo Mật
Xác Thực
- Xác thực JWT Bearer token
- Tích hợp IAM Service
Phân Quyền
- User chỉ truy cập được ví của mình
- Admin endpoints yêu cầu role Admin/SuperAdmin
Bảo Vệ Dữ Liệu
- Lưu số tiền với độ chính xác cao
- Audit trail giao dịch
- Soft delete cho ví
Hiệu Năng
Tối Ưu
- Connection pooling (EF Core)
- Index cho các queries thường xuyên
- Phân trang cho lịch sử giao dịch
Mở Rộng
- Horizontal scaling với load balancer
- Read replicas cho queries
- Redis caching (tương lai)
Giám Sát
Metrics
- Thời gian request
- Số lượng giao dịch
- Tỷ lệ lỗi
Logging
- Serilog structured logging
- Correlation IDs cho tracing
- Tích hợp Seq/Loki