
Có một khoảnh khắc rất dễ làm chủ shop mất ngủ: khách vừa thanh toán, nhưng hệ thống quản lý đơn chưa biết gì. Nhân viên phải mở từng trang kiểm tra, rồi nhắn nhau trong nhóm chat. Webhook sinh ra để bỏ qua kiểu làm việc đó: khi một sự kiện xảy ra, hệ thống phát tín hiệu cho hệ thống khác gần như ngay lập tức.
Tóm tắt nhanh: webhook là một HTTP request do hệ thống nguồn chủ động gửi tới URL của hệ thống nhận khi có sự kiện. Nó khác API ở chỗ bạn không phải liên tục hỏi “đã có gì mới chưa?”. Tuy vậy, webhook không phải chiếc hộp thần kỳ. Nếu không xác thực chữ ký, xử lý gửi trùng và có hàng đợi, một thông báo lỗi có thể biến thành đơn hàng trùng hoặc dữ liệu sai.
Webhook là gì?
Webhook là cơ chế giao tiếp theo sự kiện. Hệ thống A đăng ký một URL nhận thông báo với hệ thống B. Khi có sự kiện như thanh toán thành công, tạo đơn hoặc thay đổi trạng thái giao hàng, B gửi một HTTP request tới URL đó, thường kèm dữ liệu JSON.
Ví dụ dễ hình dung: cửa hàng dùng cổng thanh toán, phần mềm bán hàng và hệ thống gửi email. Khi thanh toán thành công, cổng thanh toán gửi webhook. Phần mềm bán hàng nhận tín hiệu, đánh dấu đơn đã trả tiền và đẩy yêu cầu sang hệ thống email. Không ai cần ngồi bấm nút làm mới màn hình.
Webhook khác API ở điểm nào?
Với API kiểu polling, hệ thống của bạn phải hỏi lặp lại: “Có đơn mới chưa?”. Hỏi quá thưa thì chậm, hỏi quá dày thì tốn tài nguyên và vẫn có lúc bỏ lỡ nhịp. Webhook chuyển phần chủ động sang hệ thống phát sự kiện.
API phù hợp khi bạn cần truy vấn dữ liệu theo yêu cầu. Webhook phù hợp khi bạn cần biết ngay một sự kiện vừa xảy ra. Trong thực tế, hai cơ chế thường đi cùng nhau: webhook báo có sự kiện, API được dùng để lấy thêm dữ liệu chi tiết.
Một webhook chạy qua những bước nào?
- Đăng ký endpoint: bạn cung cấp URL HTTPS và chọn các loại sự kiện muốn nhận.
- Sự kiện xảy ra: chẳng hạn một khoản thanh toán chuyển sang trạng thái thành công.
- Hệ thống nguồn tạo payload: dữ liệu thường có tên sự kiện, mã sự kiện, thời gian và phần dữ liệu chính.
- Request được gửi: hệ thống nguồn gửi HTTP POST tới endpoint của bạn.
- Endpoint xác minh và ghi nhận: kiểm tra chữ ký, mã sự kiện và điều kiện hợp lệ.
- Trả phản hồi nhanh: trả mã 2xx sau khi đã ghi nhận an toàn, thay vì bắt bên gửi chờ toàn bộ quy trình nghiệp vụ.
- Xử lý phía sau: hàng đợi hoặc worker thực hiện việc nặng như cập nhật CRM, xuất hóa đơn hoặc gửi email.

Stripe khuyến nghị endpoint kiểm tra chữ ký từ header và giữ nguyên raw body của request, vì việc framework tự định dạng lại JSON có thể làm xác minh thất bại. Tài liệu Stripe cũng nhấn mạnh nên trả 2xx nhanh trước khi chạy logic phức tạp. Xem tài liệu webhook của Stripe.
7 lớp bảo mật và độ tin cậy nên có
1. Chỉ nhận HTTPS
Webhook thường mang mã đơn, trạng thái thanh toán hoặc dữ liệu khách hàng. Dùng HTTPS là điều kiện tối thiểu để dữ liệu không đi qua mạng dưới dạng dễ đọc. Đừng dùng URL tạm thời không có TLS chỉ vì nó tiện cho giai đoạn thử nghiệm.
2. Xác minh chữ ký
Đừng tin một request chỉ vì nó gọi đúng URL. Bên gửi nên ký payload bằng secret; bên nhận tính lại chữ ký và so sánh bằng phép so sánh an toàn. Stripe dùng header Stripe-Signature và yêu cầu raw body để xác minh. Nếu chữ ký sai, dừng xử lý và ghi log đủ để điều tra.
3. Chặn replay attack
Replay attack là khi kẻ xấu lấy một request hợp lệ rồi gửi lại. Payload nên có timestamp, còn endpoint đặt khoảng thời gian chấp nhận. Mã sự kiện cũng cần được lưu để biết request này đã xử lý hay chưa.
4. Thiết kế idempotency
Idempotency nghĩa là cùng một sự kiện được xử lý một lần hay năm lần thì kết quả cuối vẫn như nhau. Hãy lưu event_id hoặc combination gồm nguồn, loại sự kiện và mã đối tượng trước khi tạo tác động không thể đảo ngược như trừ tiền, cộng điểm hoặc xuất kho.
5. Trả lời nhanh, xử lý chậm
Endpoint nên làm ít việc: xác minh, ghi nhận, đẩy vào hàng đợi rồi trả 2xx. Nếu bạn đợi cả quy trình đồng bộ hoàn tất, timeout sẽ khiến bên gửi tưởng thất bại và gửi lại. Đó là cách một đơn hàng biến thành hai dòng trong kho.
6. Có retry nhưng đừng giả định retry giống nhau
Mỗi nhà cung cấp có chính sách khác nhau. Stripe có thể gửi lại khi endpoint trả mã ngoài nhóm 2xx và tạo timestamp, chữ ký mới cho lần giao lại. GitHub thì ghi rõ họ không tự động redeliver delivery thất bại; đội ngũ phải redeliver thủ công hoặc viết script theo dõi. Đọc tài liệu của từng nhà cung cấp, đừng bê nguyên một giả định sang mọi nền tảng.
7. Log và cảnh báo
Log tối thiểu nên có thời điểm nhận, event_id, loại sự kiện, mã phản hồi, thời gian xử lý và lý do từ chối. Không log secret, token hay toàn bộ dữ liệu cá nhân. Đặt cảnh báo khi tỷ lệ 4xx, 5xx hoặc thời gian xử lý tăng bất thường.
Khi nào SME nên dùng webhook?
Webhook đáng dùng khi sự kiện cần phản hồi nhanh và hệ thống liên quan đã hỗ trợ sẵn, như thanh toán, đơn hàng, CRM, form đăng ký hoặc quy trình phê duyệt. Nếu khối lượng nhỏ, bạn có thể bắt đầu bằng một endpoint, một bảng event_log và một hàng đợi đơn giản.
Không nên mở webhook cho mọi sự kiện ngay từ đầu. Hãy chọn một luồng có giá trị rõ, ví dụ thanh toán thành công cập nhật đơn hàng, rồi đo tỷ lệ nhận thành công, thời gian xử lý và số lần gửi lại.
Checklist trước khi đưa vào chạy thật
- Endpoint là HTTPS và có giới hạn request hợp lý.
- Chữ ký được xác minh trên raw body.
- Event ID được lưu để chống xử lý trùng.
- Logic nặng chạy sau hàng đợi.
- Có retry, dead-letter hoặc quy trình xử lý thất bại.
- Log không chứa secret và dữ liệu cá nhân không cần thiết.
- Có cách redeliver an toàn sau sự cố.
Kết luận
Webhook giúp các hệ thống nói chuyện với nhau theo sự kiện thay vì liên tục hỏi thăm. Giá trị lớn nhất không nằm ở việc nhận được một HTTP request, mà ở cách bạn xác minh, ghi nhận, chống trùng và phục hồi khi bên gửi hoặc bên nhận gặp sự cố.
Việc nên làm ngay là chọn một luồng nhỏ như thanh toán cập nhật đơn hàng, viết bảng event_log và thử cả ba tình huống: request hợp lệ, chữ ký sai và cùng một event gửi lại.
Nguồn tham khảo
Stripe – Webhooks
GitHub – Handling failed webhook deliveries
Techzika – Bảo vệ API key khi dùng công cụ AI