رفتن به محتوا

بررسی امضای وب‌هوک

آنچه یاد می‌گیرید: امضای پیام‌های وب‌هوک چیست، چطور آن را بررسی کنید، و چطور کد خود را بدون سرور آزمایش کنید.

شما و سلر ۳۶۰ یک کلید امضای مشترک دارید که در هیچ پیامی فرستاده نمی‌شود. سلر ۳۶۰ هر پیام را با این کلید امضا می‌کند؛ شما همان محاسبه را تکرار می‌کنید. اگر امضاها یکی بود، پیام واقعا از سلر ۳۶۰ آمده و در راه دست نخورده است؛ مثل مهر برجسته روی نامه‌ی اداری.

S360-Signature: t=1762930000,v1=25ece598dedd14967fd7b77a3a873814605f38d98eac7bad39feecc1f8559349
  • t: زمان ارسال (ثانیه از ۱۹۷۰).
  • v1: امضای HMAC-SHA256 روی رشته‌ی t + "." + بدنه‌ی خام، با کلید امضای نشانی شما.
  1. بدنه‌ی خام را پیش از هر تبدیلی بخوانید؛ JSON تبدیل‌شده و دوباره ساخته‌شده امضای دیگری دارد.
  2. رشته‌ی t + "." + بدنه‌ی خام را با کلید امضا و HMAC-SHA256 امضا کنید.
  3. حاصل را با v1 با مقایسه‌ی ثابت‌زمان مقایسه کنید.
  4. اگر t بیش از ۵ دقیقه با زمان سرور شما فاصله دارد، پیام را رد کنید (جلوگیری از پخش دوباره‌ی پیام قدیمی).
function s360_verify(string $raw, string $header, string $secret, ?int $now = null): bool {
// The header holds one t and one or more v1 (two while the key rotates).
$t = null; $signatures = [];
foreach (explode(",", $header) as $part) {
[$name, $value] = array_pad(explode("=", trim($part), 2), 2, "");
if ($name === "t") { $t = $value; }
if ($name === "v1") { $signatures[] = $value; }
}
if ($t === null || !ctype_digit($t) || abs(($now ?? time()) - (int) $t) > 300) {
return false;
}
$expected = hash_hmac("sha256", $t . "." . $raw, $secret);
foreach ($signatures as $candidate) {
if (hash_equals($expected, $candidate)) { return true; }
}
return false;
}
$raw = file_get_contents("php://input");
if (!s360_verify($raw, $_SERVER["HTTP_S360_SIGNATURE"] ?? "", getenv("S360_WEBHOOK_SECRET"))) {
http_response_code(400);
exit;
}

کد خود را بدون سرور با این داده‌ها آزمایش کنید. اگر به همان امضا رسیدید، پیاده‌سازی شما درست است.

ورودی مقدار
کلید امضا whsec_test_seller360
t 1762930000
بدنه‌ی خام {"id":"evt_test","type":"ping"}
امضای مورد انتظار (v1) 25ece598dedd14967fd7b77a3a873814605f38d98eac7bad39feecc1f8559349
  • امضا روی بدنه‌ی تبدیل‌شده حساب شده، نه بدنه‌ی خام.
  • مقایسه با == به جای مقایسه‌ی ثابت‌زمان.
  • استفاده از کلید API به جای کلید امضای نشانی وب‌هوک.