Skip to content

Latest commit

 

History

History
1589 lines (1301 loc) · 43.2 KB

File metadata and controls

1589 lines (1301 loc) · 43.2 KB

Tài liệu API

Dự án này sử dụng một base path là /api cho tất cả các routes.

Base URL: http://localhost:8080/api


📋 Mục lục

  1. Authentication
  2. Products
  3. Authors
  4. Categories
  5. Reviews
  6. Cart
  7. Orders
  8. Payments
  9. Admin
  10. Authorization & Roles

1. Authentication (/api/auth)

POST /api/auth/register

Đăng ký tài khoản người dùng mới.

  • Tham số (Body):

    • name (String, Bắt buộc): Tên người dùng.
    • email (String, Tùy chọn): Email người dùng.
    • phone (String, Tùy chọn): Số điện thoại người dùng (định dạng +84...).
    • password (String, Bắt buộc): Mật khẩu (tối thiểu 8 ký tự).
    • passwordConfirm (String, Bắt buộc): Xác nhận mật khẩu.

    Lưu ý: Phải cung cấp email hoặc phone. User mới sẽ có role mặc định là "user".

  • Kết quả thành công (201):

    • Nếu đăng ký bằng email, trả về thông tin người dùng và token JWT.
    • Nếu đăng ký bằng SĐT, trả về thông báo yêu cầu xác thực OTP.
    {
        "status": "success",
        "token": "your_jwt_token",
        "data": {
            "user": {
                "_id": "userId",
                "name": "Test User",
                "email": "test@example.com",
                "phone": "+84123456789",
                "role": "user",
                "isPhoneVerified": false
            }
        }
    }

POST /api/auth/login

Đăng nhập vào hệ thống.

  • Tham số (Body):

    • identifier (String, Bắt buộc): Email hoặc số điện thoại của người dùng.
    • password (String, Bắt buộc): Mật khẩu.
  • Kết quả thành công (200):

    {
        "status": "success",
        "token": "your_jwt_token",
        "data": {
            "user": {
                "_id": "userId",
                "name": "Test User",
                "email": "test@example.com",
                "role": "user"
            }
        }
    }

POST /api/auth/verify-phone

Xác thực số điện thoại bằng mã OTP.

  • Tham số (Body):

    • phone (String, Bắt buộc): Số điện thoại đã đăng ký.
    • code (String, Bắt buộc): Mã OTP nhận được.
  • Kết quả thành công (200):

    • Trả về thông tin người dùng và token JWT sau khi xác thực thành công.

POST /api/auth/forgot-password

Yêu cầu reset mật khẩu qua email.

  • Tham số (Body):

    • email (String, Bắt buộc): Email đã đăng ký.
  • Kết quả thành công (200):

    {
        "status": "success",
        "message": "Token reset mật khẩu đã được gửi tới email!"
    }

PATCH /api/auth/reset-password/:token

Đặt lại mật khẩu mới bằng token đã nhận.

  • Tham số (URL):

    • token (String, Bắt buộc): Token reset nhận được từ email.
  • Tham số (Body):

    • password (String, Bắt buộc): Mật khẩu mới.
    • passwordConfirm (String, Bắt buộc): Xác nhận mật khẩu mới.
  • Kết quả thành công (200):

    • Trả về thông tin người dùng và token JWT mới.

2. Products (/api/product)

GET /api/product

Lấy danh sách sản phẩm với search, filter, sort và pagination.

  • Tham số (Query):

    • page (Number, Mặc định: 1): Số trang.
    • limit (Number, Mặc định: 10): Số lượng sản phẩm mỗi trang.
    • search (String): Tìm kiếm theo tên, mô tả, hoặc ISBN.
    • categoryId (ObjectId): Lọc theo danh mục.
    • authorId (ObjectId): Lọc theo tác giả.
    • minPrice (Number): Giá tối thiểu.
    • maxPrice (Number): Giá tối đa.
    • minRating (Number): Rating tối thiểu (1-5).
    • inStock (Boolean): true để chỉ hiển thị sản phẩm còn hàng.
    • sort (String): Sắp xếp theo:
      • price_asc: Giá tăng dần
      • price_desc: Giá giảm dần
      • rating: Rating cao nhất
      • bestseller: Bán chạy nhất
      • name: Tên A-Z
      • Mặc định: Mới nhất
  • Ví dụ:

    GET /api/product?search=harry&minPrice=50000&maxPrice=200000&sort=price_asc&page=1&limit=10&inStock=true
    
  • Kết quả thành công (200):

    {
        "status": "success",
        "results": 10,
        "data": {
            "products": [
                {
                    "_id": "productId",
                    "name": "Tên sản phẩm",
                    "slug": "ten-san-pham",
                    "price": 150000,
                    "discount": 10,
                    "description": "Mô tả sản phẩm",
                    "categoryId": {
                        "_id": "categoryId",
                        "name": "Tiểu thuyết",
                        "slug": "tieu-thuyet"
                    },
                    "authors": [
                        {
                            "_id": "authorId",
                            "name": "J.K. Rowling",
                            "slug": "jk-rowling"
                        }
                    ],
                    "publisher": "Bloomsbury",
                    "isbn": "978-0439708180",
                    "coverImageUrl": "https://example.com/image.jpg",
                    "rating": 4.5,
                    "inStock": 100,
                    "sold": 250,
                    "createdAt": "2025-12-01T00:00:00.000Z"
                }
            ],
            "pagination": {
                "page": 1,
                "limit": 10,
                "total": 45,
                "totalPages": 5
            }
        }
    }

GET /api/product/:id

Lấy thông tin chi tiết một sản phẩm.

  • Tham số (URL):

    • id (ObjectId, Bắt buộc): ID của sản phẩm.
  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "product": {
                "_id": "productId",
                "name": "Harry Potter và Hòn đá phù thủy",
                "slug": "harry-potter-va-hon-da-phu-thuy",
                "price": 150000,
                "discount": 10,
                "description": "Cuốn sách đầu tiên...",
                "categoryId": { ... },
                "authors": [ ... ],
                "publisher": "Bloomsbury",
                "publicationDate": "1997-06-26",
                "isbn": "978-0439708180",
                "coverImageUrl": "https://...",
                "gallery": ["url1", "url2"],
                "rating": 4.8,
                "inStock": 50,
                "sold": 1200
            }
        }
    }
  • Lỗi (404):

    {
        "status": "error",
        "message": "Sản phẩm không tồn tại"
    }

POST /api/product 🔐 Admin Only

Tạo một sản phẩm mới.

  • Headers:

    • Authorization: Bearer your_jwt_token (Admin role required)
  • Tham số (Body):

    • name (String, Bắt buộc): Tên sản phẩm.
    • price (Number, Bắt buộc): Giá sản phẩm.
    • discount (Number, 0-100): Phần trăm giảm giá.
    • description (String): Mô tả sản phẩm.
    • categoryId (ObjectId, Bắt buộc): ID danh mục.
    • authors (Array): Mảng object [{ name: "Tên tác giả" }]. Hệ thống sẽ tự tạo author mới nếu chưa tồn tại.
    • publisher (String): Nhà xuất bản.
    • publicationDate (Date): Ngày xuất bản.
    • isbn (String): Mã ISBN.
    • coverImageUrl (String): URL ảnh bìa.
    • gallery (Array of String): Mảng URL ảnh.
    • inStock (Number): Số lượng trong kho.
    • slug (String, Tùy chọn): Tự động tạo từ name nếu không cung cấp.
  • Kết quả thành công (201):

    {
        "status": "success",
        "data": {
            "product": { ... }
        }
    }

PUT /api/product/:id 🔐 Admin Only

Cập nhật thông tin sản phẩm.

  • Headers:

    • Authorization: Bearer your_jwt_token (Admin role required)
  • Tham số (URL):

    • id (ObjectId, Bắt buộc): ID của sản phẩm.
  • Tham số (Body):

    • Các trường cần cập nhật (giống POST).
  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "product": { ... }
        }
    }

DELETE /api/product/:id 🔐 Admin Only

Xóa một sản phẩm.

  • Headers:

    • Authorization: Bearer your_jwt_token (Admin role required)
  • Tham số (URL):

    • id (ObjectId, Bắt buộc): ID của sản phẩm.
  • Kết quả thành công (200):

    {
        "status": "success",
        "message": "Đã xóa sản phẩm thành công",
        "data": {
            "product": { ... }
        }
    }

3. Authors (/api/author)

GET /api/author

Lấy danh sách tác giả với pagination.

  • Tham số (Query):

    • page (Number, Mặc định: 1)
    • limit (Number, Mặc định: 10)
  • Kết quả thành công (200):

    {
        "status": "success",
        "results": 10,
        "data": {
            "authors": [
                {
                    "_id": "authorId",
                    "name": "J.K. Rowling",
                    "slug": "jk-rowling",
                    "biography": "Tiểu sử...",
                    "nationality": "British",
                    "dateOfBirth": "1965-07-31",
                    "totalBooks": 15,
                    "followers": 1000000
                }
            ],
            "pagination": {
                "page": 1,
                "limit": 10,
                "total": 50,
                "totalPages": 5
            }
        }
    }

GET /api/author/:id

Lấy chi tiết tác giả.

  • Kết quả thành công (200):
    {
        "status": "success",
        "data": {
            "author": {
                "_id": "authorId",
                "name": "J.K. Rowling",
                "slug": "jk-rowling",
                "biography": "...",
                "books": [
                    {
                        "_id": "productId",
                        "name": "Harry Potter",
                        "slug": "harry-potter",
                        "coverImageUrl": "..."
                    }
                ]
            }
        }
    }

POST /api/author 🔐 Admin Only

Tạo tác giả mới.

  • Headers: Authorization: Bearer your_jwt_token
  • Body: name (required), biography, nationality, dateOfBirth, avatar

PUT /api/author/:id 🔐 Admin Only

Cập nhật tác giả.

DELETE /api/author/:id 🔐 Admin Only

Xóa tác giả.


4. Categories (/api/category)

GET /api/category

Lấy danh sách danh mục.

  • Kết quả thành công (200):
    {
        "status": "success",
        "results": 15,
        "data": {
            "categories": [
                {
                    "_id": "categoryId",
                    "name": "Tiểu thuyết",
                    "slug": "tieu-thuyet",
                    "description": "...",
                    "parentCategory": null,
                    "imageUrl": "..."
                }
            ]
        }
    }

GET /api/category/:id

Lấy chi tiết danh mục.

POST /api/category 🔐 Admin Only

Tạo danh mục mới.

  • Headers: Authorization: Bearer your_jwt_token
  • Body: name (required), description, parentCategory, imageUrl

PUT /api/category/:id 🔐 Admin Only

Cập nhật danh mục.

DELETE /api/category/:id 🔐 Admin Only

Xóa danh mục.


5. Reviews (/api/reviews)

GET /api/reviews/product/:productId

Lấy tất cả đánh giá của một sản phẩm.

  • Tham số (URL):

    • productId (ObjectId, Bắt buộc)
  • Tham số (Query):

    • page (Number, Mặc định: 1)
    • limit (Number, Mặc định: 10)
  • Kết quả thành công (200):

    {
        "status": "success",
        "results": 10,
        "data": {
            "reviews": [
                {
                    "_id": "reviewId",
                    "rating": 5,
                    "comment": "Sản phẩm rất tốt!",
                    "userId": {
                        "_id": "userId",
                        "name": "Nguyen Van A"
                    },
                    "productId": "productId",
                    "createdAt": "2025-12-01T00:00:00.000Z"
                }
            ],
            "pagination": {
                "page": 1,
                "limit": 10,
                "total": 45,
                "totalPages": 5
            }
        }
    }

POST /api/reviews 🔐 Authenticated

Tạo đánh giá mới cho sản phẩm.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Tham số (Body):

    • productId (ObjectId, Bắt buộc): ID sản phẩm.
    • rating (Number, Bắt buộc): Điểm đánh giá (1-5).
    • comment (String): Bình luận.
  • Kết quả thành công (201):

    {
        "status": "success",
        "data": {
            "review": {
                "_id": "reviewId",
                "rating": 5,
                "comment": "Rất hay!",
                "userId": "userId",
                "productId": "productId"
            }
        }
    }

DELETE /api/reviews/:id 🔐 Authenticated

Xóa một đánh giá (phải là chủ sở hữu hoặc admin).

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Kết quả thành công (200):

    {
        "status": "success",
        "message": "Đã xóa review thành công",
        "data": {
            "review": { ... }
        }
    }

6. Cart (/api/cart)

Tất cả các API trong mục này yêu cầu đăng nhập.

GET /api/cart 🔐

Lấy giỏ hàng của người dùng hiện tại.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "cart": [
                {
                    "product": {
                        "_id": "productId",
                        "name": "Harry Potter",
                        "price": 150000,
                        "coverImageUrl": "...",
                        "inStock": 50
                    },
                    "quantity": 2,
                    "_id": "cartItemId"
                }
            ]
        }
    }

POST /api/cart 🔐

Thêm sản phẩm vào giỏ hàng.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Tham số (Body):

    • productId (ObjectId, Bắt buộc): ID sản phẩm.
    • quantity (Number, Mặc định: 1): Số lượng.
  • Kết quả thành công (200):

    {
        "status": "success",
        "message": "Sản phẩm đã được thêm vào giỏ hàng.",
        "data": {
            "cart": [ ... ]
        }
    }
  • Lỗi (400):

    {
        "status": "error",
        "message": "Sản phẩm không đủ số lượng trong kho."
    }

PATCH /api/cart/:productId 🔐

Cập nhật số lượng sản phẩm trong giỏ hàng.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Tham số (URL):

    • productId (ObjectId, Bắt buộc)
  • Tham số (Body):

    • quantity (Number, Bắt buộc): Số lượng mới (>= 1).
  • Kết quả thành công (200):

    {
        "status": "success",
        "message": "Giỏ hàng đã được cập nhật.",
        "data": {
            "cart": [ ... ]
        }
    }

DELETE /api/cart/:productId 🔐

Xóa sản phẩm khỏi giỏ hàng.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Kết quả thành công (200):

    {
        "status": "success",
        "message": "Sản phẩm đã được xóa khỏi giỏ hàng.",
        "data": {
            "cart": [ ... ]
        }
    }

7. Orders (/api/orders)

Tất cả các API trong mục này yêu cầu đăng nhập.

POST /api/orders 🔐

Tạo đơn hàng từ giỏ hàng hiện tại.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Tham số (Body):

    • shippingAddress (Object, Bắt buộc):
      • fullName (String, Bắt buộc)
      • address (String, Bắt buộc)
      • city (String, Bắt buộc)
      • postalCode (String, Bắt buộc)
      • country (String, Bắt buộc)
      • phone (String, Bắt buộc)
    • paymentMethod (String, Bắt buộc): "COD" hoặc "Card"
  • Kết quả thành công (201):

    {
        "status": "success",
        "data": {
            "order": {
                "_id": "orderId",
                "user": "userId",
                "items": [
                    {
                        "product": "productId",
                        "name": "Harry Potter",
                        "quantity": 2,
                        "price": 150000
                    }
                ],
                "totalAmount": 300000,
                "shippingAddress": { ... },
                "paymentMethod": "COD",
                "paymentStatus": "pending",
                "status": "pending",
                "createdAt": "2025-12-07T00:00:00.000Z"
            }
        }
    }
  • Lỗi (400):

    {
        "status": "error",
        "message": "Giỏ hàng của bạn đang trống."
    }

    hoặc

    {
        "status": "error",
        "message": "Sản phẩm \"Harry Potter\" không đủ hàng."
    }

POST /api/oders Tính năng "Mua ngay"

-   **Headers:**
    -   `Authorization`: `Bearer your_jwt_token`

-   **Tham số (Body):**
    -   `shippingAddress` (Object, Bắt buộc):
    -   `paymentMethod` (String, Bắt buộc): `"COD"` hoặc `"Card"`
    -   `item` (Object, bắt buộc):
        VD: {
        "shippingAddress": "Số 1 Đại Cồ Việt, Hà Nội",
        "paymentMethod": "COD",
        "items": [
            { "product": "69394302990b2958fe87145a", "quantity": 4 }
            ]
        }
- **Kết Quả:**
```json
{
"status": "success",
"data": {
    "order": {
        "user": "692c552f5946a5d346011abe",
        "items": [
            {
                "product": "69394302990b2958fe87145a",
                "name": "Cà Phê Cùng Tony",
                "quantity": 4,
                "price": 89000,
                "_id": "69442faef69e6c554fcdca33"
            }
        ],
        "totalAmount": 356000,
        "shippingAddress": "Số 1 Đại Cồ Việt, Hà Nội",
        "paymentMethod": "COD",
        "paymentStatus": "pending",
        "transactionCode": null,
        "status": "pending",
        "_id": "69442faef69e6c554fcdca32",
        "createdAt": "2025-12-18T16:45:34.542Z",
        "updatedAt": "2025-12-18T16:45:34.542Z",
        "__v": 0
        }
    }
}

GET /api/orders/my-orders 🔐

Lấy danh sách đơn hàng của người dùng hiện tại.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Kết quả thành công (200):

    {
        "status": "success",
        "results": 5,
        "data": {
            "orders": [
                {
                    "_id": "orderId",
                    "items": [ ... ],
                    "totalAmount": 300000,
                    "status": "delivered",
                    "paymentStatus": "paid",
                    "createdAt": "2025-12-01T00:00:00.000Z"
                }
            ]
        }
    }

GET /api/orders/:id 🔐

Lấy chi tiết một đơn hàng (phải là chủ đơn hàng hoặc admin).

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "order": {
                "_id": "orderId",
                "user": {
                    "_id": "userId",
                    "name": "Nguyen Van A",
                    "email": "user@example.com"
                },
                "items": [ ... ],
                "totalAmount": 300000,
                "shippingAddress": { ... },
                "paymentMethod": "COD",
                "paymentStatus": "pending",
                "status": "processing",
                "createdAt": "2025-12-07T00:00:00.000Z",
                "updatedAt": "2025-12-07T01:00:00.000Z"
            }
        }
    }

GET /api/orders/admin/ 🔐 Admin Only

Lấy tất cả đơn hàng (admin only).

  • Headers:

    • Authorization: Bearer your_admin_jwt_token
  • Kết quả thành công (200):

    {
        "status": "success",
        "results": 100,
        "data": {
            "orders": [ ... ]
        }
    }

PATCH /api/orders/admin/:id 🔐 Admin Only

Cập nhật trạng thái đơn hàng (admin only).

  • Headers:

    • Authorization: Bearer your_admin_jwt_token
  • Tham số (Body):

    • status (String, Bắt buộc): "pending", "processing", "shipped", "delivered", hoặc "cancelled"
  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "order": { ... }
        }
    }

8. Payments (/api/payment)

GET /api/product

Lấy danh sách sản phẩm.

  • Tham số (Query):

    • page (Number, Tùy chọn, Mặc định: 1): Số trang.
    • limit (Number, Tùy chọn, Mặc định: 10): Số lượng sản phẩm mỗi trang.
  • Kết quả thành công (200):

    • Trả về một mảng các sản phẩm.
    [
        {
            "_id": "productId",
            "name": "Tên sản phẩm",
            "price": 100000,
            "discount": 10,
            "description": "Mô tả sản phẩm",
            "categoryId": "categoryId",
            "authors": ["authorId1", "authorId2"],
            "rating": 4.5,
            "inStock": 100
        }
    ]

POST /api/product

Tạo một sản phẩm mới (Yêu cầu quyền admin).

  • Tham số (Body):

    • name (String, Bắt buộc)
    • price (Number, Bắt buộc)
    • description (String)
    • categoryId (ObjectId, Bắt buộc)
    • authors (Array of ObjectId)
    • inStock (Number)
    • ... (và các trường khác trong product.model.js)
  • Kết quả thành công (201):

    • Trả về đối tượng sản phẩm vừa tạo.

GET /api/product/:id

Lấy thông tin chi tiết một sản phẩm.

  • Tham số (URL):

    • id (ObjectId, Bắt buộc): ID của sản phẩm.
  • Kết quả thành công (200):

    • Trả về đối tượng sản phẩm.

PUT /api/product/:id

Cập nhật thông tin sản phẩm (Yêu cầu quyền admin).

  • Tham số (URL):

    • id (ObjectId, Bắt buộc): ID của sản phẩm.
  • Tham số (Body):

    • Các trường thông tin sản phẩm cần cập nhật.
  • Kết quả thành công (200):

    • Trả về đối tượng sản phẩm đã được cập nhật.

DELETE /api/product/:id

Xóa một sản phẩm (Yêu cầu quyền admin).

  • Tham số (URL):

    • id (ObjectId, Bắt buộc): ID của sản phẩm.
  • Kết quả thành công (200):

    • Trả về đối tượng sản phẩm đã bị xóa.

9. Admin (/api/admin) 🔐👑

Lưu ý: Tất cả các routes admin yêu cầu đăng nhập và có role admin.

  • GET /api/author: Lấy danh sách tác giả.

  • POST /api/author: Tạo tác giả mới.

  • GET /api/author/:id: Lấy chi tiết tác giả.

  • PUT /api/author/:id: Cập nhật tác giả.

  • DELETE /api/author/:id: Xóa tác giả.

  • Đối tượng Author:

    {
        "_id": "authorId",
        "name": "Tên tác giả",
        "biography": "Tiểu sử",
        "nationality": "Quốc tịch",
        "books": ["productId1", "productId2"]
    }

4. Categories (/api/category)

Tương tự như Products, bao gồm các API:

  • GET /api/category: Lấy danh sách danh mục.

  • POST /api/category: Tạo danh mục mới.

  • GET /api/category/:id: Lấy chi tiết danh mục.

  • PUT /api/category/:id: Cập nhật danh mục.

  • DELETE /api/category/:id: Xóa danh mục.

  • Đối tượng Category:

    {
        "_id": "categoryId",
        "name": "Tên danh mục",
        "slug": "ten-danh-muc",
        "description": "Mô tả danh mục",
        "parentCategory": "parentCategoryId"
    }

5. Reviews (/api/reviews)

POST /api/reviews

Tạo một đánh giá mới cho sản phẩm (Yêu cầu đăng nhập).

  • Header:

    • Authorization: Bearer your_jwt_token
  • Tham số (Body):

    • productId (ObjectId, Bắt buộc): ID sản phẩm được đánh giá.
    • rating (Number, Bắt buộc): Điểm đánh giá (1-5).
    • comment (String): Bình luận.
  • Kết quả thành công (201):

    • Trả về đối tượng review vừa tạo.
    {
        "_id": "reviewId",
        "rating": 5,
        "comment": "Sản phẩm rất tốt!",
        "userId": "userId",
        "productId": "productId"
    }

GET /api/reviews/product/:productId

Lấy tất cả đánh giá của một sản phẩm.

  • Tham số (URL):

    • productId (ObjectId, Bắt buộc): ID của sản phẩm.
  • Tham số (Query):

    • page, limit
  • Kết quả thành công (200):

    • Trả về một mảng các đánh giá.

DELETE /api/reviews/:id

Xóa một đánh giá (Yêu cầu đăng nhập và là chủ sở hữu review hoặc admin).

  • Header:

    • Authorization: Bearer your_jwt_token
  • Tham số (URL):

    • id (ObjectId, Bắt buộc): ID của review.
  • Kết quả thành công (200):

    • Trả về đối tượng review đã bị xóa.

6. Cart (/api/cart)

Tất cả các API trong mục này đều yêu cầu đăng nhập (Authorization: Bearer your_jwt_token).

GET /api/cart

Lấy thông tin giỏ hàng của người dùng hiện tại.

  • Kết quả thành công (200):
    {
        "status": "success",
        "data": {
            "cart": [
                {
                    "product": {
                        "_id": "productId",
                        "name": "Tên sản phẩm",
                        "price": 100000,
                        "images": ["url1", "url2"],
                        "stock": 50
                    },
                    "quantity": 2,
                    "_id": "cartItemId"
                }
            ]
        }
    }

POST /api/cart

Thêm sản phẩm vào giỏ hàng.

  • Tham số (Body):

    • productId (ObjectId, Bắt buộc): ID sản phẩm.
    • quantity (Number, Tùy chọn, Mặc định: 1): Số lượng.
  • Kết quả thành công (200):

    • Trả về giỏ hàng đã được cập nhật.

PATCH /api/cart/:productId

Cập nhật số lượng của một sản phẩm trong giỏ hàng.

  • Tham số (URL):

    • productId (ObjectId, Bắt buộc): ID sản phẩm trong giỏ hàng.
  • Tham số (Body):

    • quantity (Number, Bắt buộc): Số lượng mới (phải >= 1).
  • Kết quả thành công (200):

    • Trả về giỏ hàng đã được cập nhật.

DELETE /api/cart/:productId

Xóa một sản phẩm khỏi giỏ hàng.

  • Tham số (URL):

    • productId (ObjectId, Bắt buộc): ID sản phẩm cần xóa.
  • Kết quả thành công (200):

    • Trả về giỏ hàng đã được cập nhật.

DELETE /api/cart 🔐

Xóa toàn bộ giỏ hàng.

  • Yêu cầu: Đăng nhập (protect middleware)

  • Kết quả thành công (200):

    {
        "status": "success",
        "message": "Giỏ hàng đã được xóa.",
        "data": {
            "cart": {
                "_id": "cartId",
                "user": "userId",
                "items": [],
                "totalItems": 0,
                "totalPrice": 0
            }
        }
    }

8. Payments (/api/payment)

Tất cả các API trong mục này yêu cầu đăng nhập.

Tính năng thanh toán hỗ trợ ba phương thức:

  • COD (Cash on Delivery - Thanh toán khi nhận hàng)
  • VietQR (Chuyển khoản ngân hàng qua mã QR)
  • ETH (Thanh toán bằng Ethereum blockchain)

Luồng thanh toán chung

  1. Khách hàng tạo đơn hàng (POST /api/orders) với một trong ba phương thức thanh toán
  2. Hệ thống tự động khởi tạo bản ghi thanh toán với trạng thái Pending
  3. Tuỳ theo phương thức thanh toán:
    • COD: Khách hàng xác nhận đã sẵn sàng khi nhận hàng
    • VietQR: Khách hàng quét mã QR và chuyển khoản, gửi mã giao dịch
    • ETH: Khách hàng kết nối ví crypto và gửi transaction hash
  4. Khách hàng gọi API POST /api/payment/confirm để xác nhận thanh toán
  5. Hệ thống cập nhật trạng thái thanh toán thành Completed và đơn hàng thành Processing

POST /api/payment/confirm 🔐

Xác nhận thanh toán cho đơn hàng.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Tham số (Body):

    • orderId (String, Bắt buộc): ID của đơn hàng cần thanh toán
    • transactionCode (String, Bắt buộc): Mã xác nhận thanh toán tùy theo phương thức:
      • COD: Mã xác nhận hoặc để trống (VD: "COD_001" hoặc "confirmed")
      • VietQR: Mã giao dịch ngân hàng (VD: "123456789ABC")
      • ETH: Transaction hash từ blockchain (VD: "0x1234567890abcdef...")
  • Ví dụ request:

    COD:

    {
        "orderId": "69442faef69e6c554fcdca32",
        "transactionCode": "confirmed"
    }

    VietQR:

    {
        "orderId": "69442faef69e6c554fcdca32",
        "transactionCode": "VIET_QR_20251219_12345"
    }

    ETH:

    {
        "orderId": "69442faef69e6c554fcdca32",
        "transactionCode": "0x1f3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
    }
  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "payment": {
                "_id": "paymentId",
                "order": "69442faef69e6c554fcdca32",
                "user": "692c552f5946a5d346011abe",
                "amount": 356000,
                "method": "COD",
                "status": "Completed",
                "transactionCode": "confirmed",
                "paymentDate": "2025-12-19T10:30:45.000Z",
                "createdAt": "2025-12-18T16:45:34.542Z",
                "updatedAt": "2025-12-19T10:30:45.123Z"
            }
        }
    }

    Sau khi xác nhận thanh toán:

    • Trạng thái thanh toán: Completed
    • Trạng thái đơn hàng: Processing (Đang xử lý)
    • paymentDate được cập nhật thời gian xác nhận
  • Lỗi (404):

    {
        "status": "error",
        "message": "Không tìm thấy thông tin thanh toán cho đơn hàng này."
    }

GET /api/payment/:orderId 🔐

Lấy thông tin chi tiết thanh toán của một đơn hàng.

  • Headers:

    • Authorization: Bearer your_jwt_token
  • Tham số (URL):

    • orderId (String, Bắt buộc): ID của đơn hàng
  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "payment": {
                "_id": "paymentId",
                "order": "69442faef69e6c554fcdca32",
                "user": "692c552f5946a5d346011abe",
                "amount": 356000,
                "method": "COD",
                "status": "Pending",
                "transactionCode": null,
                "paymentDate": "2025-12-18T16:45:34.542Z",
                "createdAt": "2025-12-18T16:45:34.542Z",
                "updatedAt": "2025-12-18T16:45:34.542Z"
            }
        }
    }
  • Lỗi (404):

    {
        "status": "error",
        "message": "Không tìm thấy thông tin thanh toán cho đơn hàng này."
    }

Trạng thái thanh toán

Trạng thái Mô tả
Pending Đơn hàng vừa được tạo, chờ khách hàng thanh toán
Completed Thanh toán đã hoàn tất thành công
Failed Thanh toán thất bại
Refunded Đã hoàn tiền cho khách hàng

Hướng dẫn chi tiết theo phương thức thanh toán

1. Thanh toán COD (Cash on Delivery)

Quy trình:

  1. Khách hàng chọn phương thức thanh toán là "COD" khi tạo đơn hàng
  2. Đơn hàng được tạo với trạng thái paymentStatus: 'pending'
  3. Khách hàng gọi API POST /api/payment/confirm với transactionCode bất kỳ (VD: "confirmed")
  4. Thanh toán được đánh dấu là Completed
  5. Nhân viên giao hàng sẽ thu tiền trực tiếp từ khách hàng

Ví dụ:

# Tạo đơn hàng với COD
POST /api/orders
{
    "shippingAddress": "Số 1 Đại Cồ Việt, Hà Nội",
    "paymentMethod": "COD",
    "items": [
        { "product": "productId", "quantity": 2 }
    ]
}

# Xác nhận thanh toán COD
POST /api/payment/confirm
{
    "orderId": "orderId_từ_bước_trên",
    "transactionCode": "confirmed"
}

2. Thanh toán VietQR (Chuyển khoản ngân hàng)

3. Thanh toán ETH (Ethereum)

Quy trình:

  1. Khách hàng chọn phương thức thanh toán là "ETH" khi tạo đơn hàng
  2. Frontend kết nối với ví Ethereum của khách hàng (MetaMask, v.v.)
  3. Smart contract thanh toán được gọi để thực hiện giao dịch
  4. Khách hàng ký xác nhận giao dịch trong ví
  5. Sau khi giao dịch được đưa lên blockchain, nhận được transaction hash
  6. Khách hàng gọi API POST /api/payment/confirm và gửi transaction hash
  7. Hệ thống cập nhật trạng thái thanh toán thành Completed

Ví dụ:

# Tạo đơn hàng với ETH
POST /api/orders
{
    "shippingAddress": "Số 1 Đại Cồ Việt, Hà Nội",
    "paymentMethod": "ETH",
    "items": [
        { "product": "productId", "quantity": 3 }
    ]
}

# Xác nhận thanh toán ETH (sau khi giao dịch thành công trên blockchain)
POST /api/payment/confirm
{
    "orderId": "orderId_từ_bước_trên",
    "transactionCode": "0x1f3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}

Lưu ý:

  • Transaction hash bắt đầu với 0x và có độ dài 66 ký tự (66 = 2 + 64)
  • Khách hàng có thể kiểm tra giao dịch tại: https://etherscan.io/tx/[transaction_hash] (cho Mainnet) hoặc explorer blockchain tương ứng
  • Smart contract được triển khai tại địa chỉ blockchain được cấu hình trong hệ thống
  • Phí gas sẽ được trừ từ ví của khách hàng

Kiểm tra trạng thái giao dịch:

  • Truy cập vào blockchain explorer
  • Tìm kiếm transaction hash
  • Xem trạng thái: Pending, Success, hoặc Failed

9. Admin (/api/admin) 🔐👑

Lưu ý: Tất cả các routes admin yêu cầu đăng nhập và có role admin.

GET /api/admin/dashboard 🔐👑

Lấy thống kê tổng quan cho dashboard admin.

  • Yêu cầu: Admin role

  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "stats": {
                "revenue": {
                    "total": 50000000,
                    "today": 2500000,
                    "thisMonth": 15000000,
                    "thisYear": 45000000
                },
                "orders": {
                    "total": 150,
                    "today": 5,
                    "thisMonth": 45,
                    "byStatus": {
                        "pending": 10,
                        "processing": 15,
                        "shipped": 20,
                        "delivered": 100,
                        "cancelled": 5
                    }
                },
                "customers": {
                    "total": 250,
                    "newToday": 3,
                    "newThisMonth": 25
                },
                "products": {
                    "total": 100,
                    "lowStock": 8,
                    "outOfStock": 2
                }
            }
        }
    }

GET /api/admin/revenue 🔐👑

Lấy thống kê doanh thu theo khoảng thời gian.

  • Yêu cầu: Admin role

  • Query Parameters:

    • period (String, Mặc định: 'month'): Khoảng thời gian - 'week', 'month', 'year'
    • year (Number, Tùy chọn): Năm cụ thể (mặc định: năm hiện tại)
    • month (Number, Tùy chọn): Tháng cụ thể (1-12, chỉ dùng khi period='month')
  • Ví dụ:

    • GET /api/admin/revenue?period=month&year=2024&month=12
    • GET /api/admin/revenue?period=year&year=2024
    • GET /api/admin/revenue?period=week
  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "stats": {
                "period": "month",
                "year": 2024,
                "month": 12,
                "data": [
                    {
                        "period": 1,
                        "revenue": 1200000,
                        "orders": 5
                    },
                    {
                        "period": 2,
                        "revenue": 1500000,
                        "orders": 7
                    }
                ]
            }
        }
    }

GET /api/admin/inventory 🔐👑

Lấy báo cáo tồn kho chi tiết.

  • Yêu cầu: Admin role

  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "report": {
                "totalInventoryValue": 125000000,
                "stockLevels": [
                    {
                        "_id": 0,
                        "count": 2,
                        "products": []
                    },
                    {
                        "_id": 1,
                        "count": 5,
                        "products": []
                    }
                ],
                "lowStockProducts": [
                    {
                        "_id": "productId",
                        "name": "Sản phẩm A",
                        "inStock": 5,
                        "price": 100000,
                        "categoryId": {
                            "_id": "categoryId",
                            "name": "Category Name"
                        }
                    }
                ],
                "outOfStockProducts": [
                    {
                        "_id": "productId",
                        "name": "Sản phẩm B",
                        "sold": 150,
                        "price": 200000,
                        "categoryId": {
                            "_id": "categoryId",
                            "name": "Category Name"
                        }
                    }
                ],
                "productsByCategory": [
                    {
                        "_id": "categoryId",
                        "categoryName": "Tiểu thuyết",
                        "count": 25,
                        "totalStock": 500
                    }
                ]
            }
        }
    }

GET /api/admin/best-selling 🔐👑

Lấy danh sách sản phẩm bán chạy nhất.

  • Yêu cầu: Admin role

  • Query Parameters:

    • limit (Number, Mặc định: 10): Số lượng sản phẩm trả về
    • period (String, Mặc định: 'all'): Khoảng thời gian - 'all', 'month', 'year'
  • Ví dụ:

    • GET /api/admin/best-selling?limit=20&period=month
    • GET /api/admin/best-selling?period=year
  • Kết quả thành công (200):

    {
        "status": "success",
        "results": 10,
        "data": {
            "products": [
                {
                    "_id": "productId",
                    "productId": "productId",
                    "name": "Đắc Nhân Tâm",
                    "coverImageUrl": "url",
                    "price": 120000,
                    "inStock": 300,
                    "totalSold": 8900,
                    "totalRevenue": 1068000000,
                    "orderCount": 3500
                }
            ]
        }
    }

GET /api/admin/sales-by-category 🔐👑

Lấy thống kê doanh thu theo danh mục sản phẩm.

  • Yêu cầu: Admin role

  • Query Parameters:

    • period (String, Mặc định: 'all'): Khoảng thời gian - 'all', 'month', 'year'
  • Ví dụ:

    • GET /api/admin/sales-by-category?period=month
  • Kết quả thành công (200):

    {
        "status": "success",
        "results": 5,
        "data": {
            "sales": [
                {
                    "_id": "categoryId",
                    "categoryId": "categoryId",
                    "categoryName": "Kỹ năng sống",
                    "totalRevenue": 25000000,
                    "totalSold": 350,
                    "orderCount": 180
                }
            ]
        }
    }

GET /api/admin/customers 🔐👑

Lấy thống kê khách hàng.

  • Yêu cầu: Admin role

  • Kết quả thành công (200):

    {
        "status": "success",
        "data": {
            "stats": {
                "topCustomers": [
                    {
                        "_id": "userId",
                        "userId": "userId",
                        "name": "Nguyễn Văn A",
                        "email": "user@example.com",
                        "totalSpent": 5000000,
                        "orderCount": 15
                    }
                ],
                "customerGrowth": [
                    {
                        "_id": 1,
                        "count": 25
                    },
                    {
                        "_id": 2,
                        "count": 30
                    }
                ]
            }
        }
    }

10. Authorization & Roles