Sẽ mở trong thẻ mới
PDL AIAI Worker — trợ lý AI trực 24/7: trả lời khách, xử lý yêu cầu, báo cáo tự động

Kỹ sư phần mềm thời AITờ 01-07 / 112

JSON và API: cách các phần mềm nói chuyện với nhau

Quầy giao dịch có bảng dịch vụ và chiếc chuông báo ngược, ví cho API và webhook
Tờ
01-07 / 112
Hạng mục
M01 · Nền tảng máy tính và web cho người không chuyên
Cấp độ
Cơ bản
Thời gian đọc
21 phút
Giai đoạn công trình
0 · Khám phá
Cập nhật
Bản đồ công trìnhTờ này lắp: API, Thanh toán VietQR
Bản đồ công trình Mộc OMSBài này: API, Thanh toán VietQR. Đã học: Coding agent, Khách hàng, Kênh bán, Sheet & sổ tay. Chưa tới: PRD & spec, Repo & CI, Kiểm thử, Hosting & tên miền, Giám sát lỗi, Giao diện app, Database, Dashboard, báo cáo, Trợ lý AI nhận đơn, Màn hình bếp, Đăng nhập, vai trò, Thông báo khách, Nhiều tiệm (MộcOS), Kế toán, hoá đơn.Thi công & hạ tầngDòng đơn hàngNghiệp vụ & dịch vụMở rộng MộcOSPRD & specspecCoding agentagentRepo & CIrepo-ciKiểm thửtestsHosting & tên miềnhostingGiám sát lỗimonitoringKhách hàngcustomerKênh bánchannelsGiao diện appapp-uiAPIapiDatabasedatabaseDashboard, báo cáoreportsSheet & sổ taysheetTrợ lý AI nhận đơnai-assistantMàn hình bếpkitchenĐăng nhập, vai tròauthThanh toán VietQRpaymentsThông báo kháchnotificationsNhiều tiệm (MộcOS)tenantsKế toán, hoá đơnintegrations0 Khám phá1 MVP2 Ra mắt3 Thêm AI4 Mở rộng
Bản đồ công trình Mộc OMSBài này: API, Thanh toán VietQR. Đã học: Coding agent, Khách hàng, Kênh bán, Sheet & sổ tay. Chưa tới: PRD & spec, Repo & CI, Kiểm thử, Hosting & tên miền, Giám sát lỗi, Giao diện app, Database, Dashboard, báo cáo, Trợ lý AI nhận đơn, Màn hình bếp, Đăng nhập, vai trò, Thông báo khách, Nhiều tiệm (MộcOS), Kế toán, hoá đơn.Dòng đơn hàngKhách hàngKênh bánGiao diệnAPIDatabaseBáo cáoNghiệp vụ & dịch vụSheet, sổ tayTrợ lý AIMàn hình bếpĐăng nhậpThanh toánThông báoThi công & hạ tầngPRD & specCoding agentRepo & CIKiểm thửHostingGiám sátMở rộng MộcOSNhiều tiệmKế toán0 Khám phá1234

Bài nàyĐã họcChưa tớiĐã thay thế

Bạn sẽ học được gì

Tiêu chí nghiệm thu

JSON: mẫu phiếu order mà phần mềm nào cũng đọc được

Hãy tưởng tượng mỗi chi nhánh Bánh Mộc tự ghi phiếu đặt bánh gửi bếp trung tâm theo kiểu riêng: Phú Nhuận viết tay, Thảo Điền nhắn Zalo, Gò Vấp gọi điện. Anh Tuấn sẽ phải “dịch” ba kiểu khác nhau mỗi sáng. Giải pháp là một mẫu phiếu chung: ô nào ghi gì, viết theo định dạng nào.

JSON (JavaScript Object Notation) chính là mẫu phiếu chung của thế giới phần mềm. Dù tên có chữ JavaScript, JSON được hầu hết ngôn ngữ (Python, PHP, Go, Java…) đọc và viết được. Nó là chữ thuần, con người cũng đọc được.

Cú pháp JSON trong năm phút

JSON chỉ có vài quy tắc:

  • Object (phiếu có các ô tên): nằm trong { }, gồm các cặp "tên": giá trị, phân cách bằng dấu phẩy.
  • Array (danh sách): nằm trong [ ], các phần tử phân cách bằng dấu phẩy.
  • Tên ô (key) luôn là chuỗi trong dấu nháy kép "...".
  • Giá trị chỉ có sáu loại:
Loại Ví dụ Ghi chú
Chuỗi (string) "BM-261012-007" Bắt buộc nháy kép, không dùng nháy đơn
Số (number) 450000 Không có dấu chấm ngăn cách hàng nghìn, không có đơn vị
Đúng/sai (boolean) true, false Viết thường, không có nháy
Rỗng null Cố ý để trống
Object { "size": "20cm" } Có thể lồng nhau
Array [1, 2, 3] Có thể chứa object

Bạn sẽ thấy JSON rất giống object và array trong TypeScript ở bài Đọc hiểu code cơ bản01-04. Điều đó không ngẫu nhiên; JSON được phát triển từ cách viết đó, nhưng chặt chẽ hơn.

Một đơn hàng Bánh Mộc dạng JSON

Đây là đơn của chị Hương (đơn quen thuộc từ các bài trước) khi Mộc OMS trả về cho một ứng dụng khác. Tên các ô bám theo mô hình dữ liệu của dự án (orders, order_items, customers), nhưng viết theo quy ước camelCase của API: database lưu delivery_at, API trả deliveryAt; mã định danh (id) là chuỗi uuid:

JSON
{
  "code": "BM-261012-007",
  "channel": "zalo",
  "status": "da_xac_nhan",
  "branch": { "id": "b1a7c3e2-5d4f-4a6b-8c9d-0e1f2a3b4c5d", "name": "Bánh Mộc Phú Nhuận" },
  "customer": {
    "id": "c2b8d4f3-6e5a-4b7c-9d0e-1f2a3b4c5d6e",
    "fullName": "Trần Thị Hương",
    "phone": "0901234123"
  },
  "deliveryType": "delivery",
  "deliveryAt": "2026-10-13T15:00:00+07:00",
  "deliveryAddress": "45 đường Số 7, phường Mẫu, TP.HCM",
  "items": [
    {
      "productId": "a3c9e5f4-7f6b-4c8d-8e1f-2a3b4c5d6e7f",
      "productName": "Bánh kem dâu 20cm",
      "isCustomCake": true,
      "quantity": 1,
      "unitPrice": 450000,
      "cakeMessage": "Mừng sinh nhật Bin",
      "options": { "size": "20cm", "flavor": "dâu", "candles": 5 }
    },
    {
      "productId": "d4dae6a5-8a7c-4d9e-9f2a-3b4c5d6e7f80",
      "productName": "Bánh quy hộp quà",
      "isCustomCake": false,
      "quantity": 2,
      "unitPrice": 120000,
      "cakeMessage": null,
      "options": {}
    }
  ],
  "subtotal": 690000,
  "shippingFee": 0,
  "total": 690000,
  "deposit": 345000,
  "paymentStatus": "deposit",
  "note": "Gọi trước khi giao 15 phút",
  "createdAt": "2026-10-12T09:24:00+07:00"
}

(Tên, số điện thoại, địa chỉ là dữ liệu minh họa.)

Đọc từ trên xuống như đọc một phiếu:

  • Đơn BM-261012-007, nhận qua Zalo, đã xác nhận, thuộc chi nhánh Phú Nhuận.
  • Khách là một object lồng bên trong (customer), có mã, tên, số điện thoại.
  • items là một danh sách hai món. Món đầu là bánh kem tùy chỉnh (isCustomCake: true), có chữ trên bánh và các tùy chọn size, vị, số nến. Món thứ hai không có chữ (null) và không có tùy chọn ({}).
  • Các con số tiền khớp với phép tính bạn đã “chạy tay” ở bài 01-04: 450.000 + 2 × 120.000 = 690.000, giao tận nơi nhưng từ 500.000 nên miễn ship, đã cọc 345.000 (50% tiền bánh, đủ điều kiện xác nhận đơn).

Hai quy ước quan trọng trong ví dụ:

  • Tiền là số nguyên VNĐ (690000), không viết "690.000đ" hay 690000.0. Định dạng hiển thị là việc của giao diện.
  • Thời gian là chuỗi theo chuẩn ISO 8601 kèm múi giờ: "2026-10-13T15:00:00+07:00" nghĩa là 15 giờ ngày 13/10/2026 giờ Việt Nam. JSON không có kiểu ngày giờ riêng; nếu bỏ phần +07:00, hệ thống khác có thể hiểu nhầm thành giờ quốc tế và bánh được giao lệch 7 tiếng.

Lỗi JSON thường gặp và thông báo tương ứng

JSON khắt khe hơn TypeScript. Bốn lỗi phổ biến nhất, kèm thông báo bạn sẽ thấy (trong Node.js và các trình duyệt dựa trên Chromium, tại thời điểm viết):

Lỗi Ví dụ sai Thông báo thường gặp
Dấu phẩy thừa ở cuối {"total": 690000,} Expected double-quoted property name in JSON at position ...
Dùng nháy đơn {'code': "BM-1"} Expected property name or '}' in JSON at position 1
Có chú thích (JSON không cho phép) {"code": "BM-1" // ghi chú} Expected ',' or '}' after property value in JSON at position ...
Bị cắt cụt, thiếu dấu đóng {"code": "BM-1" Expected ',' or '}' after property value... hoặc Unexpected end of JSON input

Và một lỗi cực kỳ phổ biến khi làm việc với API:

Phiên agent

SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

Dịch: code chờ nhận JSON, nhưng server trả về một trang HTML (bắt đầu bằng <!DOCTYPE). Thường gặp khi gọi sai địa chỉ (server trả trang lỗi 404 dạng HTML), chưa đăng nhập (bị chuyển sang trang đăng nhập), hoặc server gặp lỗi 500 và trả trang báo lỗi. Gặp lỗi này, đừng sửa phần đọc JSON; hãy kiểm tra URL và mã trạng thái của request trước.

API: quầy giao dịch có thực đơn

API (Application Programming Interface, giao diện lập trình ứng dụng) là cách một phần mềm mở “cửa” cho phần mềm khác sử dụng chức năng của nó.

Ẩn dụ quen thuộc: quầy giao dịch ngân hàng có bảng dịch vụ. Bạn không vào két, không sửa sổ cái. Bạn đến quầy, chọn dịch vụ trong bảng (gửi tiền, rút tiền, sao kê), điền đúng mẫu, xuất trình giấy tờ, và nhận kết quả. Bảng dịch vụ và mẫu giấy tờ chính là tài liệu API.

Ở bài Phần mềm thực chất là gì01-01, bạn biết giao diện không chỉ dành cho con người. API là giao diện dành cho phần mềm. Mộc OMS sẽ vừa dùng API của người khác (Supabase, VietQR, Zalo, dịch vụ email, mô hình AI), vừa có thể cung cấp API (cho trợ lý AI nhận đơn qua Zalo ở module 12 gửi đơn vào hệ thống).

REST API: kiểu quầy giao dịch phổ biến nhất

Có nhiều kiểu API, nhưng kiểu bạn gặp nhiều nhất trên web là REST API. Ý tưởng cốt lõi: mỗi tài nguyên (đơn hàng, khách hàng, sản phẩm) có một địa chỉ, và bạn dùng HTTP method (đã học ở bài Internet và Web hoạt động thế nào01-02) để nói muốn làm gì với nó.

Một endpoint là sự kết hợp method + đường dẫn, tương ứng một “dịch vụ” trong bảng. Ví dụ bảng dịch vụ của Mộc OMS (minh họa):

Method Đường dẫn Việc làm Mã trả về khi thành công
GET /api/orders?date=2026-10-12&status=moi Lấy danh sách đơn theo ngày và trạng thái 200
GET /api/orders/BM-261012-007 Xem chi tiết một đơn 200
POST /api/orders Tạo đơn mới 201
PATCH /api/orders/BM-261012-007 Sửa một phần đơn, ví dụ đổi trạng thái 200
POST /api/webhooks/payments Nhận thông báo thanh toán từ bên ngoài (xem phần webhook) 200

Để ý: không có DELETE /api/orders/.... Ở Bánh Mộc, đơn không bao giờ bị xóa mà chuyển sang trạng thái da_huy, để còn lịch sử đối soát. Đây là một quyết định nghiệp vụ thể hiện qua thiết kế API. Cách thiết kế API bài bản (đặt tên, phân trang, định dạng lỗi) có trong bài Thiết kế API04-04.

Giải phẫu một lần gọi API

Một request API gồm bốn phần, như một bộ hồ sơ nộp ở quầy:

  1. Method + URL: dịch vụ nào. POST https://oms.banhmoc.vn/api/orders
  2. Header: thông tin trên bìa hồ sơ. Hai header gặp nhiều nhất:
    • Authorization: Bearer <token>: “đây là giấy tờ chứng minh tôi được phép”.
  3. Body: nội dung hồ sơ, dạng JSON. Request GET thường không có body; thông tin lọc nằm trong query (?date=...&status=...).
  4. Response: mã trạng thái + header + body JSON.

Ví dụ request tạo đơn và response tương ứng:

Phiên agent

POST /api/orders HTTP/1.1
Host: oms.banhmoc.vn
Content-Type: application/json
Authorization: Bearer <token-của-ứng-dụng-gọi>

{
  "customerPhone": "0901234123",
  "channel": "zalo",
  "deliveryType": "pickup",
  "deliveryAt": "2026-10-13T10:00:00+07:00",
  "items": [{ "productId": "d4dae6a5-8a7c-4d9e-9f2a-3b4c5d6e7f80", "quantity": 2 }]
}

Phiên agent

HTTP/1.1 201 Created
Content-Type: application/json

{ "code": "BM-261012-008", "status": "moi", "subtotal": 240000, "shippingFee": 0, "total": 240000 }

Chú ý: request không gửi giá. Server tự tra giá sản phẩm (bánh quy hộp quà) theo productId và tính tổng, đúng quy tắc “không tin dữ liệu từ bên ngoài” ở bài Frontend, backend, database01-03. Quy tắc này áp dụng cho mọi phần mềm gọi API của bạn, không chỉ trình duyệt.

Khi có lỗi, một API tốt trả mã trạng thái phù hợp kèm thông báo rõ ràng:

JSON
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Giờ nhận phải sau thời điểm đặt ít nhất 24 giờ đối với bánh kem.",
    "field": "delivery_at"
  }
}

API key và xác thực cơ bản

Quầy giao dịch không phục vụ người lạ. Phần mềm gọi API phải chứng minh mình là ai. Cách phổ biến và đơn giản nhất là API key: một chuỗi ký tự dài, ngẫu nhiên, do nhà cung cấp cấp cho bạn, giống thẻ ra vào kèm hạn mức chi tiêu.

API key thường được gửi trong header, tùy nhà cung cấp quy định:

Phiên agent

Authorization: Bearer sk_live_51Hx...   (dạng phổ biến)
x-api-key: 7f3a9c...                   (một số dịch vụ dùng header riêng)

Vì sao API key nguy hiểm nếu lộ? Vì ai cầm nó cũng được coi là chính bạn: gửi tin nhắn Zalo dưới danh nghĩa tiệm, đọc dữ liệu khách hàng, gọi mô hình AI và bạn trả tiền. Ba quy tắc tối thiểu:

  1. Không bao giờ đặt API key bí mật trong code frontend (ai cũng xem được, như bài 01-03 đã nói).
  2. Không bao giờ viết thẳng key vào code hay đưa vào Git. Key nằm trong biến môi trường, chủ đề của bài kế tiếp.
  3. Mỗi môi trường, mỗi mục đích một key riêng, để khi lộ có thể thu hồi một key mà không ảnh hưởng tất cả.

Ngoài API key, bạn sẽ gặp các cơ chế phức tạp hơn như OAuth (bấm “Đăng nhập bằng Google/Zalo” để cấp quyền cho ứng dụng khác mà không đưa mật khẩu) và token có thời hạn (như “access token” của Zalo OA cần làm mới định kỳ). Nguyên tắc bảo vệ giống nhau: đó là chìa khóa, phải cất kỹ.

Webhook: API “gọi ngược”

Bình thường, bạn gọi API của người khác khi bạn cần. Nhưng có những việc bạn không biết khi nào xảy ra. Ví dụ: khách quét mã VietQR chuyển cọc 345.000đ. Tiền về lúc nào? Mộc OMS có thể hỏi ngân hàng mỗi 5 giây “đã có tiền chưa?” (gọi là polling, hỏi liên tục). Cách này lãng phí và chậm.

Webhook đảo chiều: bạn đăng ký với bên kia một địa chỉ, và khi có sự kiện, bên kia chủ động gọi tới địa chỉ đó. Ẩn dụ: thay vì cứ 5 phút gọi shipper hỏi “giao chưa em?”, bạn dặn “giao xong nhắn chị nhé”. Webhook chính là tin nhắn “giao xong rồi chị”.

Với VietQR, chuẩn QR chuyển khoản liên ngân hàng, nhiều ngân hàng và cổng trung gian thanh toán cung cấp webhook báo giao dịch đến. Luồng xử lý trong Mộc OMS trông thế này:

Hình chữ ký Hành trình request
  1. Khách
  2. Ngân hàng / cổng thanh toán
  3. Mộc OMS
  4. Kiểm tra chữ ký, đúng là ngân hàng gửi?
  5. Mã giao dịch này đã ghi nhận chưa?
  6. Đơn BM-261012-007 đã nhận cọc
Xem sơ đồ gốc (Hình 1)

Vuốt ngang để xem hết sơ đồ

Màn hình của HàDatabaseMộc OMS/api/webhooks/paymentsNgân hàng / cổng thanh toán

KháchQuét VietQR, chuyển 345.000đ, nội dung BM-261012-0071POST webhook (JSON giao dịch + chữ ký)2Kiểm tra chữ ký, đúng là ngân hàng gửi?3Mã giao dịch này đã ghi nhận chưa?4Chưa có5Ghi payments, cập nhật payment_status = deposit6200 OK (đã nhận)7Đơn BM-261012-007 đã nhận cọc8

Hình 1 Sơ đồ tuần tự
Đọc sơ đồ dạng chữ
  1. Khách → Ngân hàng / cổng thanh toán: Quét VietQR, chuyển 345.000đ, nội dung BM-261012-007
  2. Ngân hàng / cổng thanh toán → Mộc OMS /api/webhooks/payments: POST webhook (JSON giao dịch + chữ ký)
  3. Mộc OMS /api/webhooks/payments → Mộc OMS /api/webhooks/payments: Kiểm tra chữ ký, đúng là ngân hàng gửi?
  4. Mộc OMS /api/webhooks/payments → Database: Mã giao dịch này đã ghi nhận chưa?
  5. Database → Mộc OMS /api/webhooks/payments: Chưa có
  6. Mộc OMS /api/webhooks/payments → Database: Ghi payments, cập nhật payment_status = deposit
  7. Mộc OMS /api/webhooks/payments → Ngân hàng / cổng thanh toán: 200 OK (đã nhận)
  8. Mộc OMS /api/webhooks/payments → Màn hình của Hà: Đơn BM-261012-007 đã nhận cọc

Ba điểm kỹ thuật bạn cần biết để kiểm tra code agent viết cho webhook:

  1. Xác minh người gửi. Địa chỉ webhook là công khai; kẻ xấu có thể gửi một request giả “khách đã chuyển 5 triệu”. Nhà cung cấp thường kèm chữ ký (signature) hoặc khóa bí mật để bạn kiểm tra. Code không kiểm tra chữ ký là lỗ hổng nghiêm trọng.
  2. Chống ghi trùng (idempotency). Nhà cung cấp có thể gửi lại cùng một thông báo nhiều lần (khi mạng chập chờn, khi chưa nhận được 200). Code phải kiểm tra mã giao dịch (cột reference trong bảng payments) để không ghi nhận một khoản tiền hai lần.
  3. Trả lời nhanh. Bên gửi chờ phản hồi trong thời gian giới hạn; việc nặng (gửi email, tính báo cáo) nên làm sau.

Chi tiết tích hợp thanh toán và webhook được bàn trong bài Tích hợp bên thứ ba04-08.

Đọc tài liệu API có hệ thống

Khi tích hợp một dịch vụ, agent sẽ đọc tài liệu API. Nhưng bạn cần biết tài liệu có những gì để kiểm tra agent hiểu đúng, và để phát hiện khi agent bịa ra một endpoint không tồn tại (điều xảy ra khá thường xuyên với dịch vụ ít phổ biến). Một bộ tài liệu API tốt có:

Mục Câu hỏi cần trả lời
Base URL Địa chỉ gốc là gì? Có địa chỉ riêng cho môi trường thử nghiệm (sandbox) không?
Xác thực Dùng API key, OAuth hay token? Đặt ở header nào? Lấy key ở đâu?
Danh sách endpoint Có những dịch vụ nào, method và đường dẫn ra sao?
Tham số và body Gửi những ô nào, ô nào bắt buộc, kiểu dữ liệu gì?
Ví dụ response Thành công trả về gì? Lỗi trả về gì?
Mã lỗi Từng mã lỗi nghĩa là gì, xử lý thế nào?
Giới hạn tốc độ (rate limit) Được gọi bao nhiêu lần mỗi phút? Vượt thì bị 429.
Webhook Có không, định dạng ra sao, cách xác minh chữ ký?
Phiên bản và thay đổi API có đánh phiên bản không? Có trang ghi thay đổi (changelog) không?
Giá Tính phí theo lượt gọi, theo tháng, hay theo tin nhắn? (luôn kiểm tra trang chính thức)

Gọi thử API: curl và công cụ giao diện

Cách tốt nhất để hiểu API là tự gọi một lần. Bạn không cần viết chương trình.

Dùng curl trong terminal

curl là công cụ dòng lệnh gửi request HTTP, có sẵn trên macOS, hầu hết bản Linux, và Windows 10/11. Thử gọi API công khai của GitHub, lấy thông tin một tài khoản mẫu, không cần key:

BASH
# macOS / Linux
curl https://api.github.com/users/octocat

# Thêm -i để xem cả mã trạng thái và header
curl -i https://api.github.com/users/octocat
POWERSHELL
# Windows PowerShell: gõ curl.exe để dùng đúng curl
# (trong Windows PowerShell 5.1, "curl" là tên gọi tắt của một lệnh khác)
curl.exe -i https://api.github.com/users/octocat

Bạn sẽ thấy dòng HTTP/2 200 (hoặc tương tự), các header, rồi một khối JSON chứa tên, số repo, ngày tạo tài khoản. Hãy thử sửa octocat thành một tên không tồn tại và xem mã trạng thái đổi thành 404.

Khi Mộc OMS chạy trên máy, agent có thể dùng curl để kiểm chứng API vừa viết, ví dụ:

BASH
# Gửi đơn mới (nội dung lấy từ file don-moi.json) tới server đang chạy trên máy
curl -i -X POST http://localhost:3000/api/orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OMS_TEST_TOKEN" \
  -d @don-moi.json

Đọc lệnh: -X POST là method, -H thêm header, -d @don-moi.json lấy body từ file, $OMS_TEST_TOKEN là token đọc từ biến môi trường thay vì gõ thẳng (bài sau sẽ giải thích). Dấu \ ở cuối dòng chỉ để viết một lệnh dài trên nhiều dòng (cú pháp macOS/Linux).

Công cụ có giao diện

Nếu thích bấm nút hơn gõ lệnh, có nhiều công cụ giao diện để gửi request và xem response đẹp mắt, như Postman, Insomnia, Bruno, Hoppscotch, hoặc tiện ích mở rộng trong VS Code. Tính năng và chính sách giá thay đổi theo thời gian; hãy xem trang chính thức tại thời điểm bạn dùng. Với người mới, chúng giúp nhìn thấy rõ bốn phần của request: method, URL, header, body.

Áp dụng vào dự án Bánh Mộc

Nhật ký công trình · Bánh Mộc

BM-261013-013

13.10.2026

  • Chị LanChủ chuỗi
  • HàBán hàng online
Chị Lan gửi lại lệnh thử webhook lần hai và thấy sổ không có dòng trùng

Chị Lan muốn khi khách chuyển cọc bằng VietQR, Hà thấy ngay trên màn hình, không phải mở app ngân hàng dò từng giao dịch như hiện nay. Trước khi giao việc cho agent, chị làm bài tập “đọc tài liệu API” với nhà cung cấp dịch vụ thanh toán mà ngân hàng của tiệm giới thiệu:

  1. Chị mở tài liệu chính thức, điền bảng 10 câu hỏi ở trên. Chị phát hiện dịch vụ có môi trường sandbox, có webhook kèm chữ ký, và có giới hạn số lần gọi mỗi phút.
  2. Chị nhờ agent chỉ đọc tài liệu và tóm tắt, không viết code, rồi đối chiếu với bảng của mình. Agent ban đầu mô tả một endpoint “xác nhận giao dịch” không có trong tài liệu. Chị hỏi lại nguồn, agent thừa nhận đã suy đoán. Bài học được ghi vào sổ: luôn yêu cầu dẫn nguồn.
  3. Chị viết yêu cầu cho agent với các tiêu chí rõ ràng: kiểm tra chữ ký, không ghi trùng giao dịch theo mã reference, ghi vào bảng payments, cập nhật payment_status, trả 200 nhanh, và viết test cho ba trường hợp: giao dịch hợp lệ, chữ ký sai, giao dịch gửi lặp lại.

Agent hoàn thành ở môi trường thử nghiệm và gửi kèm lệnh curl mô phỏng webhook để chị tự chạy. Lần đầu tiên, chị tự gõ một lệnh terminal, thấy HTTP/1.1 200 OK và một dòng mới xuất hiện trong bảng thanh toán thử nghiệm. Chị gửi lại lệnh đó lần nữa, và không có dòng thứ hai. Chống ghi trùng hoạt động.

Prompt mẫu

Prompt 1: tóm tắt tài liệu API trước khi tích hợp.

Tôi sắp tích hợp [tên dịch vụ] vào Mộc OMS. Đây là link/tài liệu chính thức: [dán].
CHƯA viết code. Hãy tóm tắt theo bảng: base URL (production và sandbox), cách xác thực,
các endpoint cần cho việc [mô tả nhu cầu], body và response mẫu, mã lỗi chính,
giới hạn tốc độ, webhook và cách xác minh chữ ký. Với mỗi thông tin, ghi rõ trích từ
phần nào của tài liệu. Thông tin nào tài liệu không nói, ghi "không có trong tài liệu",
không được suy đoán.

Prompt 2: viết webhook an toàn.

Viết route handler nhận webhook thanh toán tại /api/webhooks/payments theo tài liệu đã tóm tắt.
Yêu cầu:
- Xác minh chữ ký bằng secret đọc từ biến môi trường PAYMENT_WEBHOOK_SECRET; sai chữ ký trả 401.
- Validate body bằng Zod.
- Chống ghi trùng: nếu reference đã tồn tại trong bảng payments thì trả 200 và không ghi thêm.
- Ghi payments, cập nhật orders.payment_status trong cùng một transaction.
- Trả 200 nhanh; không gửi email/Zalo trong request này.
Viết test cho: hợp lệ, chữ ký sai, gửi lặp. Chạy test và dán kết quả.
Cuối cùng đưa tôi một lệnh curl mẫu (dùng dữ liệu giả) để tôi tự thử trên máy.

Prompt 3: giải thích một JSON hoặc một lỗi API.

Đây là response tôi nhận được khi gọi API (đã che thông tin nhạy cảm):
[dán mã trạng thái, header quan trọng và body]
Hãy giải thích từng ô trong JSON nghĩa là gì, request có thành công không, và nếu lỗi
thì nguyên nhân khả dĩ và cách kiểm tra. Nếu body là HTML thay vì JSON, giải thích vì sao.

Sai lầm thường gặp

  1. Sự cố 01

    Tin endpoint do AI “nhớ”.

    Triệu chứng

    Agent viết code gọi một endpoint không tồn tại hoặc đã đổi, chạy thử mới lỗi, mất thời gian dò.

    Cách tránh

    Bắt agent dẫn nguồn tài liệu chính thức; gọi thử ở sandbox bằng curl trước khi viết code đầy đủ.

  2. Sự cố 02

    Webhook không xác minh chữ ký.

    Triệu chứng

    Ai biết địa chỉ webhook cũng có thể giả mạo thông báo “đã thanh toán”.

    Cách tránh

    Yêu cầu bắt buộc kiểm tra chữ ký; có test cho trường hợp chữ ký sai.

  3. Sự cố 03

    Ghi nhận một khoản tiền nhiều lần.

    Triệu chứng

    Nhà cung cấp gửi lại webhook, hệ thống cộng tiền hai lần, đối soát cuối ngày lệch.

    Cách tránh

    Dùng mã giao dịch làm khóa duy nhất; có test “gửi lặp”.

  4. Sự cố 04

    Thời gian thiếu múi giờ, tiền có định dạng.

    Triệu chứng

    "2026-10-12 15:00" hay "690.000đ" trong JSON gây hiểu nhầm giữa các hệ thống.

    Cách tránh

    Quy định trong AGENTS.md: thời gian theo ISO 8601 kèm múi giờ; tiền là số nguyên VNĐ.

  5. Sự cố 05

    Lộ API key qua chat, ảnh chụp hoặc code.

    Triệu chứng

    Key đã lộ phải coi như bị đánh cắp.

    Cách tránh

    Chỉ nhắc tên biến môi trường; che key trong mọi ảnh chụp và lệnh curl chia sẻ; thu hồi ngay khi nghi lộ.

Checklist

Phiếu nghiệm thu

Bài tập thực hành

Phiên agent

{
  'code': "BM-261012-009",
  "total": 350.000,
  "isPaid": "false",
  "items": [ { "productId": "a3c9e5f4-7f6b-4c8d-8e1f-2a3b4c5d6e7f", "quantity": 1 }, ],
}

Kết quả mong đợi: (1) 'code' phải dùng nháy kép; (2) 350.000 sẽ bị hiểu là ba trăm năm mươi (số thập phân), phải viết 350000; (3) "false" là chuỗi, nên là false (và trong mô hình Bánh Mộc nên dùng "paymentStatus": "unpaid"); (4) dấu phẩy thừa sau phần tử cuối của mảng và sau ]. Lỗi (2) và (3) không làm JSON sai cú pháp nhưng sai ý nghĩa, loại lỗi nguy hiểm hơn vì máy không báo.

  1. Bài 1

    Cơ bản

    Sửa JSON lỗi

    Đoạn sau có 4 lỗi. Tìm và sửa:

  2. Bài 2

    Cơ bản

    Gọi API GitHub

    Chạy curl -i https://api.github.com/users/octocat (Windows: curl.exe -i ...). Tìm trong kết quả: mã trạng thái, header content-type, và ô public_repos trong JSON. Rồi thử với một tên không tồn tại.

    Kết quả mong đợi

    Lần đầu mã 200 và content-type là application/json; lần sau mã 404 kèm JSON báo “Not Found”.

  3. Bài 3

    Nâng cao

    Đọc tài liệu một API thật

    Chọn một dịch vụ bạn định tích hợp (thanh toán, gửi email, tin nhắn). Mở tài liệu chính thức, điền bảng 10 câu hỏi. Sau đó dùng Prompt mẫu 1 và so sánh bảng của bạn với bảng agent tóm tắt.

    Kết quả mong đợi

    Hai bảng khớp ở phần lớn thông tin; mọi chỗ khác biệt đều được kiểm tra lại với tài liệu gốc. Ghi lại nếu agent có thông tin không dẫn nguồn được.

Thuật ngữ trong bài

JSON
Định dạng dữ liệu dạng chữ, “mẫu phiếu chung” giữa các phần mềm
Object / Array (JSON)
Phiếu có các ô tên {} / danh sách []
ISO 8601
Chuẩn viết ngày giờ, ví dụ 2026-10-12T15:00:00+07:00
API
Giao diện để phần mềm khác sử dụng chức năng của bạn
REST API
Kiểu API dùng URL cho tài nguyên và HTTP method cho hành động
Endpoint
Một “dịch vụ” của API: method + đường dẫn
Header Authorization
Nơi đặt giấy tờ xác thực như API key, token
API key
Chuỗi bí mật chứng minh phần mềm gọi là ai
OAuth
Cơ chế cấp quyền cho ứng dụng khác mà không đưa mật khẩu
Rate limit
Giới hạn số lần gọi trong một khoảng thời gian
Sandbox
Môi trường thử nghiệm của nhà cung cấp, không dùng tiền/dữ liệu thật
Polling
Hỏi đi hỏi lại định kỳ xem có gì mới
Webhook
Bên kia chủ động gọi tới bạn khi có sự kiện
Chữ ký (signature)
Dấu xác minh request webhook đúng do nhà cung cấp gửi
Idempotency (chống trùng)
Xử lý cùng một yêu cầu nhiều lần vẫn cho kết quả như một lần
curl
Công cụ dòng lệnh gửi request HTTP

Đọc thêm

Nghiệm thu tờ 01-07

Đọc xong và tự kiểm theo phiếu nghiệm thu, rồi đánh dấu tờ này.

Tác giả
Phú Digital
Đội ngũ PDL Digital — triển khai website, giải pháp AI và digital marketing cho doanh nghiệp.
Tư vấn 1:1

Muốn dựng phần mềm riêng cho doanh nghiệp của bạn?

Kỹ sư PDL cùng bạn chọn bước đầu tiên phù hợp — phản hồi trong giờ làm việc (T2–T7, 8h–18h).

<script src="https://cdn.jsdelivr.net/npm/page-flip/dist/js/page-flip.browser.js"></script>

<div id="container-flipbook" style="display:flex; justify-content:center;">
    <div id="my-flipbook">
       <div class="page"> <img src="https://pdl.vn/wp-content/uploads/2025/05/AI-Google-Search.jpg" /> </div>
       <div class="page"> <img src="https://pdl.vn/wp-content/uploads/2025/05/wearable-tech-advertising.jpg" /> </div>
       <div class="page"> <img src="https://pdl.vn/wp-content/uploads/2025/05/multimodal-embeddings-digital-marketing.jpg" /> </div>
    </div>
</div>
#my-flipbook {
    box-shadow: 0 0 20px rgba(0,0,0,0.2);
    margin: 20px auto;
    background-color: #f0f0f0;
}

.page {
    background-color: white;
    overflow: hidden;
}

.page img {
    width: 100%;
    height: 100%;
    object-fit: cover; /* Giúp ảnh vừa vặn trang sách */
}
// Đảm bảo thư viện đã sẵn sàng
function initFlipbook() {
    const el = document.getElementById("my-flipbook");
    if (!el || !window.St) return; // Nếu chưa thấy thư viện St thì thoát

    const pageFlip = new St.PageFlip(el, {
        width: 550,
        height: 733,
        size: "stretch",
        minWidth: 315,
        maxWidth: 1000,
        minHeight: 420,
        maxHeight: 1350,
        showCover: true,
        maxShadowOpacity: 0.5,
    });

    pageFlip.loadFromHTML(document.querySelectorAll(".page"));
}

// Chạy khởi tạo
if (document.readyState === 'complete') {
    initFlipbook();
} else {
    window.addEventListener('load', initFlipbook);
}
PDL · Tư vấn 1:1

Nhận tư vấn
miễn phí

Để lại thông tin, chuyên viên PDL sẽ liên hệ để hiểu nhu cầu và đề xuất giải pháp phù hợp ngân sách của bạn.

  • Phân tích nhanh hiện trạng website, quảng cáo, kênh bán hàng
  • Đề xuất lộ trình & báo giá minh bạch, rõ từng hạng mục
  • Không ràng buộc: nghe tư vấn xong mới quyết định
Giờ làm việc T2–T7 · 08:00–18:00

Chỉ mất khoảng 30 giây

Bạn cần tư vấn về

🔒 Thông tin được bảo mật, chỉ dùng để PDL liên hệ tư vấn.