Thứ tự và trùng lặp
thu tu va trung lapWebhook Dòng Tiền Pro giao ít nhất một lần và không đảm bảo thứ tự: cách khử trùng theo webhook-id, xử lý sự kiện tới sai thứ tự và nhận tiền về đúng một lần. webhook dong tien pro giao it nhat mot lan va khong dam bao thu tu: cach khu trung theo webhook-id, xu ly su kien toi sai thu tu va nhan tien ve dung mot lan.Dòng Tiền Pro giao webhook theo nguyên tắc ít nhất một lần: sự kiện không bị mất, nhưng có thể tới hai lần (ví dụ khi phản hồi 2xx của bạn bị mất giữa đường) và các sự kiện khác nhau có thể tới không đúng thứ tự phát sinh. Bộ nhận phải chịu được cả hai điều đó.
Khử trùng theo webhook-id
Phần tiêu đề “Khử trùng theo webhook-id”Mỗi lần giao mang header webhook-id dạng msg_…. Giá trị này giữ nguyên qua mọi lần thử lại và cả khi phát lại thủ công, nên nó là khoá khử trùng đúng. Cách làm chắc chắn nhất là ghi webhook-id vào một bảng có ràng buộc duy nhất, rồi chỉ xử lý nếu việc ghi thành công:
CREATE TABLE webhook_inbox ( webhook_id text PRIMARY KEY, received_at timestamptz NOT NULL DEFAULT now());
-- Một hàng được thêm: lần đầu thấy, xử lý. Không thêm hàng nào: đã xử lý, trả 2xx và bỏ qua.INSERT INTO webhook_inbox (webhook_id) VALUES ($1) ON CONFLICT DO NOTHING;Thực hiện INSERT và việc cập nhật dữ liệu nghiệp vụ trong cùng một giao dịch cơ sở dữ liệu. Nếu xử lý lỗi, giao dịch quay lui, webhook_id không được lưu, và lần giao lại sau đó được xử lý bình thường.
Khoá khử trùng thay thế là data.object.id (ví dụ tx_…) kèm loại sự kiện, hữu ích khi bạn muốn một giao dịch chỉ kích hoạt một hành động duy nhất cho mỗi loại sự kiện.
Không đảm bảo thứ tự
Phần tiêu đề “Không đảm bảo thứ tự”Hai sự kiện của cùng một giao dịch, ví dụ transaction.created rồi transaction.confirmed, có thể tới ngược thứ tự, nhất là khi một lần giao phải thử lại. Cách xử lý:
- Dựa vào dữ liệu trong sự kiện, không dựa vào thứ tự đến:
timestampcủa phong bì và các trường nhưstatus,occurred_atcủa đối tượng cho biết trạng thái nào mới hơn. - Ghi theo kiểu "ghi đè nếu mới hơn" (upsert theo
data.object.id), không theo kiểu "thêm mới rồi cập nhật". Khi nhậntransaction.confirmedmà chưa có bản ghi giao dịch, hãy tạo bản ghi từ chính sự kiện đó. - Khi nghi ngờ, đọc lại đối tượng bằng API (
GET /v1/transactions/{id}) để lấy trạng thái hiện tại.
Nhận tiền về đúng một lần
Phần tiêu đề “Nhận tiền về đúng một lần”Chỉ coi giao dịch là tiền về khi nhận transaction.confirmed. Sự kiện transaction.created có thể mang giao dịch còn tạm tính (provisional), chưa đủ bằng chứng. confirmed là xác thực nguồn, không phải ngân hàng xác nhận quyết toán, nên các quy trình cần độ chắc chắn cao hơn (giao hàng, hạch toán) vẫn nên có bước đối chiếu của bạn.
Kết hợp với khử trùng ở trên: ghi nhận khoản thu trong cùng giao dịch cơ sở dữ liệu với việc lưu webhook_id, và đặt ràng buộc duy nhất trên tx_… nếu cần một khoản thu cho mỗi giao dịch.
Trả lời nhanh, xử lý sau
Phần tiêu đề “Trả lời nhanh, xử lý sau”Trả 2xx trong 10 giây. Nếu việc xử lý chậm, lưu thông điệp đã xác minh vào hàng đợi của bạn rồi trả lời ngay, và xử lý ở tiến trình khác. Khử trùng vẫn làm ở bước nhận, trước khi đưa vào hàng đợi.