# Kiểm Tra Bảo Mật Module Thanh Toán GoodGo Platform - Danh Sách File

## 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. TẦNG DOMAIN - CÁC THỰC THỂ

### 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. |

### 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. TẦNG DOMAIN - REPOSITORY (Giao Diện)

| 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. TẦNG DOMAIN - SỰ KIỆN

| 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. TẦNG CƠ SỞ HẠ TẦNG - REPOSITORY (Triển Khai)

| 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. TẦNG CƠ SỞ HẠ TẦNG - DỊCH VỤ CỔNG THANH TOÁN

### 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. |

### 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. |

### 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). |

### 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). |

### 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. TẦNG ỨNG DỤNG - COMMAND

### 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. |

### 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. |

### 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. |

### 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. TẦNG ỨNG DỤNG - QUERY

| 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. TẦNG TRÌNH BÀY - CONTROLLER

| 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. TẦNG TRÌNH BÀY - DTO

| 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 (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 (tùy chọn), limit, offset. |

---

## 10. MODULE & CÁC FILE KIỂM THỬ

| 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. |

### 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 |

---

## TÓM TẮT KẾT QUẢ BẢO MẬT

### ✅ 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ệ

### ⚠️ 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ử

---

## 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)
