A
Đăng nhập

Nội dung này đã khóa

Vui lòng đăng nhập hoặc đăng ký mua sách để đọc tiếp những kiến thức chuyên sâu này.

Mua bản đầy đủ

Chương 8: Backend & API - Bộ não của hệ thống

Chapter 8 Backend

"Backend không chỉ là nơi lưu trữ dữ liệu. Nó là nơi ra quyết định, thực thi lụật chơi và kết nối thế giới."

Trong chương trước, ta đã xây xong "Bộ xương" (Database). Chương này, ta sẽ xây dựng "Hệ thần kinh" (API) để điều khiển cơ thể vận động. Chúng ta sẽ giải quyết bài toán: Làm sao để khách bấm nút "Mua hàng", hệ thống tự động trừ kho, ghi đơn và báo tin nhắn về điện thoại cho Sếp?

8.1 Kiến trúc Backend cho VibeMaterial (Next.js App Router)

Chúng ta sử dụng Next.js Server Actions - công nghệ mới nhất giúp viết Backend ngay trong Frontend mà không cần dựng Server riêng.

8.1.1 Phân cấp API (Security First)

  • Public API (Cho khách hàng):
    • GET /products: Xem danh sách (Chỉ lấy tên, giá. Ẩn giá vốn).
    • POST /checkout: Gửi đơn hàng (Chỉ được tạo, không được sửa đơn cũ).
  • Private API (Cho Admin):
    • POST /admin/products: Nhập hàng.
    • PATCH /admin/orders: Duyệt đơn.
    • Yêu cầu: Phải check quyền role = 'admin' cực gắt.

8.2 Prompt Mẫu: Thiết kế API (Tránh lộ nhạy cảm)

Đừng để AI tự bịa API. Nó hay trả về thừa thãi. Hãy dùng Prompt:

Prompt: You are a backend engineer. Design REST API endpoints for client-side e-commerce features:

  • Get product list
  • Get product detail
  • Create order Constraints:
  • Read-only for products
  • Payload must be minimal (Save user's 4G)
  • NO sensitive fields exposed (cost_price, supplier_info) Output: endpoint list + sample JSON response.

8.3 Bài toán kinh điển: "Transaction" (Giao dịch)

Đây là thứ phân biệt giữa một Coder nghiệp dư và Chuyên nghiệp.

8.3.1 Vấn đề:

Khi khách mua 1 đơn gồm 2 món (Xi măng, Gạch). Hệ thống phải làm 3 việc:

  1. Tạo dòng trong bảng orders (Phiếu thu).
  2. Tạo 2 dòng trong bảng order_items (Chi tiết).
  3. Trừ kho trong bảng products.

Rủi ro: Nếu bước 1 thành công (tạo đơn), nhưng bước 2 lỗi (mạng lag, hết hàng) -> Dữ liệu bị rác. Đơn hàng tồn tại nhưng không có sản phẩm nào. Kho không bị trừ. Tiền vẫn thu. -> Thảm họa.

8.3.2 Giải pháp: Database Transaction (Tất cả hoặc Không gì cả)

Chúng ta phải ép Database: "Làm hết cả 3 việc này cùng lúc. Nếu 1 cái lỗi, hủy bỏ tất cả (Rollback)."

Trong Supabase/Next.js, ta Prompt AI như sau:

Role: Backend Developer. Task: Write a Server Action submitOrder(cartData) to handle checkout. Logic:

  1. Start a Transaction (or use rpc function in Supabase).
  2. Insert into orders -> Get order_id.
  3. Loop cartData -> Insert into order_items using that order_id.
  4. If any error happens, Rollback everything. Output: Postgre Function SQL code (Best for transaction integrity).

Code minh họa (SQL Procedure):

create or replace function create_order(
  user_id uuid, 
  items jsonb, -- Mảng giỏ hàng gửi lên
  total int
) returns bigint language plpgsql as $$
declare
  new_order_id bigint;
  item jsonb;
begin
  -- 1. Tạo đơn hàng
  insert into orders (user_id, total_amount) values (user_id, total) 
  returning id into new_order_id;

  -- 2. Duyệt qua từng món để lưu chi tiết
  for item in select * from jsonb_array_elements(items)
  loop
    insert into order_items (order_id, product_id, quantity, price_at_purchase)
    values (new_order_id, (item->>'id')::bigint, (item->>'qty')::int, (item->>'price')::int);
    
    -- 3. Trừ kho (Tùy chọn, có thể làm bằng Trigger riêng)
    -- update products set stock = stock - ...
  end loop;

  return new_order_id;
exception when others then
  raise exception 'Lỗi tạo đơn: %', sqlerrm; -- Rollback tự động
end; $$;

Bạn thấy đó, thay vì viết JS phức tạp, ta đẩy logic khó xuống Database. An toàn tuyệt đối.

8.4 Automation: Cánh tay nối dài (Webhook)

Code xong Backend rồi, nhưng Sếp muốn: "Có đơn cái là ting ting ngay!". Bạn không thể bắt Sếp ngồi F5 trang Admin cả ngày được.

Chúng ta dùng Webhook kết hợp với n8n (hoặc Make/Zapier).

8.4.1 Quy trình hoạt động:

  1. Sự kiện: Có dòng mới chui vào bảng orders (Supabase).
  2. Trigger: Supabase Database Webhook tự động bắn 1 cục JSON sang URL của n8n.
  3. Xử lý (n8n):
    • Nhận JSON.
    • Format tin nhắn: "💰 Đơn mới #1001 - 500k - Khách: Anh Hiền".
    • Gửi lệnh sang Telegram Bot API.
  4. Kết quả: Điện thoại sếp rung bần bật sau 1 giây khách bấm mua.

8.4.2 Cấu hình thực chiến:

  1. Vào Supabase -> Database -> Webhooks -> Create Webhook.
    • Table: orders
    • Event: INSERT
    • Type: HTTP Request -> Paste link n8n vào.
  2. Vào n8n:
    • Node 1: Webhook (POST).
    • Node 2: Telegram (Send Message).
    • Text: Có đơn mới: {{body.record.id}}. Tiền: {{body.record.total_amount}}.

Đây chính là VibeCode: Kết hợp sức mạnh của Code (SQL Transaction) và sự tiện lợi của Low-code (n8n Automation).

8.5 Bảo mật API: Rào chắn cuối cùng (RLS & Validation)

Đừng tin người dùng. Kể cả họ là khách quen.

8.5.1 Server-side Validation

Frontend đã chặn nhập số âm rồi. Backend có cần chặn lại không? CÓ! Hacker có thể dùng Postman gửi thẳng request { quantity: -10 } lên API để hack kho (trừ của trừ thành cộng). Trong API create_order, bắt buộc phải check: if quantity <= 0: throw Error.

8.5.2 Rate Limiting (Chống Spam)

Đối thủ cạnh tranh có thể viết tool spam 1000 đơn ảo trong 1 giây để phá bạn.

  • Giải pháp: Dùng upstash/ratelimit trong Next.js Middleware.
  • Luật: "Một IP chỉ được tạo tối đa 5 đơn trong 1 phút".

8.6 Tối ưu hiệu năng: Đừng để API "đốt tiền" (Performance)

8.6.1 Bài toán N + 1 Query (Kẻ móc túi thầm lặng)

Đây là lỗi sơ đẳng mà người mới hay gặp.

  • Sai: Lấy 100 đơn hàng (1 query). Sau đó chạy vòng lặp for để lấy tên khách hàng của từng đơn (100 queries nữa). -> Tổng 101 queries. Server quá tải.
  • Đúng: Dùng lệnh JOIN (hoặc select(*, customer:customers(*))). Lấy tất cả trong 1 query duy nhất.

    Ví dụ đi chợ: Đừng chạy ra chợ mua 1 mớ rau rồi chạy về, lặp lại 10 lần. Hãy cầm cái làn, chạy ra chợ 1 lần mua đủ 10 mớ.

8.6.2 Cái bẫy "Realtime" (Thời gian thực)

Khách hàng hay đòi: "Anh muốn nhân viên vừa nhập kho, sếp ở nhà thấy số nhảy ngay lập tức."

  • Cảnh báo: Realtime = Kết nối liên tục = Tốn tiền/Tốn pin. Supabase tính tiền trên số kết nối này.
  • Lời khuyên: Với app quản lý (Admin), đôi khi không cần Realtime từng giây. Chỉ cần dùng cơ chế "Fetch on Focus" (Khi sếp mở app lên thì tải lại data). Tiết kiệm 90% chi phí.

8.6.3 Limit & Pagination (Phân trang)

Đừng bao giờ SELECT * toàn bộ 10,000 dòng dữ liệu về Frontend.


8.7 Đúc kết & Giới thiệu chương tiếp theo

Backend không cần phải làm những thứ cao siêu như Microservices ngay từ đầu. Với SMEs, Backend tốt là Backend:

  1. Chính xác: Tiền nong, kho bãi phải khớp (Transactions)
  2. Thông báo kịp thời: Có automation báo cáo (Webhook + n8n + Telegram)
  3. An toàn: Không bị hack đơn ảo (Validation, Rate Limiting)

Đây chính là VibeCode: Kết hợp sức mạnh của Code (SQL Transaction) và sự tiện lợi của Low-code (n8n Automation).

Bộ xương (Database) và Hệ thần kinh (Backend) đã sẵn sàng. Giờ là lúc khoác lên một tấm áo lộng lẫy để khách hàng chiêm ngưỡng. Ở Chương 9: Frontend & UI, chúng ta sẽ xây giao diện với TailwindCSS + Shadcn/UI - biến những dữ liệu khô khan thành trải nghiệm mua hàng đầy hấp dẫn.