Skip to content

Mô hình miền

Payment sở hữu 2 bảng (WebhookConfig + các row theo merchant trong bảng Configuration chia sẻ). Schema Transaction / PaymentAttempt / PaymentResult thuộc sở hữu của @nx/mq-pay (cross-package read cho payment).

1. ERD đầy đủ

2. Cột chung

Mọi entity thêm các cột này qua generateCommonColumnDefs():

CộtKiểu
idtext (PK, Snowflake)
createdAt / modifiedAt / deletedAttimestamptz
createdBy / modifiedBytext
metadatajsonb

3. Entity

3.1 WebhookConfig

Thuộc tínhGiá trị
BảngWebhookConfig
Nguồncore/src/models/schemas/public/webhook-config/schema.ts
Soft-delete
TrườngKiểuBắt buộcMô tả
nametextTên hiển thị
urltextEndpoint webhook
eventTypestext[]Sự kiện đã đăng ký (ví dụ ['mq-pay:attempt.success'])
statustextACTIVATED (mặc định) / DEACTIVATED
signingMethodtextNONE (mặc định) / HMAC_SHA256
secrettextSecret ký (sử dụng khi signingMethod ≠ NONE)
headersjsonbHTTP header tùy chỉnh, mặc định {}
metadatajsonbMặc định { timeoutMs: 30000, maxRetries: 3 }

Index: (status).

3.2 Configuration (các row liên quan đến payment)

Thuộc tínhGiá trị
BảngConfiguration (chia sẻ)
Nguồncore/src/models/schemas/public/configuration/schema.ts
TrườngKiểuBắt buộcMô tả
codetextVNPAY_QR_MMS / VNPAY_PHONE_POS / mã credential theo merchant
grouptextINTEGRATION cho payment config
principalTypetextMERCHANT cho row theo merchant
principalIdtextMerchant id
environmenttextDEVELOPMENT / PRODUCTION
tValuetextJSON config được mã hóa (provider config như appId, masterMerchantCode)
credentialtextCredential được mã hóa — ẩn khỏi đọc CRUD; AES-256-GCM
dataTypetextTEXT / JSON / BOOLEAN
statustextACTIVATED (mặc định)

Ràng buộc:

  • Partial unique: (group, code, principalId, principalType, environment) WHERE deletedAt IS NULL
  • Index: (group, code, environment), (group, principalType), GIN metadata, (principalId), (principalType, principalId), (status)

3.3 Transaction (từ @nx/mq-pay)

TrườngKiểuGhi chú
statusenumNEW (1xx) / PARTIAL (3xx) / SETTLED (3xx) / CANCELLED (5xx) / BLOCKED (5xx) / CLOSED (5xx)
total / paiddecimalTheo dõi số tiền
sourceType / sourceIdtextĐa hình — thường là SaleOrder / SaleCheck
metadata.merchant.source.idjsonb pathPhạm vi merchant, dùng bởi PaymentSocketEventService

3.4 PaymentAttempt (từ @nx/mq-pay)

TrườngKiểuGhi chú
transactionIdtextFK
statusenumNEW (100) / SENT (200) / SUCCESS (300) / FAIL (500) / EXPIRED (510)
paymentProvidertextVNPAY_QR_MMS / VNPAY_PHONE_POS / VNPAY_SMART_POS / SYSTEM
metadata.sourcejsonb{ id, uid, type } — order/check khởi tạo

4. Status Enums

4.1 PaymentProviders (từ @nx/mq-pay)

Giá trịTrạng thái
SYSTEMTiền mặt / chuyển khoản ngân hàng thủ công (in-platform)
VNPAY_QR_MMSHỗ trợ
VNPAY_PHONE_POSHỗ trợ
VNPAY_SMART_POSHỗ trợ (placeholder)
MOMOKHÔNG HỖ TRỢ
ZALOPAYKHÔNG HỖ TRỢ
VIETQRPlaceholder

4.2 Vòng đời Transaction

CodeTrạng tháiGhi chú
100NEWĐã tạo
300PARTIALĐã nhận một phần thanh toán
300SETTLEDĐã thanh toán đầy đủ (immutable)
500CANCELLEDTự động hủy (chưa có thanh toán)
500BLOCKEDAdmin chặn (có thể đảo ngược)
500CLOSEDAdmin đóng (không thể đảo ngược)

4.3 Vòng đời PaymentAttempt

CodeTrạng thái
100NEW
200SENT (đã có QR)
300SUCCESS
500FAIL
510EXPIRED

4.4 Hành động credential (theo IMQPayOptions.credentialGetter)

Hành độngSử dụng
CREATE_PAYMENTKý request đến nhà cung cấp
VERIFY_IPNXác minh IPN của nhà cung cấp
CHECK_TRANSACTIONTruy vấn trạng thái transaction
CANCEL_PAYMENTHủy thanh toán đang chờ
REFUNDHoàn tiền

4.5 Loại credential

LoạiMục đích
REQUESTKý request đến nhà cung cấp
RESPONSEXác minh response từ nhà cung cấp
IPNXác minh IPN
PLATFORM_UNIT_TOKENToken theo từng đơn vị (ví dụ cấp terminal)

4.6 Topic WebSocket (PaymentWebSocketTopics)

TopicNguồn
observation/payment/transactionSự kiện vòng đời Transaction
observation/payment/payment-attemptSự kiện Attempt

5. Invariant liên entity

InvariantCưỡng chế
Configuration.credential đã mã hóa không bao giờ được đọc trực tiếp qua CRUD repositorySchema đánh dấu credential là hidden; truy cập thô qua drizzle connector chỉ trong PaymentConfigurationService
WebhookConfig.eventTypes[] chứa tên sự kiện hợp lệValidation zod tại lớp service
Chuyển trạng thái Transaction tuân theo state machine MQ-PayThuộc sở hữu của @nx/mq-pay
Phân phối webhook at-least-once đến subscriberWebhookDispatcherService với retry + timeout
Secret mã hóa nhất quán giữa các podLấy từ APP_ENV_APPLICATION_SECRET (phải giống nhau)

6. Hành vi Soft-delete

EntitySoft-deleteGhi chú
WebhookConfigƯu tiên deactivate qua status thay vì delete
Configuration (row payment)Migration seed tạo lại khi bootstrap

7. Trang liên quan

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.