Fullstack Platform Nền Tảng Fullstack Graduation Project Đồ Án Tốt Nghiệp

NomNom Food Platform Nền Tảng Ẩm Thực NomNom

A comprehensive multi-role Food Ordering & Delivery platform with dedicated portals for Customers, Merchants, Drivers, and Administrators, featuring VNPay payment integration and real-time tracking. Nền tảng đặt và giao đồ ăn đa phân quyền quy mô lớn với các cổng giao diện riêng biệt cho Khách hàng, Cửa hàng, Tài xế và Quản trị viên, tích hợp thanh toán cổng VNPay và bản đồ định vị thời gian thực.

Role
Team Leader & System Architect Trưởng Nhóm & Kiến Trúc Sư Hệ Thống
Date
Tech Stack
React 19 Vite Tailwind CSS Node.js Express MySQL 8 VNPay Sandbox Cloudinary Leaflet Recharts
NomNom Multi-Role Food Platform Architecture

1. 🎯 The Engineering Problem & Leadership Context

Developing an end-to-end food delivery monorepo under strict capstone milestones presents significant architectural complexity:

  1. Multi-Role Concurrency & Workflow Isolation: Food delivery inherently involves four interdependent personas: Customers (ordering), Merchants (kitchen prep & stock), Drivers (order pickup & GPS routing), and Administrators (platform settlements & dispute moderation). Mixing these responsibilities creates severe security vulnerabilities and codebase chaos.
  2. Financial Consistency & Payment Verification: Handling online transactions via VNPay requires cryptographic checksum validation, secure Instant Payment Notification (IPN) handlers, and atomic database balance updates.
  3. Engineering Team Orchestration: Leading a 6-member engineering team across a short timeframe requires structured Git workflows, code reviews, API contracts, and quality gates.

NomNom was architected and delivered as the flagship graduation project at FPT Polytechnic (Specialization: Web Development). As Team Leader & System Architect, I led the team across 5 structured development waves.


2. 🏗️ System Architecture & 4-Role Workflow

flowchart TD
    subgraph FrontendSPA ["React 19 and Vite Multi-Role Portals"]
        Customer["Customer App (/app)\nBrowse menus, Cart, Orders, Reviews"]
        Merchant["Merchant Portal (/merchant)\nMenu management, Live order prep, Finance"]
        Driver["Driver App (/driver)\nDispatch, GPS routing, Proof of delivery"]
        Admin["Admin Dashboard (/admin)\nPlatform config, Payouts, Moderation"]
    end

    Customer --> API["Express.js API Gateway (/api/v1)"]
    Merchant --> API
    Driver --> API
    Admin --> API

    subgraph BackendServices ["Backend Core and Persistence Engine"]
        Auth["JWT Authentication and RBAC Guards"]
        DB[("MySQL 8 Database\n25+ Relational Tables")]
        VNPay["VNPay Payment Gateway\nHMAC-SHA512 IPN Handler"]
        Cloud["Cloudinary Media CDN and Nodemailer"]
    end

    API --> Auth
    API --> DB
    API --> VNPay
    API --> Cloud

3. ⚙️ Key Technical Decisions

  • Role-Based Access Control (RBAC) Middleware: API endpoints enforce multi-tier authentication guards that inspect decoded JWT claims, restricting routes strictly to authorized roles (customer, merchant, driver, admin).
  • Cryptographic VNPay IPN Verification: Implemented strict HMAC-SHA512 signature validation on upstream VNPay webhooks to guarantee financial reconciliation without double-credit vulnerabilities.
  • Relational Data Integrity: Architected a normalized MySQL schema with foreign key constraints, atomic transactions for multi-item orders, and automated voucher deductions.

4. 💻 Core Implementation Highlights

import crypto from 'crypto';

/**
 * Validates VNPay IPN Webhook Signature and verifies transaction status
 */
export function verifyVNPayIPN(vnp_Params, secretKey) {
  const secureHash = vnp_Params['vnp_SecureHash'];
  delete vnp_Params['vnp_SecureHash'];
  delete vnp_Params['vnp_SecureHashType'];

  // Sort parameter keys alphabetically according to VNPay specifications
  const sortedParams = Object.keys(vnp_Params)
    .sort()
    .reduce((result, key) => {
      if (vnp_Params[key] !== '' && vnp_Params[key] !== undefined) {
        result[key] = vnp_Params[key];
      }
      return result;
    }, {});

  const signData = new URLSearchParams(sortedParams).toString();
  const hmac = crypto.createHmac('sha512', secretKey);
  const signed = hmac.update(Buffer.from(signData, 'utf-8')).digest('hex');

  const isValidSignature = secureHash === signed;
  const isSuccessful = vnp_Params['vnp_ResponseCode'] === '00';

  return {
    isValid: isValidSignature,
    isSuccess: isValidSignature && isSuccessful,
    orderId: vnp_Params['vnp_TxnRef'],
    amount: Number(vnp_Params['vnp_Amount']) / 100
  };
}

5. 📊 Results & Graduation Achievement

  • Top Graduation Defense: Achieved outstanding evaluation from the academic defense jury.
  • Flawless Multi-Role Operation: 100% functional coverage across all 4 roles with zero security bypasses.
  • Production-Ready Codebase: Complete monorepo source code hosted at github.com/nguywnben/nomnom.

1. 🎯 Bối Cảnh & Thách Thức Kỹ Thuật

Phát triển một hệ thống đặt và giao đồ ăn toàn diện đòi hỏi giải quyết nhiều bài toán phức tạp về kiến trúc hệ thống và quản trị nhóm:

  1. Phân quyền đa vai trò & Quy trình nghiệp vụ độc lập: Mô hình giao đồ ăn thực tế bao gồm 4 đối tượng tương tác liên tục: Khách hàng (đặt món), Cửa hàng (chế biến & tồn kho), Tài xế (nhận cuốc & giao hàng) và Quản trị viên (đối soát tài chính & kiểm duyệt). Việc trộn lẫn mã nguồn sẽ tạo ra lỗ hổng bảo mật nghiêm trọng.
  2. Tính toàn vẹn tài chính & Thanh toán: Tích hợp cổng thanh toán VNPay yêu cầu xác thực chữ ký số HMAC-SHA512, xử lý webhook IPN an toàn và cập nhật số dư nguyên tử (atomic transaction) trong database.
  3. Quản trị đội ngũ kỹ thuật: Với vai trò Trưởng nhóm (Team Leader), nhiệm vụ là phân chia công việc cho 6 lập trình viên qua 5 sprint phát triển, đảm bảo tiến độ và chất lượng mã nguồn.

NomNom được thiết kế và hoàn thiện như đồ án tốt nghiệp xuất sắc tại FPT Polytechnic (Chuyên ngành Phát triển Web).


2. 🏗️ Kiến Trúc Hệ Thống & 4 Phân Quyền

flowchart TD
    subgraph FrontendSPA ["Giao Diện Đa Phân Quyền React 19 & Vite"]
        Customer["Khách Hàng (/app)\nXem thực đơn, Giỏ hàng, Đặt món, Đánh giá"]
        Merchant["Cửa Hàng (/merchant)\nQuản lý món, Nhận đơn trực tiếp, Doanh thu"]
        Driver["Tài Xế (/driver)\nNhận chuyến, Bản đồ định vị, Xác nhận giao"]
        Admin["Quản Trị Viên (/admin)\nCấu hình sàn, Đối soát thanh toán, Kiểm duyệt"]
    end

    Customer --> API["Cổng API Express.js (/api/v1)"]
    Merchant --> API
    Driver --> API
    Admin --> API

    subgraph BackendServices ["Dịch Vụ Backend & Cơ Sở Dữ Liệu"]
        Auth["Xác Thực JWT & Middleware Phân Quyền (RBAC)"]
        DB[("Cơ Sở Dữ Liệu MySQL 8\nHơn 25 bảng quan hệ chuẩn hóa")]
        VNPay["Cổng Thanh Toán VNPay\nHMAC-SHA512 IPN Webhook"]
        Cloud["Lưu Trữ Ảnh Cloudinary & Gửi Mail OTP"]
    end

    API --> Auth
    API --> DB
    API --> VNPay
    API --> Cloud

3. ⚙️ Các Quyết Định Kỹ Thuật Then Chốt

  • Middleware phân quyền RBAC đa lớp: Mọi endpoint API đều được kiểm soát bởi middleware xác thực token JWT, kiểm tra quyền hạn (customer, merchant, driver, admin) trước khi cho phép truy cập tài nguyên.
  • Xác thực chữ ký số VNPay IPN: Áp dụng thuật toán HMAC-SHA512 sắp xếp tham số chuẩn hóa để kiểm tra phản hồi từ VNPay, chống tấn công sửa đổi giá trị đơn hàng.
  • Toàn vẹn dữ liệu quan hệ: Thiết kế mô hình cơ sở dữ liệu MySQL chuẩn hóa với hơn 25 bảng, sử dụng transaction để đảm bảo việc trừ tồn kho món ăn và áp dụng voucher diễn ra an toàn 100%.

4. 💻 Đoạn Code Cốt Lõi Minh Họa

import crypto from 'crypto';

/**
 * Xác thực tính hợp lệ của chữ ký số Webhook VNPay IPN
 */
export function verifyVNPayIPN(vnp_Params, secretKey) {
  const secureHash = vnp_Params['vnp_SecureHash'];
  delete vnp_Params['vnp_SecureHash'];
  delete vnp_Params['vnp_SecureHashType'];

  // Sắp xếp các tham số theo bảng chữ cái theo quy chuẩn VNPay
  const sortedParams = Object.keys(vnp_Params)
    .sort()
    .reduce((result, key) => {
      if (vnp_Params[key] !== '' && vnp_Params[key] !== undefined) {
        result[key] = vnp_Params[key];
      }
      return result;
    }, {});

  const signData = new URLSearchParams(sortedParams).toString();
  const hmac = crypto.createHmac('sha512', secretKey);
  const signed = hmac.update(Buffer.from(signData, 'utf-8')).digest('hex');

  const isValidSignature = secureHash === signed;
  const isSuccessful = vnp_Params['vnp_ResponseCode'] === '00';

  return {
    isValid: isValidSignature,
    isSuccess: isValidSignature && isSuccessful,
    orderId: vnp_Params['vnp_TxnRef'],
    amount: Number(vnp_Params['vnp_Amount']) / 100
  };
}

5. 📊 Kết Quả Đạt Được & Dấu Ấn Lãnh Đạo

  • Đạt điểm xuất sắc trước hội đồng tốt nghiệp: Được hội đồng giảng viên đánh giá cao về quy mô và tính ứng dụng thực tế.
  • Vận hành trơn tru cả 4 phân quyền: Hệ thống hoạt động đồng bộ, thanh toán tự động và định vị bản đồ chính xác.
  • Mã nguồn hoàn thiện: Toàn bộ dự án được công khai trên GitHub tại github.com/nguywnben/nomnom.