Kiểm tra chữ ký webhook API
Kiểm tra chữ ký webhook của Stripe, GitHub, Slack, Shopify, PayOS, SePay hoặc HMAC bất kỳ: xem chữ ký mong đợi, chuỗi được ký và khoảng thời gian chống phát lại.
Sai chữ ký là lỗi webhook hay gặp nhất: body đã bị parse rồi serialize lại, dùng nhầm secret, hoặc timestamp vượt khoảng cho phép. API kiểm tra webhook đối chiếu payload với cách ký của từng nhà cung cấp và hiển thị giá trị mong đợi cạnh giá trị nhận được. Hỗ trợ: Stripe (Stripe-Signature t= / v1=, cho phép lệch 5 phút), GitHub (X-Hub-Signature-256), Slack (v0 với X-Slack-Request-Timestamp), Shopify (base64 X-Shopify-Hmac-Sha256), PayOS (HMAC trên các trường data đã sắp xếp, kèm chuỗi được ký) và SePay (Authorization: Apikey).
provider=generic dùng cho mọi trường hợp khác: HMAC-SHA1/256/512, hex hoặc base64, tiền tố tuỳ chọn và header cần đọc. Gửi body thô qua payload (chuỗi, đúng như nhận được) và object headers hoặc signature.
Dùng để debug tích hợp và kiểm thử; khi chạy thật hãy kiểm tra chữ ký trong code của bạn. Secret chỉ dùng trong bộ nhớ, không lưu, không ghi log.
Tham số
| Tên | Vị trí | Kiểu | Bắt buộc | Mặc định | |
|---|---|---|---|---|---|
provider | body | string | không | generic | stripe, github, slack, shopify, payos, sepay hoặc generic. |
secret | body | string | có | Secret ký / API key. | |
payload | body | string | có | Body thô của request, dạng chuỗi. | |
headers | body | object | không | Các header của request (đọc header chữ ký từ đây). | |
signature | body | string | không | Giá trị chữ ký, thay cho headers. | |
tolerance | body | number | không | 300 | Tuổi tối đa (giây) với Stripe, Slack; 0 = không kiểm tra. |
algorithm | body | string | không | sha256 | Generic: sha1, sha256, sha512. |
encoding | body | string | không | hex | Generic: hex hoặc base64. |
Ví dụ
curl -X POST "https://apibox.io.vn/v1/webhook-verify" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"provider":"github","secret":"gh","payload":"{\"id\":\"evt_1\"}","signature":"sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e"}'const res = await fetch('https://apibox.io.vn/v1/webhook-verify', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"provider": "github",
"secret": "gh",
"payload": "{\"id\":\"evt_1\"}",
"signature": "sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e"
}),
});
const data = await res.json();
console.log(data);import requests
res = requests.post(
"https://apibox.io.vn/v1/webhook-verify",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"provider": "github", "secret": "gh", "payload": "{\"id\":\"evt_1\"}", "signature": "sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e"},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/webhook-verify');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"provider":"github","secret":"gh","payload":"{\\"id\\":\\"evt_1\\"}","signature":"sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e"}',
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Kết quả trả về
{
"valid": true,
"provider": "github",
"expected": "sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e",
"received": "sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e",
"note": "The secret is used in memory only and never stored. …"
}
Ứng dụng
- Debug lỗi “invalid signature” với Stripe, PayOS, GitHub
- Kiểm thử endpoint webhook trong CI
- Tìm hiểu cách từng nhà cung cấp ký webhook
- Kiểm tra payload đã bắt được bằng webhook tester
Hỏi đáp
Vì sao chữ ký không khớp?
Thường do body đã bị parse và serialize lại (khác khoảng trắng hoặc thứ tự khoá). Chữ ký được tính trên đúng các byte gốc; hãy gửi payload là chuỗi nguyên bản.
Khoảng cho phép là bao nhiêu?
Với Stripe và Slack, chữ ký cũ hơn 300 giây bị từ chối để chống phát lại. Đổi bằng tolerance=, hoặc dùng now= để thử sự kiện cũ.
Gửi secret có an toàn không?
Secret chỉ dùng để tính HMAC và không bao giờ được lưu. Nên dùng secret của môi trường test, và đổi ngay secret nào bị lộ.
API liên quan
Tạo mã hash
Tính MD5, SHA-1, SHA-256, SHA-384, SHA-512 và CRC32 của chuỗi hoặc file trong một lần gọi, xuất hex hoặc base64, hỗ trợ ký HMAC.
B64Mã hoá / Giải mã
Mã hoá hoặc giải mã chuỗi sang Base64, Base64URL, hex, URL encode, HTML entity, Unicode escape, ROT13 hay nhị phân chỉ với một lần gọi API.
***Tạo mật khẩu
Tạo mật khẩu ngẫu nhiên an toàn bằng CSPRNG (4–256 ký tự, tối đa 100 cái mỗi lần) hoặc kiểm tra độ mạnh, entropy và thời gian bẻ khoá của mật khẩu.