Bỏ qua để đến nội dung

Idempotency

Mạng có thể đứt giữa lúc bạn gửi yêu cầu và nhận phản hồi. Nếu bạn gửi lại một yêu cầu tạo mới, bạn có thể tạo trùng. Idempotency cho phép gửi lại nhiều lần mà kết quả chỉ xảy ra một lần.

Thêm header Idempotency-Key với một giá trị duy nhất cho mỗi thao tác logic vào mọi yêu cầu POST:

Terminal window
curl -X POST "https://api.hoadon.pro/v1/..." \
-H "Authorization: Bearer $HOADON_API_KEY" \
-H "Idempotency-Key: 7b1f6f0e-2c64-4b8e-9f3a-5d2f0c1a9e11" \
-H "Content-Type: application/json" \
-d '{ "org_id": "..." }'
  • Khoá được ghi nhận 24 giờ kể từ lần dùng đầu tiên.
  • Gửi lại cùng khoá và cùng nội dung trong 24 giờ: API trả lại phản hồi đã lưu của lần đầu, không thực hiện lại thao tác.
  • Không dùng một khoá cho hai yêu cầu khác nội dung. Mỗi thao tác logic mới cần khoá mới.
  • Khoá có hiệu lực theo tổ chức gốc của khoá API: hai tích hợp khác nhau có thể dùng cùng một giá trị mà không ảnh hưởng nhau, nhưng nên tránh.
  • Header chỉ có tác dụng với POST. GET vốn an toàn để gửi lại.

Dùng UUID ngẫu nhiên (phiên bản 4) hoặc một mã gắn với thao tác trong hệ thống của bạn, ví dụ erp-invoice-push-INV-2026-0042. Lưu khoá cùng bản ghi của bạn trước khi gửi yêu cầu để khi thử lại bạn dùng đúng khoá cũ.

async function postOnce(url, body, key, attempts = 4) {
for (let i = 0; i < attempts; i += 1) {
try {
const res = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.HOADON_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': key,
},
body: JSON.stringify(body),
});
if (res.status < 500) return res;
} catch {
// lỗi mạng: thử lại với cùng khoá
}
await new Promise((resolve) => setTimeout(resolve, 2 ** i * 500));
}
throw new Error('Hết số lần thử');
}