Webhook URL
Tổng quan
Tính năng này chuyển dữ liệu của hóa đơn đã thanh toán đến máy chủ của người bán. Nó tồn tại để cửa hàng của người bán có thể xử lý khoản thanh toán tự động và giao sản phẩm hoặc dịch vụ cho người mua của bạn.
Webhook URL được đặt riêng cho từng dự án và trỏ đến các script xử lý thanh toán bên trong cửa hàng của người bán. Địa chỉ phải dùng HTTPS và tên miền: địa chỉ IP không được chấp nhận, và chứng chỉ được xác minh ở mỗi lần gửi.
Mỗi khi trạng thái hóa đơn chuyển sang Đã thanh toán (Paid), dịch vụ gửi một yêu cầu POST đến URL này theo định dạng sau:
{
"wallet":{
"id":"47aa71e2-07a0-482e-9172-7114d7376ba0",
"name":"usdt-tron",
"blockchain":"tron",
"cryptocurrency":"usdt",
"address":"TKbstUwMzLrfTAGL4erYb7gc7ghmHQ9zG7"
},
"project":{
"id":"9deea1e2-0c08-41a3-bdc2-a34eada3892d",
"name":"My project",
"commissionPayer":"seller",
"commissionRate":1
},
"invoice":{
"id":"a4c9e2ee-9a03-43e5-a1a1-00caf679d16a",
"uid":"AFhygKX21ecd",
"createDatetime":"2024-02-26 13:29:24",
"timeToPayDatetime":"2024-02-27 01:29:24",
"commissionFiatUSD":0.05,
"amountFiatUSD":5.02,
"amountFiat":5,
"calcAmountFiat":5.02,
"currencyFiat":"USD",
"description":null,
"serviceData":null,
"status":"paid"
},
"payment":{
"id":"f986ad8d-2298-473d-982a-efbc817b975d",
"amount":5.02,
"hash":"74763b65e43bcc9492a6ce9a7f26fbfdbd7635aecd3454420b5e9534cba50ee6",
"transactionDatetime":"2024-02-26 13:32:57"
}
}
Thông báo phát đi ở mỗi lần chuyển sang Đã thanh toán — cả khi dịch vụ tự tìm thấy khoản thanh toán lẫn khi người bán khớp khoản thanh toán với hóa đơn thủ công.
Tham số yêu cầu
| Tham số | Mô tả |
|---|---|
wallet.id | ID ví ở định dạng UUID |
wallet.name | Tên ví |
wallet.blockchain | Blockchain của ví tiền mã hóa |
wallet.cryptocurrency | Tiền mã hóa của ví |
wallet.address | Địa chỉ của ví tiền mã hóa |
project.id | ID dự án ở định dạng UUID |
project.name | Tên dự án |
project.commissionPayer | Bên trả phí dịch vụ |
project.commissionRate | Mức phí tính bằng % |
invoice.id | ID hóa đơn ở định dạng UUID |
invoice.uid | ID hóa đơn (dành cho người mua) |
invoice.createDatetime | Ngày giờ tạo hóa đơn (UTC) |
invoice.timeToPayDatetime | Ngày giờ hóa đơn còn hiệu lực với người mua đến (UTC). Việc tìm kiếm thanh toán tiếp tục thêm 1 giờ sau mốc này — để tính đến các mạng chậm. Vì vậy thông báo có thể đến cho hóa đơn đã hiển thị là hết hạn |
invoice.commissionFiatUSD | Số tiền phí dịch vụ. Tính từ số tiền invoice.amountFiatUSD |
invoice.amountFiatUSD | Số tiền bằng USD. Khi tạo hóa đơn, nó được tính từ invoice.amountFiat theo tỷ giá hiện tại. Tại thời điểm thanh toán, nó bị ghi đè bằng số tiền thực nhận, quy đổi sang USD theo tỷ giá lúc đó. Phí trong invoice.commissionFiatUSD cũng được tính lại từ nó |
invoice.amountFiat | Số tiền gốc của hóa đơn bằng tiền pháp định. Không thay đổi |
invoice.calcAmountFiat | Số tiền tính bằng đồng tiền invoice.currencyFiat theo tỷ giá tiền mã hóa tại thời điểm thanh toán. Nó có thể khác invoice.amountFiat vì người mua có thể thanh toán hóa đơn sau khi tạo một khoảng thời gian chứ không phải ngay lập tức. Trong khoảng thời gian đó, tỷ giá tiền mã hóa so với invoice.currencyFiat có thể biến động theo cả hai chiều |
invoice.currencyFiat | Tiền pháp định |
invoice.description | Mô tả đặt khi tạo hóa đơn |
invoice.serviceData | Dữ liệu dịch vụ đặt khi tạo hóa đơn |
invoice.status | Trạng thái hóa đơn |
payment.id | ID khoản thanh toán ở định dạng UUID |
payment.amount | Số tiền thanh toán bằng tiền mã hóa |
payment.hash | Hash của giao dịch on-chain |
payment.transactionDatetime | Ngày giờ của giao dịch on-chain (UTC) |
Chữ ký thông báo
Mỗi yêu cầu được ký bằng khóa bí mật webhook. Chữ ký đi trong các header X-Timestamp và X-Signature, giúp bạn chắc chắn thông báo đến từ dịch vụ chứ không phải từ kẻ ngoài đã biết địa chỉ trình xử lý của bạn.
Hãy xác minh chữ ký trước khi xử lý đơn hàng. Cơ chế và các ví dụ sẵn dùng nằm trong Xác minh chữ ký webhook.
Khuyến nghị xử lý
Đừng từ chối thông báo vì thời hạn thanh toán đã qua. Phép kiểm tra kiểu “hóa đơn đã hết hạn, nên khoản thanh toán không hợp lệ” trông có vẻ hợp lý nhưng cắt mất một phần các khoản thanh toán thật: trên mạng chậm, giao dịch có thể được xác nhận sau thời hạn, và người bán có thể khớp thủ công khoản thanh toán với hóa đơn hết hạn. Bản thân thông báo đã xác nhận khoản thanh toán.
Xác minh số tiền theo trường gốc invoice.amountFiat. Đây là số tiền hóa đơn như khi phát hành, và nó không thay đổi. Trường amountFiatUSD phản ánh số tiền thực nhận và có thể khác số đã phát hành — vừa do biến động tỷ giá, vừa do khớp thanh toán thủ công.
Phân tích số tiền dưới dạng số. Các số 0 cuối bị lược bỏ: số tiền 10.00 đến dưới dạng 10; hãy định dạng nó ở phía bạn khi hiển thị. Số tiền dưới 0.0001 đến ở dạng lũy thừa, ví dụ 1.0e-6 — phân tích JSON chuẩn trả về đúng con số; chỉ tự phân tích chuỗi thủ công mới hỏng.
Xử lý thông báo theo cách idempotent. Cùng một thông báo có thể đến lần nữa — ví dụ, khi script của bạn xử lý khoản thanh toán thành công nhưng trả về mã ngoài 2xx. Trước khi giao hàng, hãy kiểm tra invoice.id này đã được xử lý chưa.
Thoát ký tự các giá trị khi xuất ra. Các trường invoice.description và invoice.serviceData quay lại đúng như người bán đã gửi. Nếu bạn kết xuất chúng trong HTML, hãy thoát ký tự ở phía bạn.
Lịch gửi
Máy chủ tại Webhook URL phải phản hồi bằng mã HTTP 2xx. Mã khác, hết thời gian chờ hoặc kết nối bị đứt đều tính là gửi thất bại.
Dịch vụ không đi theo chuyển hướng: phản hồi 301 hoặc 302 là gửi thất bại, không phải bước nhảy đến địa chỉ mới. Hãy đặt địa chỉ cuối cùng của trình xử lý.
Kết nối được phép 5 giây, toàn bộ yêu cầu 10 giây. Nếu trình xử lý không kịp trong khoảng đó, lần gửi tính là thất bại.
Sau lần gửi thất bại, dịch vụ thử lại theo lịch sau:
- 5 phút sau lần gửi thất bại gần nhất
- Sau 15 phút
- Sau 30 phút
- Sau 1 giờ
- Sau 3 giờ
- Sau 6 giờ
- Sau 12 giờ
- Sau 24 giờ
Sau đó, các lần gửi dừng lại.
Tắt Webhook URL
Đôi khi script webhook của cửa hàng xử lý khoản thanh toán đúng nhưng trả về mã HTTP ngoài 2xx. Điều này dẫn đến việc máy chủ của chúng tôi thử lại thường xuyên theo lịch ở trên, gây tải thêm cho cả máy chủ của chúng tôi lẫn của bạn.
Để ngăn những trường hợp như vậy, chúng tôi có cơ chế tắt Webhook URL trong dự án. Để tránh nó, hãy làm các bước sau:
- Sửa mã trình xử lý webhook của bạn để nó trả về mã 2xx, thường là 200, khi xử lý thanh toán thành công. Kiểm tra bằng bất kỳ trình giả lập nào, ví dụ Postman.
- Liên hệ hỗ trợ kỹ thuật để chỉnh lại cài đặt.
- Bật lại Webhook URL trong cài đặt dự án và lưu dự án.