Webhook
Thay vì bên cần dữ liệu hỏi liên tục, bên có dữ liệu tự gửi một gói tin sang ngay khi sự kiện xảy ra. Kiểu như thay vì gọi điện hỏi hàng về chưa, bạn để lại số và họ nhắn khi hàng về.
Định nghĩa
Bạn đặt một đơn hàng và trả tiền qua ví điện tử. Vài giây sau, hệ thống của cửa hàng biết tiền đã về và tự chuyển đơn sang trạng thái đã thanh toán. Không ai ngồi bấm nút. Phía ví đã bắn một gói tin sang một địa chỉ mà cửa hàng khai báo trước. Đó là webhook.
Webhook đảo ngược chiều gọi: bên có dữ liệu là bên chủ động, còn bên cần dữ liệu chỉ việc dựng sẵn một địa chỉ để hứng.
Cơ chế
- Bên nhận đăng ký một URL công khai, gọi là callback URL, kèm danh sách sự kiện muốn nghe.
- Sự kiện xảy ra bên gửi: giao dịch thành công, đơn đổi trạng thái, hợp đồng được ký.
- Bên gửi thực hiện một cuộc gọi
POSTtới URL đó, mang theo dữ liệu sự kiện. - Bên nhận trả về
200để xác nhận đã nhận. Nếu trả mã lỗi hoặc quá thời gian chờ, bên gửi sẽ thử lại theo lịch riêng của họ.
Chi tiết ở bước 4 quyết định độ ổn định của cả tích hợp, và đó chính là phần BA phải viết ra chứ không phải để dev tự đoán.
So sánh webhook và polling
| Webhook | Polling | |
|---|---|---|
| Cách hoạt động | Bên gửi bắn khi có sự kiện | Bên nhận hỏi lặp lại theo chu kỳ |
| Độ trễ | Gần như tức thì | Bằng chu kỳ hỏi, thường 1–15 phút |
| Tải hệ thống | Thấp, chỉ khi có việc | Cao, phần lớn lần hỏi trả về rỗng |
| Yêu cầu hạ tầng | Bên nhận phải có URL truy cập được từ internet | Không cần, bên nhận chỉ gọi ra |
| Khi bên nhận sập | Có thể mất sự kiện nếu retry cạn lượt | Hồi phục xong hỏi lại là có đủ |
Vì lý do ở dòng cuối, nhiều hệ thống nghiêm túc dùng cả hai: webhook cho tốc độ, thêm một job đối soát chạy mỗi giờ để quét những sự kiện lọt lưới.
Những thứ phải chốt trước khi dev code
- Danh sách sự kiện và cấu trúc gói tin cho từng loại. Đừng nhận một mẫu duy nhất rồi tưởng sự kiện nào cũng giống nhau.
- Xác thực: bên gửi ký gói tin bằng chữ ký HMAC trong header, bên nhận kiểm chữ ký trước khi tin. Thiếu bước này thì bất kỳ ai biết URL cũng bắn được một giao dịch giả vào hệ thống của bạn, và nó sẽ được ghi nhận y như thật.
- Chống trùng. Bên gửi có thể bắn lại cùng một sự kiện. Bên nhận cần một khoá duy nhất để xử lý đúng một lần, và trong tài liệu bạn ghi rõ trường nào đóng vai trò khoá đó.
- Chính sách thử lại: mấy lần, giãn cách bao lâu, quá số lần thì đi đâu.
- Thời gian chờ. Bên gửi thường chỉ chờ vài giây, nên bên nhận lưu gói tin rồi trả
200ngay, xử lý nghiệp vụ nặng sau đó. - Thứ tự. Trạng thái đơn đi lùi là chuyện có thật.
Ví dụ thực tế
1h15 sáng, máy chủ của một nền tảng học trực tuyến được tắt để nâng cấp. 1h35 nó chạy lại. Trong hai mươi phút đó có 14 giao dịch thành công — nền tảng này bán khoảng 680 lượt mỗi ngày qua một cổng thanh toán trong nước, và việc mở quyền học phụ thuộc hoàn toàn vào webhook. Gói tin bắn vào khoảng không, cổng thanh toán thử lại ba lần trong 10 phút rồi bỏ. Sáng hôm sau bộ phận chăm sóc nhận 14 cuộc gọi của học viên đã trả tiền mà không vào học được.
Sau sự cố, đội bổ sung một job chạy mỗi 15 phút gọi REST API lấy danh sách giao dịch thành công trong 2 giờ gần nhất và đối chiếu. Kể từ đó vẫn có webhook trượt, nhưng không còn ai phải gọi điện xin lỗi học viên.
Một chuyện nhỏ về tài liệu
Gói tin thật mà đối tác bắn sang rất hay khác gói tin in trong tài liệu của chính họ. Thiếu trường, thừa trường, tên trường viết kiểu khác, có lần số tiền về dưới dạng chuỗi ký tự thay vì số. Lần gần nhất mình ngồi đối chiếu, tài liệu ghi mười một trường, gói tin thật có mười bốn, và ba trường thừa kia lại đúng là ba trường đội kế toán đang cần.
