# Tóm Tắt Kiểm Tra Định Giá → Thanh Toán GoodGo

## 🎯 Tổng Quan Nhanh

| Khía cạnh | Trạng thái | Chi tiết chính |
|--------|--------|-------------|
| **Trang Định Giá** | ✅ Hoàn chỉnh | `/pricing` hiển thị 4 gói, chuyển đổi tháng/năm |
| **API Gói dịch vụ** | ✅ Hoàn chỉnh | `GET /subscriptions/plans` với dữ liệu dự phòng |
| **Backend Đăng ký** | ✅ Hoàn chỉnh | Mẫu CQRS, thực thể miền, kho lưu trữ |
| **Tích hợp Cổng Thanh toán** | ✅ Hoàn chỉnh | VNPay, MoMo, ZaloPay sẵn sàng sử dụng |
| **API Thanh toán** | ✅ Hoàn chỉnh | Tạo thanh toán, lấy trạng thái, xử lý callback |
| **Mô hình Cơ sở dữ liệu** | ✅ Hoàn chỉnh | Plan, Subscription, Payment, UsageRecord |
| **Luồng Thanh toán Frontend** | ❌ THIẾU | Không có modal/trang để khởi tạo thanh toán |
| **Trình xử lý Trả về Thanh toán** | ❌ THIẾU | Không có trang xử lý chuyển hướng từ cổng |
| **Tự động Tạo Đăng ký** | ❌ THIẾU | Quy trình thủ công sau khi thanh toán |

---

## 🏗️ Tổng Quan Kiến Trúc

### Stack Frontend
```
Trang Định Giá (/pricing)
    ↓ hook usePlans()
    ↓ React Query
API Client: subscriptionApi.getPlans()
    ↓ GET /subscriptions/plans
Backend (endpoint /subscriptions/plans)
```

### Luồng Thanh toán (Hiện bị Hỏng)
```
Trang Định Giá (Chọn Gói)
    ✅ Hiển thị gói, giá, tính năng
    ❌ Nút CTA trỏ đến /register thay vì thanh toán

[THIẾU] Modal/Trang Thanh toán
    ❌ Chưa triển khai
    ❌ Không có xác nhận gói
    ❌ Không có lựa chọn phương thức thanh toán

[THIẾU] Tạo Thanh toán
    ❌ Cần gọi POST /payments
    ❌ Cần chuyển hướng đến paymentUrl

Cổng Thanh toán (VNPay/MoMo/ZaloPay)
    ✅ Backend có triển khai createPaymentUrl
    ✅ Xác minh chữ ký đã sẵn sàng
    ❌ Chưa triển khai chuyển hướng frontend

[THIẾU] Trình xử lý Trả về
    ❌ Không có trang nhận callback từ cổng
    ❌ Không có cơ chế poll trạng thái thanh toán
    ❌ Không có tạo đăng ký

[THIẾU] Tạo Đăng ký
    ❌ Cần gọi POST /subscriptions
    ❌ Cần hiển thị thông báo thành công

Bảng điều khiển/Trang chủ
    ✅ Có trang thanh toán để xem lịch sử
    ❌ Không có giao diện quản lý đăng ký
```

---

## 📁 Cấu Trúc Tệp Frontend

```
apps/web/
├── app/[locale]/(public)/pricing/
│   └── page.tsx                          ✅ Trang định giá chính
│
├── lib/
│   ├── subscription-api.ts               ✅ API client & types (PlanDto, CreateSubscriptionResult, v.v.)
│   ├── payment-api.ts                    ✅ API client & types (CreatePaymentResult, PaymentStatusDto, v.v.)
│   └── hooks/
│       ├── use-subscription.ts           ✅ usePlans(), useBillingHistory(), useQuota()
│       └── use-payments.ts               ✅ useTransactions(), usePaymentStatus()
│
├── app/[locale]/(dashboard)/dashboard/
│   └── payments/page.tsx                 ✅ Trình xem lịch sử giao dịch
│
└── components/
    └── (cần thêm component mới cho thanh toán)
        ├── checkout-modal/               ❌ Thiếu
        ├── payment-provider-select/      ❌ Thiếu
        └── subscription-status/          ❌ Thiếu
```

---

## 🔧 Cấu Trúc Tệp Backend

```
apps/api/src/modules/
│
├── subscriptions/
│   ├── presentation/
│   │   ├── controllers/subscriptions.controller.ts       ✅ 8 endpoint
│   │   └── dto/
│   │       ├── create-subscription.dto.ts                ✅ { planTier, billingCycle }
│   │       ├── upgrade-subscription.dto.ts               ✅
│   │       ├── cancel-subscription.dto.ts                ✅
│   │       └── meter-usage.dto.ts                        ✅
│   │
│   ├── application/
│   │   ├── commands/
│   │   │   ├── create-subscription/                      ✅ Tạo đăng ký
│   │   │   ├── upgrade-subscription/                     ✅
│   │   │   ├── cancel-subscription/                      ✅
│   │   │   └── meter-usage/                              ✅
│   │   └── queries/
│   │       ├── get-plan/                                 ✅ Trả về PlanDto[]
│   │       ├── check-quota/                              ✅
│   │       └── get-billing-history/                      ✅
│   │
│   ├── domain/
│   │   ├── entities/subscription.entity.ts               ✅ Aggregate CQRS
│   │   ├── events/                                       ✅ 5 sự kiện miền
│   │   └── repositories/subscription.repository.ts       ✅ Interface
│   │
│   └── infrastructure/
│       ├── repositories/prisma-subscription.repository.ts ✅
│       └── event-handlers/listing-created-usage.handler.ts ✅
│
└── payments/
    ├── presentation/
    │   ├── controllers/payments.controller.ts            ✅ 5 endpoint
    │   └── dto/
    │       ├── create-payment.dto.ts                     ✅ { provider, type, amountVND, description, returnUrl }
    │       ├── refund-payment.dto.ts                     ✅
    │       └── list-transactions.dto.ts                  ✅
    │
    ├── application/
    │   ├── commands/
    │   │   ├── create-payment/                           ✅ Logic tạo thanh toán chính
    │   │   ├── handle-callback/                          ✅ Trình xử lý webhook
    │   │   └── refund-payment/                           ✅
    │   └── queries/
    │       ├── get-payment-status/                       ✅ Poll trạng thái
    │       └── list-transactions/                        ✅
    │
    ├── domain/
    │   ├── entities/payment.entity.ts                    ✅ Aggregate CQRS
    │   ├── events/                                       ✅ 4 sự kiện miền
    │   ├── value-objects/money.vo.ts                     ✅
    │   └── repositories/payment.repository.ts            ✅ Interface
    │
    └── infrastructure/
        ├── repositories/prisma-payment.repository.ts     ✅
        └── services/
            ├── payment-gateway.interface.ts              ✅ IPaymentGateway
            ├── payment-gateway.factory.ts                ✅ Lấy cổng thanh toán phù hợp
            ├── vnpay.service.ts                          ✅ createPaymentUrl() + verifyCallback()
            ├── momo.service.ts                           ✅ createPaymentUrl() + verifyCallback()
            └── zalopay.service.ts                        ✅ createPaymentUrl() + verifyCallback()
```

---

## 🔌 Tóm Tắt Endpoint API

### Endpoint Đăng ký
```
GET    /subscriptions/plans                    → PlanDto[]
GET    /subscriptions/plans/:tier              → PlanDto
POST   /subscriptions                          → CreateSubscriptionResult (yêu cầu xác thực)
PUT    /subscriptions/upgrade                  → UpgradeSubscriptionResult (yêu cầu xác thực)
DELETE /subscriptions                          → CancelSubscriptionResult (yêu cầu xác thực)
POST   /subscriptions/usage                    → MeterUsageResult (yêu cầu xác thực)
GET    /subscriptions/quota/:metric            → QuotaCheckResult (yêu cầu xác thực)
GET    /subscriptions/billing                  → BillingHistoryDto (yêu cầu xác thực)
```

### Endpoint Thanh toán
```
POST   /payments                               → CreatePaymentResult (yêu cầu xác thực)
POST   /payments/callback/:provider            → HandleCallbackResult (webhook)
GET    /payments/:id                           → PaymentStatusDto (yêu cầu xác thực)
GET    /payments                               → TransactionListDto (yêu cầu xác thực)
POST   /payments/:id/refund                    → RefundPaymentResult (chỉ quản trị viên)
```

---

## 💰 Các Gói Định Giá

```javascript
const TIERS = [
  {
    tier: 'FREE',
    monthlyVND: '0',
    yearlyVND: '0',
    maxListings: 3,
    maxSearches: 5,
  },
  {
    tier: 'AGENT_PRO',
    monthlyVND: '499,000',
    yearlyVND: '4,990,000',
    maxListings: 50,
    maxSearches: 30,
    popular: true,
  },
  {
    tier: 'INVESTOR',
    monthlyVND: '999,000',
    yearlyVND: '9,990,000',
    maxListings: 20,
    maxSearches: 100,
  },
  {
    tier: 'ENTERPRISE',
    monthlyVND: '4,990,000',
    yearlyVND: '49,900,000',
    maxListings: -1,      // Không giới hạn
    maxSearches: -1,      // Không giới hạn
  },
];
```

---

## 📊 Mô Hình Dữ Liệu (Prisma)

### Plan
```prisma
id: String @id
tier: PlanTier @unique (FREE, AGENT_PRO, INVESTOR, ENTERPRISE)
name: String
priceMonthlyVND: BigInt
priceYearlyVND: BigInt
maxListings: Int?
maxSavedSearches: Int?
maxAnalyticsQueries: Int?
maxMediaUploads: Int?
features: Json           // { analytics: true, aiValuation: false, ... }
isActive: Boolean
```

### Subscription
```prisma
id: String @id
userId: String @unique
user: User
planId: String
plan: Plan
status: SubscriptionStatus (ACTIVE, PAST_DUE, CANCELLED, EXPIRED)
currentPeriodStart: DateTime
currentPeriodEnd: DateTime
cancelledAt: DateTime?
createdAt: DateTime
updatedAt: DateTime
```

### Payment
```prisma
id: String @id
userId: String
provider: PaymentProvider (VNPAY, MOMO, ZALOPAY, BANK_TRANSFER)
type: PaymentType (SUBSCRIPTION, LISTING_FEE, DEPOSIT, FEATURED_LISTING)
amountVND: BigInt
status: PaymentStatus (PENDING, PROCESSING, COMPLETED, FAILED, REFUNDED)
providerTxId: String?
callbackData: Json?
idempotencyKey: String?  ← Ngăn chặn thanh toán trùng lặp
createdAt: DateTime
updatedAt: DateTime
```

---

## 🔑 Chi Tiết Triển Khai Quan Trọng

### Luồng Tạo Thanh toán (Backend)
```
Người dùng nhấn "Thanh toán ngay"
  ↓
Frontend: POST /payments {
  provider: 'VNPAY',
  type: 'SUBSCRIPTION',
  amountVND: 499000,
  description: 'Agent Pro - Monthly',
  returnUrl: 'https://goodgo.vn/payment-return',
  idempotencyKey: UUID  ← Duy nhất cho mỗi lần thanh toán
}
  ↓
Backend CreatePaymentHandler:
  1. Kiểm tra idempotencyKey (ngăn trùng lặp)
  2. Xác thực số tiền (1 đến 100 tỷ VND)
  3. Lấy cổng thanh toán (VNPay/MoMo/ZaloPay)
  4. Gọi gateway.createPaymentUrl()
     - Trả về paymentUrl: "https://gateway.com/pay?params..."
     - Trả về providerTxId: "VNP-12345..."
  5. Đánh dấu thanh toán là PROCESSING trong DB
  6. Phát sự kiện PaymentCreatedEvent
  7. Trả về cho client: { paymentId, paymentUrl, providerTxId }
  ↓
Frontend:
  window.location = paymentUrl  ← Chuyển hướng đến cổng
  ↓
Người dùng hoàn tất thanh toán tại cổng
  ↓
Cổng chuyển hướng đến returnUrl với tham số callback
  ↓
Backend webhook: POST /payments/callback/vnpay?params...
  1. Xác minh chữ ký callback
  2. Kiểm tra trạng thái thanh toán
  3. Cập nhật trạng thái thanh toán trong DB
  4. Phát sự kiện PaymentCompletedEvent
  ↓
PaymentCompletedEvent kích hoạt:
  - Gửi thông báo qua email
  - Cập nhật liên kết gói của người dùng (cuối cùng)
  ↓
Trình xử lý callback frontend (nếu được triển khai):
  1. Lấy paymentId từ URL
  2. Poll GET /payments/{paymentId}
  3. Khi status = COMPLETED:
     - POST /subscriptions { planTier, billingCycle }
     - Hiển thị thông báo thành công
     - Chuyển hướng đến bảng điều khiển
```

### Triển Khai Cổng Thanh toán

#### VNPay
```typescript
// Chữ ký: HMAC SHA-512
// Yêu cầu qua: Tham số URL
// Mã phản hồi: vnp_ResponseCode = '00' nghĩa là thành công
// Mã giao dịch: vnp_TransactionNo
```

#### MoMo
```typescript
// Chữ ký: HMAC SHA-256
// Yêu cầu qua: Body JSON POST
// Mã phản hồi: resultCode = 0 nghĩa là thành công
// Mã giao dịch: transId
```

#### ZaloPay
```typescript
// Chữ ký: HMAC SHA-256 (tương tự MoMo)
// Yêu cầu qua: Body JSON POST
// Mã phản hồi: return_code = 1 nghĩa là thành công
// Mã giao dịch: zp_trans_id
```

---

## 🚨 Những Thiếu Sót Nghiêm Trọng (Những Gì Còn Thiếu)

### 1. Modal/Trang Thanh toán ❌
**Chức năng cần có:**
- Hiển thị chi tiết gói đã chọn
- Hiện giá theo tháng và theo năm
- Cho phép chọn phương thức thanh toán (VNPay, MoMo, ZaloPay)
- Hiển thị điều khoản và điều kiện
- Xử lý tạo thanh toán và chuyển hướng

**Hiện tại:** Nút CTA trên trang định giá trỏ đến `/register` thay vì bắt đầu thanh toán

### 2. Trình xử lý Trả về Thanh toán ❌
**Chức năng cần có:**
- Nhận chuyển hướng từ cổng thanh toán
- Trích xuất trạng thái thanh toán từ URL/callback
- Poll trạng thái thanh toán qua GET /payments/:id
- Tạo đăng ký khi thanh toán thành công
- Hiển thị giao diện thành công/lỗi

**Hiện tại:** Không có trang nào cho luồng này

### 3. Tự động Tạo Đăng ký ❌
**Chức năng cần có:**
- Sau khi thanh toán thành công, gọi POST /subscriptions
- Truyền planTier và billingCycle
- Cập nhật trạng thái đăng ký của người dùng
- Chuyển hướng đến bảng điều khiển

**Hiện tại:** Quy trình thủ công, không có giao diện

### 4. Giao diện Quản lý Đăng ký ⚠️ Một phần
**Những gì đã có:**
- Trang thanh toán hiển thị lịch sử giao dịch

**Những gì còn thiếu:**
- Trang trạng thái/chi tiết đăng ký
- Giao diện nâng cấp/hạ cấp gói
- Giao diện hủy đăng ký
- Hiển thị mức sử dụng/hạn mức

---

## 📋 Lộ Trình Triển Khai

### Giai đoạn 1: Thanh toán Cơ bản (1-2 ngày)
```
✅ Trang định giá đã tồn tại
❌ Thêm component CheckoutModal
❌ Thêm bộ chọn nhà cung cấp thanh toán
❌ Tạo trang /payment-return
❌ Triển khai poll thanh toán
❌ Kết nối tạo đăng ký
```

### Giai đoạn 2: Tích hợp Đầy đủ (1-2 ngày)
```
✅ Tất cả endpoint backend đã sẵn sàng
❌ Xử lý các trường hợp ngoại lệ (hết thời gian, người dùng đóng cửa sổ, v.v.)
❌ Thêm luồng phục hồi lỗi
❌ Thêm giao diện đang tải/thành công
❌ Kiểm tra với cả 3 nhà cung cấp thanh toán
```

### Giai đoạn 3: Quản lý Đăng ký (1-2 ngày)
```
✅ Endpoint API nâng cấp/hạ cấp đã tồn tại
✅ API hủy đăng ký đã tồn tại
❌ Xây dựng trang chi tiết đăng ký
❌ Thêm giao diện nâng cấp/hạ cấp
❌ Thêm giao diện hủy với xác nhận
❌ Thêm hiển thị hạn mức sử dụng
```

### Giai đoạn 4: Kiểm tra & Hoàn thiện (1-2 ngày)
```
❌ Kiểm tra E2E cho tất cả nhà cung cấp thanh toán
❌ Xử lý lỗi & các trường hợp ngoại lệ
❌ Tối ưu hóa hiệu suất
❌ Tích hợp phân tích/theo dõi
```

---

## 🎯 Các Bước Tiếp Theo

1. **Hiểu UX thanh toán mong muốn** - Thanh toán nên bắt đầu ở đâu/như thế nào?
   - Modal từ trang định giá?
   - Trang thanh toán riêng?
   - Trực tiếp trên trang định giá?

2. **Tạo component CheckoutModal** - Thiết kế phù hợp với trang định giá
   - Tóm tắt gói
   - Phân tích giá
   - Bộ chọn nhà cung cấp thanh toán
   - Nút "Tiến hành Thanh toán"

3. **Triển khai mutation tạo thanh toán** - Kết nối với React Query
   - Hook `useCreatePayment()`
   - Xử lý trạng thái đang tải/lỗi
   - Chuyển hướng đến paymentUrl

4. **Xây dựng trang /payment-return** - Xử lý chuyển hướng từ cổng
   - Phân tích tham số URL
   - Poll trạng thái thanh toán
   - Tạo đăng ký khi thành công

5. **Kiểm tra với cả 3 nhà cung cấp** - Đảm bảo tất cả tích hợp hoạt động
   - Sử dụng thông tin đăng nhập sandbox/kiểm tra
   - Xác minh callback

6. **Thêm giao diện quản lý đăng ký** - Cho phép người dùng quản lý gói
   - Xem đăng ký hiện tại
   - Nâng cấp/hạ cấp
   - Hủy với xác nhận

---

## 📚 Tài Liệu Tham Khảo

Tài liệu kiểm tra đầy đủ: `PRICING_CHECKOUT_AUDIT.md`

Các tệp cần xem xét:
- Frontend: `/apps/web/app/[locale]/(public)/pricing/page.tsx`
- Backend thanh toán: `/apps/api/src/modules/payments/`
- Backend đăng ký: `/apps/api/src/modules/subscriptions/`
- Prisma schema: `/prisma/schema.prisma` (dòng 451-514)

---

**Trạng thái:** Sẵn sàng triển khai thanh toán  
**Ước tính công sức:** 4-6 ngày  
**Độ phức tạp:** Trung bình (toàn bộ hạ tầng backend đã sẵn sàng)
