Bản đồ công trìnhTờ này lắp: API, Thanh toán VietQR
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:
{
"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. itemslà 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đ"hay690000.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:
Điền ô trống rồi sao chép
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:
- Method + URL: dịch vụ nào.
POST https://oms.banhmoc.vn/api/orders - 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”.
- Body: nội dung hồ sơ, dạng JSON. Request
GETthường không có body; thông tin lọc nằm trong query (?date=...&status=...). - Response: mã trạng thái + header + body JSON.
Ví dụ request tạo đơn và response tương ứng:
Điền ô trống rồi sao chép
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 }]
}
Điền ô trống rồi sao chép
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:
{
"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:
Điền ô trống rồi sao chép
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:
- 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).
- 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.
- 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:
- Khách
- Ngân hàng / cổng thanh toán
- Mộc OMS
- Kiểm tra chữ ký, đúng là ngân hàng gửi?
- Mã giao dịch này đã ghi nhận chưa?
- Đơn BM-261012-007 đã nhận cọc
Xem sơ đồ gốc (Hình 1)
Vuốt ngang để xem hết sơ đồ
Đọc sơ đồ dạng chữ
- Khách → Ngân hàng / cổng thanh toán: Quét VietQR, chuyển 345.000đ, nội dung BM-261012-007
- Ngân hàng / cổng thanh toán → Mộc OMS /api/webhooks/payments: POST webhook (JSON giao dịch + chữ ký)
- 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?
- Mộc OMS /api/webhooks/payments → Database: Mã giao dịch này đã ghi nhận chưa?
- Database → Mộc OMS /api/webhooks/payments: Chưa có
- Mộc OMS /api/webhooks/payments → Database: Ghi payments, cập nhật payment_status = deposit
- Mộc OMS /api/webhooks/payments → Ngân hàng / cổng thanh toán: 200 OK (đã nhận)
- 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:
- 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.
- 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
referencetrong bảngpayments) để không ghi nhận một khoản tiền hai lần. - 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:
# 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
# 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ụ:
# 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 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:
- 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.
- 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.
- 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ảngpayments, cập nhậtpayment_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
Điền ô trống rồi sao ché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.
Điền ô trống rồi sao chép
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.
Điền ô trống rồi sao chép
Đâ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
-
Sự cố 01
Tin endpoint do AI “nhớ”.
Triệu chứngAgent 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ánhBắ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 đủ.
-
Sự cố 02
Webhook không xác minh chữ ký.
Triệu chứngAi biết địa chỉ webhook cũng có thể giả mạo thông báo “đã thanh toán”.
Cách tránhYêu cầu bắt buộc kiểm tra chữ ký; có test cho trường hợp chữ ký sai.
-
Sự cố 03
Ghi nhận một khoản tiền nhiều lần.
Triệu chứngNhà 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ánhDùng mã giao dịch làm khóa duy nhất; có test “gửi lặp”.
-
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ánhQuy định trong AGENTS.md: thời gian theo ISO 8601 kèm múi giờ; tiền là số nguyên VNĐ.
-
Sự cố 05
Lộ API key qua chat, ảnh chụp hoặc code.
Triệu chứngKey đã lộ phải coi như bị đánh cắp.
Cách tránhChỉ 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
Bài tập thực hành
Điền ô trống rồi sao chép
{
'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.
-
Bài 1
Cơ bản
Sửa JSON lỗi
Đoạn sau có 4 lỗi. Tìm và sửa:
-
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, headercontent-type, và ôpublic_repostrong 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-typelàapplication/json; lần sau mã 404 kèm JSON báo “Not Found”. -
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
- 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
- MDN Web Docs: tìm “Working with JSON”, “HTTP headers”.
- GitHub Docs: ví dụ về một bộ tài liệu REST API được tổ chức tốt.
- Thiết kế API: endpoint, phương thức, mã trạng thái và hợp đồng dữ liệu04-04
- Tích hợp bên thứ ba: thanh toán, thông báo, webhook04-08
- Quản lý secrets: API key, mật khẩu và file .env09-03
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.

