Tài liệu API: webhook
Webhook đẩy sự kiện về máy chủ của bạn ngay lúc chúng xảy ra. Hãy đặt Webhook URL cho ứng dụng của bạn ở Thêm → Merchant API; từ đó nền tảng POST một JSON body có chữ ký cho mỗi sự kiện bạn đã đăng ký.
Envelope
{
"update_id": 123,
"update_type": "invoice_paid",
"request_date": "2026-08-11T12:00:00Z",
"payload": { … }
}
update_id giữ nguyên qua các lần gửi lại của cùng một sự kiện — hãy chống
trùng theo trường này. request_date được ghi theo từng lần gửi.
payload là đối tượng đầy đủ ứng với loại sự kiện: đối tượng invoice cho các sự
kiện hóa đơn, đối tượng check, hoặc đối tượng subscription (cấu trúc nằm trên
các trang tài liệu tương ứng).
Các loại sự kiện
update_type | Bắn khi | Payload |
|---|---|---|
invoice_paid | một hóa đơn được thanh toán — luôn được gửi | đối tượng invoice |
invoice_expired | một hóa đơn quá hạn mà chưa ai trả | đối tượng invoice |
check_activated | một Lì xì của bạn được nhận | đối tượng check |
refund_completed | một lần hoàn tiền được thực hiện | đối tượng invoice kèm các trường refunded_* |
subscription_activated | một người dùng đăng ký gói | đối tượng subscription |
subscription_charged | một kỳ được thu tiền — charge.kind cho biết là kỳ nào: initial, renewal hoặc resubscribe | đối tượng subscription + charge: {period_no, kind, asset, amount, fee, paid_at} |
subscription_cancelled | một gói đăng ký bị hủy, dù do bên nào | đối tượng subscription |
subscription_expired | hết thời gian gia hạn mà vẫn chưa trả | đối tượng subscription |
Mọi loại trừ invoice_paid đều cần bật thủ công (một phần mở rộng so với
Crypto Bot — một bên tiêu thụ đúng khuôn Crypto Bot sẽ không bao giờ gặp một
update_type lạ trừ khi chính bạn xin nó). Bật cho từng ứng dụng ở mục Sự
kiện webhook bổ sung trên màn hình Merchant API — các nút gạt xuất hiện khi đã
đặt webhook URL, và chúng được đặt tên bằng đúng các định danh thô ở bảng trên.
Kiểm tra chữ ký
Mỗi lần gửi đều mang header TgPayCrypto-API-Signature
(Crypto-Pay-API-Signature là tên gọi thay thế để tương thích, cùng một giá
trị): chuỗi hex HMAC-SHA256 của nội dung thô trong yêu cầu, dùng khóa là bản băm
SHA-256 của token API chính của ứng dụng. Đây đúng là cơ chế của Crypto Bot,
nên code kiểm tra sẵn có chạy nguyên vẹn:
import hashlib, hmac
secret = hashlib.sha256(API_TOKEN.encode()).digest()
expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, headers["TgPayCrypto-API-Signature"])
Hãy kiểm tra trên đúng các byte thô nhận được — một bản đã phân tích rồi tuần tự hóa lại có thể khác từng byte và làm hỏng phép kiểm tra. Chỉ token chính mới ký; token giới hạn quyền không bao giờ ký. Đổi token chính là đổi luôn khóa ký webhook ngay lập tức, nên hãy cập nhật secret trên máy chủ của bạn trong cùng một lượt.
Gửi và thử lại
- Một lần gửi được tính là thành công khi nhận được phản hồi 2xx bất kỳ trong vòng 10 giây.
- Mọi thứ khác — mã lỗi, hết thời gian chờ, lỗi kết nối — đều được thử lại theo cấp số nhân: lần đầu sau khoảng 10 giây, khoảng cách nhân đôi dần tới 8 giờ, tối đa 17 lần, trải trên khoảng 3 ngày.
- Sau lần cuối cùng, lần gửi đó bị bỏ. Bản thân webhook URL không bao giờ bị tự động tắt — một endpoint chập chờn không âm thầm hủy đăng ký ứng dụng của bạn.
- Vì có thử lại, handler của bạn phải idempotent: hãy chống trùng theo
update_idtrước khi làm gì.
⚠️ Kiểm tra trước khi giao hàng
Ai cũng POST được tới webhook URL của bạn. Cho tới khi chữ ký được xác minh
thành công, hãy coi body là dữ liệu không đáng tin: đừng giao đơn hàng, đừng
cộng tiền cho ai, đừng đánh dấu bất cứ gì là đã trả. Thứ tự an toàn là: kiểm tra
chữ ký → chống trùng theo update_id → rồi mới hành động.
Bài viết này có giúp được bạn không?
Cảm ơn phản hồi của bạn.