chore: update project documentation, audit reports, and initialize IDE configuration files
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
This commit is contained in:
@@ -1,224 +1,223 @@
|
||||
# GoodGo Platform Payment Module - Security Review File Inventory
|
||||
# Kiểm Tra Bảo Mật Module Thanh Toán GoodGo Platform - Danh Sách File
|
||||
|
||||
## Overview
|
||||
Comprehensive file listing for the Order & Escrow entities security review in the payments module.
|
||||
Location: `/Users/velikho/Desktop/WORKING/goodgo-platform-ai/apps/api/src/modules/payments/`
|
||||
## Tổng Quan
|
||||
Danh sách file toàn diện cho đợt kiểm tra bảo mật các thực thể Order & Escrow trong module thanh toán.
|
||||
Vị trí: `/Users/velikho/Desktop/WORKING/goodgo-platform-ai/apps/api/src/modules/payments/`
|
||||
|
||||
---
|
||||
|
||||
## 1. DOMAIN LAYER - ENTITIES
|
||||
## 1. TẦNG DOMAIN - CÁC THỰC THỂ
|
||||
|
||||
### Core Entities
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `domain/entities/order.entity.ts` | **ORDER ENTITY** - Manages order lifecycle with state machine (CREATED→PAYMENT_PENDING→PAYMENT_CONFIRMED→ESCROW_HELD→SHIPPED→DELIVERED→ESCROW_RELEASED→COMPLETED). Validates transitions. Emits events: OrderCreatedEvent, OrderPaidEvent, OrderCancelledEvent. Critical fields: buyerId, sellerId, listingId, amount (Money VO), platformFee, sellerPayout. |
|
||||
| `domain/entities/escrow.entity.ts` | **ESCROW ENTITY** - Manages escrow lifecycle (PENDING→HELD→RELEASED/DISPUTED/REFUNDED). Stores escrow amount, fee, and calculated netPayout. Emits: EscrowHeldEvent, EscrowReleasedEvent, EscrowDisputedEvent. Validates state transitions. |
|
||||
| `domain/entities/payment.entity.ts` | **PAYMENT ENTITY** - Manages payment transactions (PENDING→PROCESSING→COMPLETED/FAILED/REFUNDED). Stores userId, provider (VNPAY/MOMO/ZALOPAY), type, amount, callbackData, idempotencyKey. Emits: PaymentCreatedEvent, PaymentCompletedEvent, PaymentFailedEvent, PaymentRefundedEvent. |
|
||||
### Các Thực Thể Cốt Lõi
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `domain/entities/order.entity.ts` | **THỰC THỂ ORDER** - Quản lý vòng đời đơn hàng với máy trạng thái (CREATED→PAYMENT_PENDING→PAYMENT_CONFIRMED→ESCROW_HELD→SHIPPED→DELIVERED→ESCROW_RELEASED→COMPLETED). Xác thực các chuyển trạng thái. Phát sự kiện: OrderCreatedEvent, OrderPaidEvent, OrderCancelledEvent. Các trường quan trọng: buyerId, sellerId, listingId, amount (Money VO), platformFee, sellerPayout. |
|
||||
| `domain/entities/escrow.entity.ts` | **THỰC THỂ ESCROW** - Quản lý vòng đời escrow (PENDING→HELD→RELEASED/DISPUTED/REFUNDED). Lưu trữ số tiền escrow, phí và netPayout đã tính. Phát: EscrowHeldEvent, EscrowReleasedEvent, EscrowDisputedEvent. Xác thực chuyển trạng thái. |
|
||||
| `domain/entities/payment.entity.ts` | **THỰC THỂ PAYMENT** - Quản lý giao dịch thanh toán (PENDING→PROCESSING→COMPLETED/FAILED/REFUNDED). Lưu trữ userId, provider (VNPAY/MOMO/ZALOPAY), type, amount, callbackData, idempotencyKey. Phát: PaymentCreatedEvent, PaymentCompletedEvent, PaymentFailedEvent, PaymentRefundedEvent. |
|
||||
|
||||
### Value Objects
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `domain/value-objects/money.vo.ts` | **MONEY VALUE OBJECT** - Wraps amounts as bigint in VND. Validates: amount > 0, max limit 999_999_999_999. Used for all financial amounts. |
|
||||
| `domain/value-objects/platform-fee.vo.ts` | **PLATFORM FEE VALUE OBJECT** - Calculates 5% platform fee. Methods: `fromOrderAmount()` (auto-calc 5%), `create()` (explicit amount). Validates fee >= 0. |
|
||||
### Các Value Object
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `domain/value-objects/money.vo.ts` | **VALUE OBJECT MONEY** - Bọc các số tiền dưới dạng bigint theo VND. Xác thực: amount > 0, giới hạn tối đa 999_999_999_999. Dùng cho tất cả các số tiền tài chính. |
|
||||
| `domain/value-objects/platform-fee.vo.ts` | **VALUE OBJECT PHÍ NỀN TẢNG** - Tính phí nền tảng 5%. Các phương thức: `fromOrderAmount()` (tự động tính 5%), `create()` (số tiền tường minh). Xác thực fee >= 0. |
|
||||
|
||||
---
|
||||
|
||||
## 2. DOMAIN LAYER - REPOSITORIES (Interfaces)
|
||||
## 2. TẦNG DOMAIN - REPOSITORY (Giao Diện)
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `domain/repositories/order.repository.ts` | **ORDER REPOSITORY INTERFACE** - Defines CRUD + query methods: findById, findByIdempotencyKey, findByBuyerId, findBySellerId, save, update. Idempotency protection. |
|
||||
| `domain/repositories/escrow.repository.ts` | **ESCROW REPOSITORY INTERFACE** - Defines: findById, findByOrderId, save, update. One escrow per order relationship. |
|
||||
| `domain/repositories/payment.repository.ts` | **PAYMENT REPOSITORY INTERFACE** - Defines: findById, findByProviderTxId, findByIdempotencyKey, findByUserId, save, update, **updateIfStatus** (atomic conditional update for race condition handling). |
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `domain/repositories/order.repository.ts` | **GIAO DIỆN ORDER REPOSITORY** - Định nghĩa các phương thức CRUD + truy vấn: findById, findByIdempotencyKey, findByBuyerId, findBySellerId, save, update. Bảo vệ idempotency. |
|
||||
| `domain/repositories/escrow.repository.ts` | **GIAO DIỆN ESCROW REPOSITORY** - Định nghĩa: findById, findByOrderId, save, update. Quan hệ một escrow trên một order. |
|
||||
| `domain/repositories/payment.repository.ts` | **GIAO DIỆN PAYMENT REPOSITORY** - Định nghĩa: findById, findByProviderTxId, findByIdempotencyKey, findByUserId, save, update, **updateIfStatus** (cập nhật có điều kiện nguyên tử để xử lý race condition). |
|
||||
|
||||
---
|
||||
|
||||
## 3. DOMAIN LAYER - EVENTS
|
||||
## 3. TẦNG DOMAIN - SỰ KIỆN
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `domain/events/order-created.event.ts` | Emitted when order created - contains orderId, buyerId, sellerId, listingId, amount |
|
||||
| `domain/events/order-paid.event.ts` | Emitted when payment confirmed - contains orderId, buyerId, amount |
|
||||
| `domain/events/order-cancelled.event.ts` | Emitted when order cancelled - contains orderId, buyerId, sellerId |
|
||||
| `domain/events/escrow-held.event.ts` | Emitted when escrow held - contains escrowId, orderId, amount |
|
||||
| `domain/events/escrow-released.event.ts` | Emitted when escrow released - contains escrowId, orderId, netPayout |
|
||||
| `domain/events/escrow-disputed.event.ts` | Emitted when escrow disputed - contains escrowId, orderId, reason |
|
||||
| `domain/events/payment-created.event.ts` | Emitted when payment created - contains paymentId, userId, provider, amount |
|
||||
| `domain/events/payment-completed.event.ts` | Emitted when payment completes - contains paymentId, userId, provider |
|
||||
| `domain/events/payment-failed.event.ts` | Emitted when payment fails - contains paymentId, userId, provider |
|
||||
| `domain/events/payment-refunded.event.ts` | Emitted when payment refunded - contains paymentId, userId, provider, amount |
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `domain/events/order-created.event.ts` | Phát khi tạo order - chứa orderId, buyerId, sellerId, listingId, amount |
|
||||
| `domain/events/order-paid.event.ts` | Phát khi thanh toán được xác nhận - chứa orderId, buyerId, amount |
|
||||
| `domain/events/order-cancelled.event.ts` | Phát khi order bị hủy - chứa orderId, buyerId, sellerId |
|
||||
| `domain/events/escrow-held.event.ts` | Phát khi escrow được giữ - chứa escrowId, orderId, amount |
|
||||
| `domain/events/escrow-released.event.ts` | Phát khi escrow được giải phóng - chứa escrowId, orderId, netPayout |
|
||||
| `domain/events/escrow-disputed.event.ts` | Phát khi escrow bị tranh chấp - chứa escrowId, orderId, reason |
|
||||
| `domain/events/payment-created.event.ts` | Phát khi tạo thanh toán - chứa paymentId, userId, provider, amount |
|
||||
| `domain/events/payment-completed.event.ts` | Phát khi thanh toán hoàn tất - chứa paymentId, userId, provider |
|
||||
| `domain/events/payment-failed.event.ts` | Phát khi thanh toán thất bại - chứa paymentId, userId, provider |
|
||||
| `domain/events/payment-refunded.event.ts` | Phát khi thanh toán được hoàn tiền - chứa paymentId, userId, provider, amount |
|
||||
|
||||
---
|
||||
|
||||
## 4. INFRASTRUCTURE LAYER - REPOSITORIES (Implementations)
|
||||
## 4. TẦNG CƠ SỞ HẠ TẦNG - REPOSITORY (Triển Khai)
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `infrastructure/repositories/prisma-order.repository.ts` | **ORDER REPOSITORY IMPL** - Prisma ORM implementation. Stores: id, buyerId, sellerId, listingId, status, amountVND, platformFeeVND, sellerPayoutVND, idempotencyKey, metadata. Handles order persistence. |
|
||||
| `infrastructure/repositories/prisma-escrow.repository.ts` | **ESCROW REPOSITORY IMPL** - Prisma ORM implementation. Stores: id, orderId, amountVND, feeVND, status, heldAt, releasedAt, disputeReason, disputedAt. Handles escrow persistence. |
|
||||
| `infrastructure/repositories/prisma-payment.repository.ts` | **PAYMENT REPOSITORY IMPL** - Prisma ORM. Stores: id, userId, transactionId, provider, type, amountVND, status, providerTxId, callbackData, idempotencyKey. **CRITICAL: `updateIfStatus()` uses conditional WHERE clause for atomic race condition prevention** (Line 84-109). |
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `infrastructure/repositories/prisma-order.repository.ts` | **TRIỂN KHAI ORDER REPOSITORY** - Triển khai Prisma ORM. Lưu trữ: id, buyerId, sellerId, listingId, status, amountVND, platformFeeVND, sellerPayoutVND, idempotencyKey, metadata. Xử lý lưu trữ order. |
|
||||
| `infrastructure/repositories/prisma-escrow.repository.ts` | **TRIỂN KHAI ESCROW REPOSITORY** - Triển khai Prisma ORM. Lưu trữ: id, orderId, amountVND, feeVND, status, heldAt, releasedAt, disputeReason, disputedAt. Xử lý lưu trữ escrow. |
|
||||
| `infrastructure/repositories/prisma-payment.repository.ts` | **TRIỂN KHAI PAYMENT REPOSITORY** - Prisma ORM. Lưu trữ: id, userId, transactionId, provider, type, amountVND, status, providerTxId, callbackData, idempotencyKey. **QUAN TRỌNG: `updateIfStatus()` sử dụng mệnh đề WHERE có điều kiện để ngăn race condition nguyên tử** (Dòng 84-109). |
|
||||
|
||||
---
|
||||
|
||||
## 5. INFRASTRUCTURE LAYER - PAYMENT GATEWAY SERVICES
|
||||
## 5. TẦNG CƠ SỞ HẠ TẦNG - DỊCH VỤ CỔNG THANH TOÁN
|
||||
|
||||
### Payment Gateway Interface
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `infrastructure/services/payment-gateway.interface.ts` | **GATEWAY INTERFACE** - Defines IPaymentGateway contract: createPaymentUrl(), verifyCallback(), refund(). CallbackVerifyResult includes: isValid, orderId, providerTxId, isSuccess, rawData. Sensitive for security. |
|
||||
### Giao Diện Cổng Thanh Toán
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `infrastructure/services/payment-gateway.interface.ts` | **GIAO DIỆN GATEWAY** - Định nghĩa hợp đồng IPaymentGateway: createPaymentUrl(), verifyCallback(), refund(). CallbackVerifyResult bao gồm: isValid, orderId, providerTxId, isSuccess, rawData. Nhạy cảm về bảo mật. |
|
||||
|
||||
### VNPay Service
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `infrastructure/services/vnpay.service.ts` | **VNPAY PAYMENT GATEWAY** - Implements IPaymentGateway. **CALLBACK VERIFICATION (Line 72-105)**: Extracts secure hash, removes it from data, sorts params, generates HMAC-SHA512, uses crypto.timingSafeEqual() for constant-time comparison. Amount multiplied by 100 for VND cents. Returns isValid, orderId (vnp_TxnRef), providerTxId (vnp_TransactionNo), isSuccess (responseCode === '00'). Refund support. |
|
||||
### Dịch Vụ VNPay
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `infrastructure/services/vnpay.service.ts` | **CỔNG THANH TOÁN VNPAY** - Triển khai IPaymentGateway. **XÁC MINH CALLBACK (Dòng 72-105)**: Trích xuất secure hash, loại bỏ khỏi dữ liệu, sắp xếp các tham số, tạo HMAC-SHA512, dùng crypto.timingSafeEqual() để so sánh thời gian cố định. Số tiền nhân 100 cho VND cents. Trả về isValid, orderId (vnp_TxnRef), providerTxId (vnp_TransactionNo), isSuccess (responseCode === '00'). Hỗ trợ hoàn tiền. |
|
||||
|
||||
### MoMo Service
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `infrastructure/services/momo.service.ts` | **MOMO PAYMENT GATEWAY** - Implements IPaymentGateway. **CALLBACK VERIFICATION (Line 102-147)**: Extracts signature from data, rebuilds raw signature with accessKey, amount, extraData, IPN/redirect URLs, orderId, etc. Uses HMAC-SHA256, constant-time comparison via crypto.timingSafeEqual(). Success check: resultCode === '0'. Refund support. Amount as Number (not bigint in API). |
|
||||
### Dịch Vụ MoMo
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `infrastructure/services/momo.service.ts` | **CỔNG THANH TOÁN MOMO** - Triển khai IPaymentGateway. **XÁC MINH CALLBACK (Dòng 102-147)**: Trích xuất chữ ký từ dữ liệu, xây dựng lại chữ ký thô với accessKey, amount, extraData, IPN/redirect URLs, orderId, v.v. Dùng HMAC-SHA256, so sánh thời gian cố định qua crypto.timingSafeEqual(). Kiểm tra thành công: resultCode === '0'. Hỗ trợ hoàn tiền. Amount dưới dạng Number (không phải bigint trong API). |
|
||||
|
||||
### ZaloPay Service
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `infrastructure/services/zalopay.service.ts` | **ZALOPAY PAYMENT GATEWAY** - Implements IPaymentGateway. **CALLBACK VERIFICATION (Line 98-144)**: Data passed as JSON string in 'data' field. MAC verified via HMAC-SHA256 with key2. Parses JSON data to extract app_trans_id and zp_trans_id. **SECURITY NOTE**: Catches JSON parse errors gracefully. Uses constant-time comparison. Refund support (key1). |
|
||||
### Dịch Vụ ZaloPay
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `infrastructure/services/zalopay.service.ts` | **CỔNG THANH TOÁN ZALOPAY** - Triển khai IPaymentGateway. **XÁC MINH CALLBACK (Dòng 98-144)**: Dữ liệu được truyền dưới dạng chuỗi JSON trong trường 'data'. MAC được xác minh qua HMAC-SHA256 với key2. Phân tích dữ liệu JSON để trích xuất app_trans_id và zp_trans_id. **LƯU Ý BẢO MẬT**: Xử lý lỗi phân tích JSON một cách duyên dáng. Dùng so sánh thời gian cố định. Hỗ trợ hoàn tiền (key1). |
|
||||
|
||||
### Payment Gateway Factory
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `infrastructure/services/payment-gateway.factory.ts` | **GATEWAY FACTORY** - Returns appropriate gateway instance (VNPay/MoMo/ZaloPay) based on provider enum. |
|
||||
### Factory Cổng Thanh Toán
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `infrastructure/services/payment-gateway.factory.ts` | **GATEWAY FACTORY** - Trả về instance gateway phù hợp (VNPay/MoMo/ZaloPay) dựa trên enum provider. |
|
||||
|
||||
---
|
||||
|
||||
## 6. APPLICATION LAYER - COMMANDS
|
||||
## 6. TẦNG ỨNG DỤNG - COMMAND
|
||||
|
||||
### Order Commands
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `application/commands/create-order/create-order.command.ts` | **CREATE ORDER COMMAND** - Input: buyerId, sellerId, listingId, amountVND, idempotencyKey. Payload object. |
|
||||
| `application/commands/create-order/create-order.handler.ts` | **CREATE ORDER HANDLER** - Idempotency check via findByIdempotencyKey. Validates amount (Money VO). Calculates platform fee (5%) and seller payout. Creates OrderEntity + EscrowEntity (PENDING status). Saves both. Emits events. |
|
||||
| `application/commands/cancel-order/cancel-order.command.ts` | **CANCEL ORDER COMMAND** - Input: orderId, userId, reason. |
|
||||
| `application/commands/cancel-order/cancel-order.handler.ts` | **CANCEL ORDER HANDLER** - Verifies user owns order, validates state transition via entity.markCancelled(), saves, emits events. |
|
||||
### Các Order Command
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `application/commands/create-order/create-order.command.ts` | **CREATE ORDER COMMAND** - Đầu vào: buyerId, sellerId, listingId, amountVND, idempotencyKey. Đối tượng payload. |
|
||||
| `application/commands/create-order/create-order.handler.ts` | **CREATE ORDER HANDLER** - Kiểm tra idempotency qua findByIdempotencyKey. Xác thực amount (Money VO). Tính phí nền tảng (5%) và seller payout. Tạo OrderEntity + EscrowEntity (trạng thái PENDING). Lưu cả hai. Phát sự kiện. |
|
||||
| `application/commands/cancel-order/cancel-order.command.ts` | **CANCEL ORDER COMMAND** - Đầu vào: orderId, userId, reason. |
|
||||
| `application/commands/cancel-order/cancel-order.handler.ts` | **CANCEL ORDER HANDLER** - Xác minh người dùng sở hữu order, xác thực chuyển trạng thái qua entity.markCancelled(), lưu, phát sự kiện. |
|
||||
|
||||
### Escrow Commands
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `application/commands/hold-escrow/hold-escrow.command.ts` | **HOLD ESCROW COMMAND** - Input: orderId. Admin-only operation. |
|
||||
| `application/commands/hold-escrow/hold-escrow.handler.ts` | **HOLD ESCROW HANDLER (Line 23-67)** - Fetches order + escrow by orderId. Calls escrow.hold() state transition. Updates both entities. Emits EscrowHeldEvent. **SECURITY NOTE**: No Redis lock - potential race condition if multiple concurrent requests. |
|
||||
| `application/commands/release-escrow/release-escrow.command.ts` | **RELEASE ESCROW COMMAND** - Input: orderId. Admin-only operation. |
|
||||
| `application/commands/release-escrow/release-escrow.handler.ts` | **RELEASE ESCROW HANDLER (Line 24-45)** - Fetches order + escrow by orderId. Calls escrow.release() state transition. Updates both entities. Emits EscrowReleasedEvent with netPayout. **SECURITY NOTE**: No Redis lock - potential race condition. |
|
||||
### Các Escrow Command
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `application/commands/hold-escrow/hold-escrow.command.ts` | **HOLD ESCROW COMMAND** - Đầu vào: orderId. Chỉ dành cho Admin. |
|
||||
| `application/commands/hold-escrow/hold-escrow.handler.ts` | **HOLD ESCROW HANDLER (Dòng 23-67)** - Lấy order + escrow theo orderId. Gọi escrow.hold() để chuyển trạng thái. Cập nhật cả hai thực thể. Phát EscrowHeldEvent. **LƯU Ý BẢO MẬT**: Không có Redis lock - tiềm ẩn race condition nếu có nhiều yêu cầu đồng thời. |
|
||||
| `application/commands/release-escrow/release-escrow.command.ts` | **RELEASE ESCROW COMMAND** - Đầu vào: orderId. Chỉ dành cho Admin. |
|
||||
| `application/commands/release-escrow/release-escrow.handler.ts` | **RELEASE ESCROW HANDLER (Dòng 24-45)** - Lấy order + escrow theo orderId. Gọi escrow.release() để chuyển trạng thái. Cập nhật cả hai thực thể. Phát EscrowReleasedEvent với netPayout. **LƯU Ý BẢO MẬT**: Không có Redis lock - tiềm ẩn race condition. |
|
||||
|
||||
### Payment Commands
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `application/commands/create-payment/create-payment.command.ts` | **CREATE PAYMENT COMMAND** - Input: userId, provider, type, amountVND, description, returnUrl, ipAddress, transactionId, idempotencyKey. |
|
||||
| `application/commands/create-payment/create-payment.handler.ts` | **CREATE PAYMENT HANDLER** - Idempotency check. Validates amount (Money VO). Gets payment gateway. Calls createPaymentUrl(). Creates PaymentEntity (PENDING status). Saves. Emits PaymentCreatedEvent. Returns paymentUrl for frontend redirect. |
|
||||
| `application/commands/refund-payment/refund-payment.command.ts` | **REFUND PAYMENT COMMAND** - Input: paymentId, reason, userId. Admin command. |
|
||||
| `application/commands/refund-payment/refund-payment.handler.ts` | **REFUND PAYMENT HANDLER** - Verifies payment exists, calls gateway.refund() with provider-specific args, updates payment status to REFUNDED, emits PaymentRefundedEvent. |
|
||||
### Các Payment Command
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `application/commands/create-payment/create-payment.command.ts` | **CREATE PAYMENT COMMAND** - Đầu vào: userId, provider, type, amountVND, description, returnUrl, ipAddress, transactionId, idempotencyKey. |
|
||||
| `application/commands/create-payment/create-payment.handler.ts` | **CREATE PAYMENT HANDLER** - Kiểm tra idempotency. Xác thực amount (Money VO). Lấy payment gateway. Gọi createPaymentUrl(). Tạo PaymentEntity (trạng thái PENDING). Lưu. Phát PaymentCreatedEvent. Trả về paymentUrl để frontend chuyển hướng. |
|
||||
| `application/commands/refund-payment/refund-payment.command.ts` | **REFUND PAYMENT COMMAND** - Đầu vào: paymentId, reason, userId. Lệnh dành cho Admin. |
|
||||
| `application/commands/refund-payment/refund-payment.handler.ts` | **REFUND PAYMENT HANDLER** - Xác minh thanh toán tồn tại, gọi gateway.refund() với các tham số đặc thù nhà cung cấp, cập nhật trạng thái thanh toán thành REFUNDED, phát PaymentRefundedEvent. |
|
||||
|
||||
### Callback Handler (CRITICAL)
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `application/commands/handle-callback/handle-callback.command.ts` | **HANDLE CALLBACK COMMAND** - Input: provider (PaymentProvider enum), callbackData (Record<string, string>). |
|
||||
| `application/commands/handle-callback/handle-callback.handler.ts` | **HANDLE CALLBACK HANDLER (Line 32-110)** - **CRITICAL SECURITY FILE**. Gets gateway, calls verifyCallback() (validates signature). If invalid: throws ValidationException. If valid: **Uses `paymentRepo.updateIfStatus()` with conditional WHERE ['PENDING', 'PROCESSING']** (Line 48-55) - atomic update to prevent duplicate processing. If update returns null: checks if payment exists (already processed - idempotent response). If success: calls payment.emitCompleted(), else payment.emitFailed(). Publishes events. **STRONG RACE CONDITION PROTECTION via conditional update**. |
|
||||
### Handler Callback (QUAN TRỌNG)
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `application/commands/handle-callback/handle-callback.command.ts` | **HANDLE CALLBACK COMMAND** - Đầu vào: provider (enum PaymentProvider), callbackData (Record<string, string>). |
|
||||
| `application/commands/handle-callback/handle-callback.handler.ts` | **HANDLE CALLBACK HANDLER (Dòng 32-110)** - **FILE BẢO MẬT QUAN TRỌNG**. Lấy gateway, gọi verifyCallback() (xác thực chữ ký). Nếu không hợp lệ: ném ValidationException. Nếu hợp lệ: **Dùng `paymentRepo.updateIfStatus()` với WHERE có điều kiện ['PENDING', 'PROCESSING']** (Dòng 48-55) - cập nhật nguyên tử để ngăn xử lý trùng lặp. Nếu cập nhật trả về null: kiểm tra xem thanh toán có tồn tại không (đã xử lý - phản hồi idempotent). Nếu thành công: gọi payment.emitCompleted(), ngược lại payment.emitFailed(). Phát sự kiện. **BẢO VỆ RACE CONDITION MẠNH qua cập nhật có điều kiện**. |
|
||||
|
||||
---
|
||||
|
||||
## 7. APPLICATION LAYER - QUERIES
|
||||
## 7. TẦNG ỨNG DỤNG - QUERY
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `application/queries/get-order-status/get-order-status.query.ts` | Query: Input orderId, userId (for authorization). |
|
||||
| `application/queries/get-order-status/get-order-status.handler.ts` | Fetches order, verifies ownership (buyer/seller), returns status + details. |
|
||||
| `application/queries/get-payment-status/get-payment-status.query.ts` | Query: Input paymentId, userId. |
|
||||
| `application/queries/get-payment-status/get-payment-status.handler.ts` | Fetches payment, verifies ownership, returns status + details. |
|
||||
| `application/queries/list-transactions/list-transactions.query.ts` | Query: Input userId, status (optional), limit, offset. |
|
||||
| `application/queries/list-transactions/list-transactions.handler.ts` | Lists payments for user with pagination, filters by status if provided. |
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `application/queries/get-order-status/get-order-status.query.ts` | Query: Đầu vào orderId, userId (để phân quyền). |
|
||||
| `application/queries/get-order-status/get-order-status.handler.ts` | Lấy order, xác minh quyền sở hữu (buyer/seller), trả về trạng thái + chi tiết. |
|
||||
| `application/queries/get-payment-status/get-payment-status.query.ts` | Query: Đầu vào paymentId, userId. |
|
||||
| `application/queries/get-payment-status/get-payment-status.handler.ts` | Lấy thanh toán, xác minh quyền sở hữu, trả về trạng thái + chi tiết. |
|
||||
| `application/queries/list-transactions/list-transactions.query.ts` | Query: Đầu vào userId, status (tùy chọn), limit, offset. |
|
||||
| `application/queries/list-transactions/list-transactions.handler.ts` | Liệt kê các thanh toán của người dùng với phân trang, lọc theo status nếu được cung cấp. |
|
||||
|
||||
---
|
||||
|
||||
## 8. PRESENTATION LAYER - CONTROLLERS
|
||||
## 8. TẦNG TRÌNH BÀY - CONTROLLER
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `presentation/controllers/orders.controller.ts` | **ORDERS CONTROLLER** - Routes: POST / (create order), GET /:id (status), POST /:id/cancel (cancel), POST /:id/escrow/hold (admin), POST /:id/escrow/release (admin). Auth: JwtAuthGuard, RolesGuard for admin ops. Converts DTO to commands. |
|
||||
| `presentation/controllers/payments.controller.ts` | **PAYMENTS CONTROLLER** - Routes: POST / (create payment), POST /callback/:provider (webhook - **Throttle + EndpointRateLimit**), GET /:id (status), GET (list), POST /:id/refund (admin refund). **CRITICAL: Callback endpoint has rate limiting (Throttle + EndpointRateLimitGuard)** - prevents callback flooding. |
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `presentation/controllers/orders.controller.ts` | **ORDERS CONTROLLER** - Các route: POST / (tạo order), GET /:id (trạng thái), POST /:id/cancel (hủy), POST /:id/escrow/hold (admin), POST /:id/escrow/release (admin). Xác thực: JwtAuthGuard, RolesGuard cho các thao tác admin. Chuyển đổi DTO thành command. |
|
||||
| `presentation/controllers/payments.controller.ts` | **PAYMENTS CONTROLLER** - Các route: POST / (tạo thanh toán), POST /callback/:provider (webhook - **Throttle + EndpointRateLimit**), GET /:id (trạng thái), GET (danh sách), POST /:id/refund (admin hoàn tiền). **QUAN TRỌNG: Endpoint callback có giới hạn tốc độ (Throttle + EndpointRateLimitGuard)** - ngăn chặn lũ lụt callback. |
|
||||
|
||||
---
|
||||
|
||||
## 9. PRESENTATION LAYER - DTOs
|
||||
## 9. TẦNG TRÌNH BÀY - DTO
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `presentation/dto/create-order.dto.ts` | DTO: sellerId, listingId, amountVND (string), idempotencyKey (optional). |
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `presentation/dto/create-order.dto.ts` | DTO: sellerId, listingId, amountVND (string), idempotencyKey (tùy chọn). |
|
||||
| `presentation/dto/cancel-order.dto.ts` | DTO: reason (string). |
|
||||
| `presentation/dto/create-payment.dto.ts` | DTO: provider (enum), type (enum), amountVND (string), description, returnUrl, transactionId (optional), idempotencyKey (optional). |
|
||||
| `presentation/dto/create-payment.dto.ts` | DTO: provider (enum), type (enum), amountVND (string), description, returnUrl, transactionId (tùy chọn), idempotencyKey (tùy chọn). |
|
||||
| `presentation/dto/refund-payment.dto.ts` | DTO: reason (string). |
|
||||
| `presentation/dto/list-transactions.dto.ts` | DTO: status (optional), limit, offset. |
|
||||
| `presentation/dto/list-transactions.dto.ts` | DTO: status (tùy chọn), limit, offset. |
|
||||
|
||||
---
|
||||
|
||||
## 10. MODULE & TEST FILES
|
||||
## 10. MODULE & CÁC FILE KIỂM THỬ
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `payments.module.ts` | **MODULE SETUP** - Registers repositories, services, handlers, controllers. |
|
||||
| `index.ts` (module level) | Exports public API. |
|
||||
| `infrastructure/repositories/index.ts` | Exports repository implementations. |
|
||||
| `infrastructure/services/index.ts` | Exports gateway services. |
|
||||
| `application/index.ts` | Exports command/query handlers. |
|
||||
| `domain/repositories/index.ts` | Exports repository interfaces. |
|
||||
| `domain/entities/index.ts` | Exports entities. |
|
||||
| `domain/value-objects/index.ts` | Exports VOs. |
|
||||
| `domain/events/index.ts` | Exports domain events. |
|
||||
| `presentation/controllers/index.ts` | Exports controllers. |
|
||||
| `presentation/dto/index.ts` | Exports DTOs. |
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `payments.module.ts` | **CÀI ĐẶT MODULE** - Đăng ký các repository, service, handler, controller. |
|
||||
| `index.ts` (cấp module) | Xuất API công khai. |
|
||||
| `infrastructure/repositories/index.ts` | Xuất các triển khai repository. |
|
||||
| `infrastructure/services/index.ts` | Xuất các dịch vụ gateway. |
|
||||
| `application/index.ts` | Xuất các handler command/query. |
|
||||
| `domain/repositories/index.ts` | Xuất các giao diện repository. |
|
||||
| `domain/entities/index.ts` | Xuất các thực thể. |
|
||||
| `domain/value-objects/index.ts` | Xuất các VO. |
|
||||
| `domain/events/index.ts` | Xuất các sự kiện domain. |
|
||||
| `presentation/controllers/index.ts` | Xuất các controller. |
|
||||
| `presentation/dto/index.ts` | Xuất các DTO. |
|
||||
|
||||
### Test Files
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| `domain/__tests__/order.entity.spec.ts` | Order entity unit tests - state machine, transitions |
|
||||
| `domain/__tests__/escrow.entity.spec.ts` | Escrow entity unit tests - hold, release, dispute, refund |
|
||||
| `domain/__tests__/payment.entity.spec.ts` | Payment entity unit tests |
|
||||
| `domain/__tests__/money.vo.spec.ts` | Money VO validation tests |
|
||||
| `domain/__tests__/platform-fee.vo.spec.ts` | Platform fee calculation tests |
|
||||
| `domain/__tests__/payment-events.spec.ts` | Domain event emission tests |
|
||||
| `application/__tests__/create-order.handler.spec.ts` | Create order handler tests |
|
||||
| `application/__tests__/create-payment.handler.spec.ts` | Create payment handler tests |
|
||||
| `application/__tests__/handle-callback.handler.spec.ts` | Callback handling tests |
|
||||
| `application/__tests__/handle-callback-edge-cases.handler.spec.ts` | Callback edge cases (race conditions, idempotency) |
|
||||
| `application/__tests__/get-payment-status.handler.spec.ts` | Payment status query tests |
|
||||
| `application/__tests__/refund-payment.handler.spec.ts` | Refund command tests |
|
||||
| `application/__tests__/list-transactions.handler.spec.ts` | List transactions query tests |
|
||||
| `infrastructure/__tests__/vnpay.service.spec.ts` | VNPay gateway tests - signature verification |
|
||||
| `infrastructure/__tests__/momo.service.spec.ts` | MoMo gateway tests - HMAC-SHA256 verification |
|
||||
| `infrastructure/__tests__/zalopay.service.spec.ts` | ZaloPay gateway tests - JSON parsing + MAC verification |
|
||||
| `infrastructure/__tests__/payment-gateway.factory.spec.ts` | Factory pattern tests |
|
||||
### Các File Kiểm Thử
|
||||
| File | Mô tả |
|
||||
|------|-------|
|
||||
| `domain/__tests__/order.entity.spec.ts` | Kiểm thử đơn vị thực thể Order - máy trạng thái, các chuyển trạng thái |
|
||||
| `domain/__tests__/escrow.entity.spec.ts` | Kiểm thử đơn vị thực thể Escrow - hold, release, dispute, refund |
|
||||
| `domain/__tests__/payment.entity.spec.ts` | Kiểm thử đơn vị thực thể Payment |
|
||||
| `domain/__tests__/money.vo.spec.ts` | Kiểm thử xác thực Money VO |
|
||||
| `domain/__tests__/platform-fee.vo.spec.ts` | Kiểm thử tính toán phí nền tảng |
|
||||
| `domain/__tests__/payment-events.spec.ts` | Kiểm thử phát sự kiện domain |
|
||||
| `application/__tests__/create-order.handler.spec.ts` | Kiểm thử handler tạo order |
|
||||
| `application/__tests__/create-payment.handler.spec.ts` | Kiểm thử handler tạo thanh toán |
|
||||
| `application/__tests__/handle-callback.handler.spec.ts` | Kiểm thử xử lý callback |
|
||||
| `application/__tests__/handle-callback-edge-cases.handler.spec.ts` | Kiểm thử các trường hợp biên callback (race condition, idempotency) |
|
||||
| `application/__tests__/get-payment-status.handler.spec.ts` | Kiểm thử query trạng thái thanh toán |
|
||||
| `application/__tests__/refund-payment.handler.spec.ts` | Kiểm thử lệnh hoàn tiền |
|
||||
| `application/__tests__/list-transactions.handler.spec.ts` | Kiểm thử query danh sách giao dịch |
|
||||
| `infrastructure/__tests__/vnpay.service.spec.ts` | Kiểm thử gateway VNPay - xác minh chữ ký |
|
||||
| `infrastructure/__tests__/momo.service.spec.ts` | Kiểm thử gateway MoMo - xác minh HMAC-SHA256 |
|
||||
| `infrastructure/__tests__/zalopay.service.spec.ts` | Kiểm thử gateway ZaloPay - phân tích JSON + xác minh MAC |
|
||||
| `infrastructure/__tests__/payment-gateway.factory.spec.ts` | Kiểm thử mẫu factory |
|
||||
|
||||
---
|
||||
|
||||
## SECURITY FINDINGS SUMMARY
|
||||
## TÓM TẮT KẾT QUẢ BẢO MẬT
|
||||
|
||||
### ✅ STRONG SECURITY MEASURES
|
||||
1. **Callback Signature Verification**: All 3 providers (VNPay, MoMo, ZaloPay) verify HMAC signatures using `crypto.timingSafeEqual()` for constant-time comparison
|
||||
2. **Atomic Race Condition Prevention**: `paymentRepo.updateIfStatus()` uses conditional WHERE clause to atomically update only if in PENDING/PROCESSING state
|
||||
3. **Idempotency Protection**: Orders + Payments check idempotencyKey to prevent duplicate operations
|
||||
4. **Rate Limiting**: Callback endpoint has Throttle + EndpointRateLimit decorators
|
||||
5. **Authorization**: All endpoints require JwtAuthGuard; admin operations require RolesGuard
|
||||
6. **Amount Validation**: Money VO validates: 0 < amount ≤ 999_999_999_999 VND
|
||||
7. **State Machine Validation**: Order + Escrow enforce valid status transitions
|
||||
### ✅ CÁC BIỆN PHÁP BẢO MẬT MẠNH
|
||||
1. **Xác Minh Chữ Ký Callback**: Cả 3 nhà cung cấp (VNPay, MoMo, ZaloPay) đều xác minh chữ ký HMAC sử dụng `crypto.timingSafeEqual()` để so sánh thời gian cố định
|
||||
2. **Ngăn Chặn Race Condition Nguyên Tử**: `paymentRepo.updateIfStatus()` sử dụng mệnh đề WHERE có điều kiện để cập nhật nguyên tử chỉ khi ở trạng thái PENDING/PROCESSING
|
||||
3. **Bảo Vệ Idempotency**: Order + Payment kiểm tra idempotencyKey để ngăn chặn các thao tác trùng lặp
|
||||
4. **Giới Hạn Tốc Độ**: Endpoint callback có decorator Throttle + EndpointRateLimit
|
||||
5. **Phân Quyền**: Tất cả endpoint yêu cầu JwtAuthGuard; các thao tác admin yêu cầu RolesGuard
|
||||
6. **Xác Thực Số Tiền**: Money VO xác thực: 0 < amount ≤ 999_999_999_999 VND
|
||||
7. **Xác Thực Máy Trạng Thái**: Order + Escrow thực thi các chuyển trạng thái hợp lệ
|
||||
|
||||
### ⚠️ SECURITY CONCERNS (NEEDS REVIEW)
|
||||
1. **Hold/Release Escrow Race Conditions**: No Redis lock on hold-escrow/release-escrow handlers - concurrent requests could cause state inconsistencies
|
||||
2. **No Distributed Lock Mechanism**: Escrow operations not protected against simultaneous requests from different servers
|
||||
3. **Callback Processing Idempotency**: While paymentRepo.updateIfStatus() prevents double-processing, idempotency check doesn't verify callback signature consistency
|
||||
4. **Payment Provider Secrets**: Keys loaded from ConfigService - verify env variable encryption at rest
|
||||
5. **Refund Authorization**: Only ADMIN role check - no business logic validation (e.g., refund window, max refund amount)
|
||||
6. **Order/Escrow Update Race**: While holds are atomic for payments, order + escrow updates in handlers are done sequentially (2 DB calls), not atomically
|
||||
### ⚠️ VẤN ĐỀ BẢO MẬT (CẦN KIỂM TRA)
|
||||
1. **Race Condition Hold/Release Escrow**: Không có Redis lock trên các handler hold-escrow/release-escrow - các yêu cầu đồng thời có thể gây ra sự không nhất quán trạng thái
|
||||
2. **Không Có Cơ Chế Khóa Phân Tán**: Các thao tác escrow không được bảo vệ trước các yêu cầu đồng thời từ các máy chủ khác nhau
|
||||
3. **Idempotency Xử Lý Callback**: Mặc dù paymentRepo.updateIfStatus() ngăn xử lý hai lần, kiểm tra idempotency không xác minh tính nhất quán của chữ ký callback
|
||||
4. **Bí Mật Nhà Cung Cấp Thanh Toán**: Các khóa được tải từ ConfigService - xác minh mã hóa biến môi trường khi lưu trữ
|
||||
5. **Phân Quyền Hoàn Tiền**: Chỉ kiểm tra vai trò ADMIN - không có xác thực logic nghiệp vụ (ví dụ: thời hạn hoàn tiền, số tiền hoàn tiền tối đa)
|
||||
6. **Race Update Order/Escrow**: Mặc dù hold là nguyên tử đối với thanh toán, cập nhật order + escrow trong handler được thực hiện tuần tự (2 lần gọi DB), không nguyên tử
|
||||
|
||||
---
|
||||
|
||||
## FILES NOT FOUND / NOT IN SCOPE
|
||||
- ❌ **Redis Lock Usage**: No Redis locks found in payments module. CONCERN: Critical for escrow hold/release.
|
||||
- ❌ **Shared Payment Utilities**: No external payment utility modules referenced
|
||||
- ❌ **Encryption for Payment Data**: No field-level encryption for sensitive payment data (though field-encryption service exists in shared module)
|
||||
|
||||
## CÁC FILE KHÔNG TÌM THẤY / NGOÀI PHẠM VI
|
||||
- ❌ **Sử Dụng Redis Lock**: Không tìm thấy Redis lock trong module thanh toán. MỐI LO NGẠI: Quan trọng cho escrow hold/release.
|
||||
- ❌ **Tiện Ích Thanh Toán Dùng Chung**: Không có module tiện ích thanh toán bên ngoài nào được tham chiếu
|
||||
- ❌ **Mã Hóa Dữ Liệu Thanh Toán**: Không có mã hóa cấp trường cho dữ liệu thanh toán nhạy cảm (mặc dù dịch vụ field-encryption tồn tại trong module shared)
|
||||
|
||||
Reference in New Issue
Block a user