📖 Bản tiếng Anh (English Edition)
Điều kiện tiên quyết: Nền tảng vững chắc về quản trị sản phẩm ngân hàng, khung tuân thủ pháp lý (Basel III/IFRS 9), kỹ nghệ độ tin cậy hệ thống (SRE) và hợp đồng giao diện API.
Phần 8: Viết PRD Cho Core Banking — Hướng Dẫn Cho Developer
Trả lời nhanh (Answer-first): Tài liệu yêu cầu sản phẩm PRD ngân hàng lõi xác lập đặc tả chức năng rõ ràng cho vòng đời tài khoản, hạch toán sổ cái và báo cáo quy định, song hành cùng các chỉ tiêu phi chức năng như độ trễ P99 dưới 50ms, tính sẵn sàng 99.999% và tuân thủ chuẩn mực vốn Basel III.
1. Khung Đặc Tả Kỹ Thuật PRD Core Banking
Khác với PRD của ứng dụng tiêu dùng thông thường vốn tập trung vào giao diện người dùng và phễu tăng trưởng, PRD ngân hàng lõi là một bản hợp đồng kỹ thuật và pháp lý quy định các phương trình kế toán, khóa đồng thời và kịch bản phục hồi lỗi:
flowchart TD
subgraph PRD_Framework ["Khung Đặc Tả Kỹ Thuật PRD Core Banking"]
Math["1. Bất Biến Toán Học & Kế Toán Lõi<br/>(Quy Tắc Bút Toán Sổ Cái GL & Làm Tròn)"]
Security["2. Bảo Mật & Ma Trận Maker-Checker<br/>(Kiểm Soát Kép, Phân Quyền RBAC, HSM & PIN)"]
Batch["3. Đặc Tả Xử Lý Theo Lô Cuối Ngày (EOD)<br/>(Dồn Tích Lãi, Cutoff & Đối Soát 3 Chiều)"]
SRE["4. Yêu Cầu Phi Chức Năng & SRE<br/>(Sẵn Sàng 99.999%, RPO=0, Độ Trễ P99 < 50ms)"]
end
Math --> Security
Security --> Batch
Batch --> SRE
2. Quy Trình Điều Phối Lô Cuối Ngày (EOD) & Đối Soát Sổ Cái
Tiến trình EOD là quy trình tài chính đóng sổ ngày làm việc của ngân hàng, thực hiện tuần tự các phép tính toán sổ cái trước khi chuyển sang ngày làm việc tiếp theo:
sequenceDiagram
autonumber
participant Scheduler as Bộ Điều Phối Lô EOD (Go / Temporal)
participant CoreDB as CSDL Sổ Cái Ngân Hàng Lõi
participant SwitchLog as Dữ Liệu Quyết Toán Đối Tác (NAPAS / Visa)
participant Recon as Engine Đối Soát 3 Chiều
participant GL as Bảng Cân Đối Thử Nghiệm (Trial Balance)
Scheduler->>CoreDB: 1. Kích hoạt mốc Cutoff giao dịch lúc nửa đêm
Scheduler->>CoreDB: 2. Tính toán lãi dồn tích hằng ngày (CASA & Vay)
Scheduler->>CoreDB: 3. Hạch toán phí dịch vụ định kỳ và thuế
Scheduler->>SwitchLog: 4. Nạp các file quyết toán từ cổng chuyển mạch
Scheduler->>Recon: 5. Thực hiện đối soát giao dịch 3 chiều tự động
alt Phát hiện chênh lệch (Lệch Tiền)
Recon-->>Scheduler: Tạo phiếu ngoại lệ kế toán (Cần can thiệp thủ công)
else Khớp 100% (Không Lệch Bút Toán)
Recon-->>Scheduler: Xác nhận đối soát thành công tuyệt đối
end
Scheduler->>GL: 6. Tạo bảng cân đối thử nghiệm và bảng cân đối kế toán
GL-->>Scheduler: Xác nhận bất biến: Tài Sản == Nợ Phải Trả + Vốn Chủ Sở Hữu
Scheduler->>CoreDB: 7. Tăng ngày hệ thống sang ngày làm việc mới (BOD)
3. Bảng Kiểm Tra (Checklist) Nghiệm Thu PRD Ngân Hàng
Trước khi đội ngũ kỹ sư bắt tay vào lập trình bất kỳ tính năng ngân hàng lõi nào, tài liệu PRD bắt buộc phải thỏa mãn các tiêu chí sau:
| Tiêu Chí Đánh Giá | Yêu Cầu Bắt Buộc Trong PRD Ngân Hàng | Cơ Chế Kiểm Chứng Tự Động |
|---|---|---|
| Bất Biến Kế Toán | Phải liệt kê chính xác các tài khoản GL bị ảnh hưởng kèm giá trị Nợ/Có. | Unit test kiểm tra đẳng thức $\Delta \text{Tài Sản} = \Delta \text{Nợ Phải Trả} + \Delta \text{Vốn Chủ Sở Hữu}$. |
| Ma Trận Maker-Checker | Các giao dịch vượt hạn mức (ví dụ > 50 triệu đồng) bắt buộc phải có 2 người duyệt độc lập (Người tạo Maker, Người duyệt Checker). | Kiểm thử API bảo đảm Người tạo không thể tự duyệt lệnh của chính mình. |
| Chuẩn Chống Trùng Lặp | Toàn bộ API ghi dữ liệu phải bắt buộc có header Idempotency-Key lưu vết tối thiểu 24 giờ. | Test case gửi trùng lặp 2 request cùng ID bảo đảm chỉ trừ tiền một lần duy nhất. |
| Kịch Bản Xử Lý Lỗi | Mọi bước xử lý xuôi đều phải có đặc tả bước bù trừ ngược (hoàn tiền, nhả giữ, xử lý phí). | Kiểm thử mô phỏng sự cố mạng (Chaos Engineering) bảo đảm rollback tự động. |
| Chỉ Số SLA SRE | Độ trễ P99 < 50ms tại 5.000 TPS; Độ sẵn sàng 99.999%; RPO = 0; RTO < 30s. | Bài kiểm tra tải phân tán k6 và diễn tập kịch bản phục hồi thảm họa tự động. |
Câu Hỏi Thường Gặp (FAQ)
Tại sao PRD Core Banking lại bắt buộc phải có bảng bất biến toán học kế toán mà các PRD SaaS thông thường không có?
Quy trình kiểm soát kép Maker-Checker là gì và được hiện thực hóa ở tầng API và Database ra sao?
PENDING_APPROVAL kèm trường maker_user_id. Tầng API sẽ từ chối thẳng thừng lệnh duyệt nếu checker_user_id == maker_user_id, đồng thời yêu cầu chữ ký số xác thực từ cán bộ kiểm soát cấp quản lý.Làm thế nào để rút ngắn khoảng thời gian chạy lô cuối ngày (EOD Batch Window) từ 6 tiếng xuống còn 20 phút?
5. Triển Khai Kỹ Thuật: Schema gRPC Protobuf v3 & Động Cơ Maker-Checker Bằng Go 1.25
Tài liệu PRD ngân hàng lõi chuẩn sản xuất bắt buộc phải xác lập các đặc tả kỹ thuật chính xác cho hợp đồng API và luồng kiểm soát tuân thủ, đặc biệt là quy trình kiểm soát kép Maker-Checker (Nguyên tắc 4 Mắt) theo quy định của cơ quan thanh tra ngân hàng.
5.1 Quy Trình Phê Duyệt Kép Maker-Checker
graph TD
subgraph MakerCheckerPipeline["Quy Trình Phê Duyệt Kiểm Soát Kép (Maker-Checker)"]
Maker[Maker: Giao Dịch Viên Khởi Tạo] --> CreateRequest[Đề Xuất Nghiệp Vụ: Chuyển Tiền Lớn / Nâng Hạn Mức]
CreateRequest --> StorePending[Lưu Yêu Cầu Ở Trạng Thái Chờ Duyệt]
StorePending --> NotifyCheckers[Thông Báo Đến Hàng Đợi Kiểm Soát Viên]
NotifyCheckers --> CheckerReview{Kiểm Soát Viên Xem Xét: UUID Khác Maker}
CheckerReview -->|Từ Chối Kèm Lý Do| StatusRejected[Trạng Thái: REJECTED & Báo Cho Maker]
CheckerReview -->|Chấp Thuận & Ký Số| ValidateMaker[Kiểm Tra UUID Checker != UUID Maker]
ValidateMaker -->|Cố Tình Tự Duyệt| SecurityAlert[CẢNH BÁO AN NINH: Vi Phạm Kiểm Soát Kép]
ValidateMaker -->|Hợp Lệ| ExecuteTx[Thực Thi Giao Dịch Ngân Hàng Lõi]
ExecuteTx --> StatusApproved[Trạng Thái: APPROVED & Ghi Sổ Cái]
end
5.2 Đặc Tả Hợp Đồng gRPC Protobuf v3
syntax = "proto3";
package banking.core.v1;
option go_package = "banking/core/v1;corev1";
import "google/protobuf/timestamp.proto";
service CoreBankingService {
rpc PostTransaction (PostTransactionRequest) returns (PostTransactionResponse);
rpc CreateApprovalRequest (CreateApprovalRequest) returns (ApprovalRequestResponse);
rpc ApproveRequest (ApproveActionRequest) returns (ApprovalActionResponse);
rpc RejectRequest (RejectActionRequest) returns (ApprovalActionResponse);
rpc GetAccountBalance (GetBalanceRequest) returns (GetBalanceResponse);
}
message PostTransactionRequest {
string idempotency_key = 1;
string source_account_id = 2;
string dest_account_id = 3;
int64 amount_micros = 4;
string currency = 5;
string narration = 6;
}
message PostTransactionResponse {
string transaction_id = 1;
int64 source_balance_micros = 2;
int64 dest_balance_micros = 3;
google.protobuf.Timestamp executed_at = 4;
}
message CreateApprovalRequest {
string request_id = 1;
string maker_id = 2;
string action_type = 3;
string payload_json = 4;
}
message ApprovalRequestResponse {
string request_id = 1;
string status = 2;
google.protobuf.Timestamp created_at = 3;
}
message ApproveActionRequest {
string request_id = 1;
string checker_id = 2;
string signature_token = 3;
}
message RejectActionRequest {
string request_id = 1;
string checker_id = 2;
string rejection_reason = 3;
}
message ApprovalActionResponse {
string request_id = 1;
string final_status = 2;
google.protobuf.Timestamp resolved_at = 3;
}
message GetBalanceRequest {
string account_id = 1;
}
message GetBalanceResponse {
string account_id = 1;
int64 ledger_balance_micros = 2;
int64 available_balance_micros = 3;
int64 overdraft_limit_micros = 4;
string currency = 5;
}
5.3 Mã Nguồn Thực Thi: Động Cơ Maker-Checker Bằng Go 1.25
package prd
import (
"context"
"errors"
"fmt"
"time"
)
type ApprovalStatus string
const (
StatusPending ApprovalStatus = "PENDING_APPROVAL"
StatusApproved ApprovalStatus = "APPROVED"
StatusRejected ApprovalStatus = "REJECTED"
)
type ApprovalRequest struct {
ID string
MakerID string
CheckerID string
ActionType string
PayloadJSON string
Status ApprovalStatus
CreatedAt time.Time
ResolvedAt time.Time
}
type ApprovalEngine struct {
requests map[string]*ApprovalRequest
}
func NewApprovalEngine() *ApprovalEngine {
return &ApprovalEngine{
requests: make(map[string]*ApprovalRequest),
}
}
func (e *ApprovalEngine) CreateRequest(makerID string, actionType string, payload string) (*ApprovalRequest, error) {
if makerID == "" {
return nil, errors.New("dinh danh maker khong duoc de trong")
}
reqID := fmt.Sprintf("req_%d", time.Now().UnixNano())
req := &ApprovalRequest{
ID: reqID,
MakerID: makerID,
ActionType: actionType,
PayloadJSON: payload,
Status: StatusPending,
CreatedAt: time.Now(),
}
e.requests[reqID] = req
return req, nil
}
func (e *ApprovalEngine) Approve(ctx context.Context, requestID string, checkerID string) (*ApprovalRequest, error) {
req, exists := e.requests[requestID]
if !exists {
return nil, errors.New("khong tim thay yeu cau phe duyet")
}
if req.Status != StatusPending {
return nil, fmt.Errorf("khong the phe duyet yeu cau o trang thai '%s'", req.Status)
}
// Thuc thi Nguyen tac 4 Mat: Maker khong the tu phe duyet yeu cau cua chinh minh
if req.MakerID == checkerID {
return nil, errors.New("vi pham quy dinh: maker va checker khong the la cung mot ca nhan")
}
req.CheckerID = checkerID
req.Status = StatusApproved
req.ResolvedAt = time.Now()
return req, nil
}
func (e *ApprovalEngine) Reject(ctx context.Context, requestID string, checkerID string) (*ApprovalRequest, error) {
req, exists := e.requests[requestID]
if !exists {
return nil, errors.New("khong tim thay yeu cau phe duyet")
}
if req.Status != StatusPending {
return nil, fmt.Errorf("khong the tu choi yeu cau o trang thai '%s'", req.Status)
}
req.CheckerID = checkerID
req.Status = StatusRejected
req.ResolvedAt = time.Now()
return req, nil
}
6. Lộ Trình Xử Lý Quyết Toán Cuối Ngày (EOD) & Phân Tầng Hệ Thống
Tài liệu PRD ngân hàng lõi phải quy định rõ ràng thứ tự các bước trong luồng xử lý lô chuyển giao ngày tài chính:
sequenceDiagram
autonumber
participant Scheduler as Bộ Điều Phối Xử Lý Lô
participant Ledger as Sổ Cái Kế Toán
participant Interest as Phân Hệ Dồn Tích Lãi
participant Regulatory as Báo Cáo Quy Định
participant Storage as Kho Lưu Trữ Bất Biến WORM
Scheduler->>Ledger: Đạt mốc khóa sổ (23:59:00 UTC) -> Tạm dừng ghi sổ
Scheduler->>Interest: Quét tài khoản CASA & Tín Dụng (Tính lãi dồn tích)
Interest-->>Scheduler: Lãi đã tính xong (Số dư đã cân bằng)
Scheduler->>Ledger: Hạch toán các bút toán lãi vào tài khoản sổ cái
Scheduler->>Regulatory: Kết xuất báo cáo Basel III & Ngân hàng Nhà nước
Regulatory->>Storage: Lưu trữ báo cáo có ký số vào kho WORM
Storage-->>Scheduler: Xác nhận lưu trữ hoàn tất
Scheduler->>Ledger: Mở khóa sổ cái -> Khởi động ngày tài chính mới
7. Ma Trận Chỉ Tiêu Phi Chức Năng (Tiêu Chuẩn Năm Số Chín 99.999%)
| Chỉ Số Kỹ Thuật | Tiêu Chuẩn SLA Sản Xuất | Ngưỡng Cảnh Báo P2 | Hậu Quả Khi Vi Phạm |
|---|---|---|---|
| Tính Sẵn Sàng Hệ Thống | $99.999%$ ($\le 5.26\text{ phút/năm}$) | $< 99.99%$ | Bị xử phạt hành chính và công bố công khai |
| Độ Trễ Xử Lý Giao Dịch P99 | $\le 45.0\text{ mili-giây}$ | $> 100.0\text{ ms}$ | Hủy giao dịch do timeout từ cổng chuyển mạch |
| Mục Tiêu Mất Mát Dữ Liệu (RPO) | Chính xác bằng $0$ | $> 0$ giao dịch | Bị thanh tra giấy phép vận hành ngân hàng |
| Thời Gian Phục Hồi Thảm Họa (RTO) | $\le 60.0\text{ giây}$ xuyên vùng | $> 300.0\text{ s}$ | Tự động chuyển vùng dự phòng thảm họa |
| Số Lượng Người Dùng Đồng Thời | $\ge 250,000$ kết nối | $< 100,000$ | Tự động mở rộng pod Kubernetes theo tải |
8. Danh Mục Kiểm Tra Tuân Thủ Pháp Lý & Sẵn Sàng Kiểm Toán
Một PRD Core Banking hoàn chỉnh phải bao gồm các tiêu chí nghiệm thu rõ ràng cho các khung pháp lý:
- Thông tư của Ngân hàng Nhà nước: Nhật ký kiểm toán ghi nhận mọi biến động số dư với tính không thể chối bỏ.
- Bộ Đệm Vốn Basel III: Tự động tính toán tài sản có rủi ro (RWA) và tỷ lệ an toàn vốn tối thiểu 10.5%.
- Chuẩn Mực IFRS 9: Tự động tính tổn thất tín dụng kỳ vọng (ECL) cho các danh mục cho vay.
- Quy Định AML/CFT của FATF: Quét danh sách đen cấm vận theo thời gian thực trên mọi giao dịch chuyển tiền liên ngân hàng trước khi hạch toán.
9. Động Cơ Tính Toán Thanh Khoản Basel III (LCR & NSFR) Bằng Go 1.25
Theo chuẩn mực an toàn vốn Basel III, ngân hàng lõi phải tự động tính toán và báo cáo Tỷ lệ Đảm bảo Thanh khoản (LCR) và Tỷ lệ Nguồn vốn Ổn định Ròng (NSFR) hàng ngày:
package prd
import (
"errors"
)
type LiquidityCoverageAssessment struct {
HQLAAmountMicros int64
TotalNetCashOutflowMicros int64
LCRRatioPercent float64
IsCompliant bool
}
type BaselCalculator struct {
MinLCRPercent float64
}
func NewBaselCalculator() *BaselCalculator {
return &BaselCalculator{MinLCRPercent: 100.0}
}
func (c *BaselCalculator) CalculateLCR(hqlaMicros int64, netOutflowMicros int64) (*LiquidityCoverageAssessment, error) {
if hqlaMicros < 0 || netOutflowMicros <= 0 {
return nil, errors.New("tham so khong hop le: luong tien ra rong phai lon hon 0")
}
ratio := (float64(hqlaMicros) / float64(netOutflowMicros)) * 100.0
isCompliant := ratio >= c.MinLCRPercent
return &LiquidityCoverageAssessment{
HQLAAmountMicros: hqlaMicros,
TotalNetCashOutflowMicros: netOutflowMicros,
LCRRatioPercent: ratio,
IsCompliant: isCompliant,
}, nil
}
func (c *BaselCalculator) CalculateNSFR(availableStableFunding int64, requiredStableFunding int64) (float64, bool) {
if requiredStableFunding <= 0 {
return 0.0, false
}
nsfr := (float64(availableStableFunding) / float64(requiredStableFunding)) * 100.0
return nsfr, nsfr >= 100.0
}
10. Giám Sát Vận Hành & Quy Tắc Cảnh Báo Prometheus Cho SLA Ngân Hàng
Để bảo đảm tính sẵn sàng 99.999% và đáp ứng các chỉ tiêu phi chức năng trong PRD, đội ngũ SRE thiết lập quy tắc giám sát Prometheus thời gian thực:
groups:
- name: core-banking-slas
rules:
- alert: CoreBankingHighP99Latency
expr: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{job="core-banking"}[5m])) by (le)) > 0.045
for: 2m
labels:
severity: critical
tier: financial-core
annotations:
summary: "Do tre giao dich P99 vuot nguong SLA 45ms"
description: "Do tre hien tai la {{ $value }}s, vi pham cam ket van hanh."
- alert: LedgerDebitCreditImbalance
expr: core_banking_ledger_debit_credit_imbalance_micros != 0
for: 0s
labels:
severity: page-emergency
tier: financial-core
annotations:
summary: "KHAN CAP: Tong no khong bang tong co trong so cai"
description: "Kich hoat dung giao dich tu dong. Chenh lech: {{ $value }} micros."
11. Phân Tích Sự Cố Thực Tế: Phòng Ngừa Trạng Thái Não Phân Đôi Khi Chuyển Vùng Thảm Họa
Trong cuộc diễn tập ứng phó thảm họa khu vực, cụm ngân hàng đa vùng suýt gặp sự cố split-brain do suy hao đường truyền mạng:
- Diễn Biến Sự Cố: Vùng chính bị rớt gói tin 65%; hệ thống kiểm tra tại vùng phụ ngỡ rằng vùng chính đã sập và tự động kích hoạt chế độ ghi.
- Nguyên Nhân Gốc Rễ: Tập lệnh thăng cấp chỉ dựa vào HTTP timeout đơn giản thay vì cơ chế đồng thuận Raft. Trong 90 giây, cả hai vùng đều tiếp nhận giao dịch ghi độc lập.
- Giải Pháp Kiến Trúc: Triển khai thẻ hàng rào (fencing tokens) dựa trên thuật toán Raft qua cụm 3 vùng khả dụng (Availability Zones). Quyền ghi đòi hỏi đa số biểu quyết của cụm, triệt tiêu hoàn toàn khả năng phát sinh giao dịch song song khi mạng phân mảnh.
12. Kịch Bản Chuyển Đổi Lên Production (Cutover Runbook) & Kiểm Thử Khói
Khi chuyển đổi từ hệ thống mainframe cũ sang kiến trúc Core Banking Go hiện đại, các đội ngũ kỹ thuật thực thi danh mục kiểm tra chuyển giao nghiêm ngặt:
- Đóng Băng Cấu Hình: Trước thời điểm chuyển đổi 48 giờ, đóng băng toàn bộ thay đổi schema và triển khai hạ tầng.
- Đối Soát Số Dư Lần Cuối (T-0): Chạy đối soát tự động so sánh bảng cân đối thử giữa sổ cái tổng hợp, tiền gửi CASA và dư nợ cho vay đến từng đơn vị tiền tệ nhỏ nhất.
- Chuyển Mạch DNS & Cổng Thanh Toán: Cấu hình lại các cổng kết nối NAPAS, SWIFT và máy ATM chuyển hướng sang endpoint gRPC mới với kiểm tra sức khỏe tự động.
- Kiểm Thử Khói (Smoke Testing): Thực hiện các giao dịch chuyển khoản thử nghiệm 10,000 VND trên tài khoản test, xác minh luồng phê duyệt Maker-Checker, khử trùng lặp và ghi nhận luồng sự kiện Kafka.
- Giám Sát Tăng Cường (Hypercare): Duy trì phòng tác chiến kỹ thuật 24/7 theo dõi độ trễ giao dịch P99, độ bão hòa connection pool cơ sở dữ liệu và các báo cáo tự động chuẩn Basel III.
