webhook-id: 7c1e2f0a-3b5d-4e8f-9a61-2d4c8b0e5f13
webhook-timestamp: 1790490600
webhook-signature: v1,s0RzLJ1d7Cxd9nwe8pqER9DWy/stEIB+uT9MlGVLlM0=
| Päis |
Mis see on |
| webhook-id |
Saadetis, sama väärtus nagu sisu väljal delivery_id. Jätke meelde saadetised, mille olete juba töödelnud, ja vastake kordusele koodiga 200, ilma et teeksite töö uuesti. |
| webhook-timestamp |
Aeg, millal me selle allkirjastasime, täissekundites alates 1970. aastast. Lükake tagasi kõik, mis erineb teie enda kellast rohkem kui viis minutit, et vana saadetist ei saaks teile uuesti saata. |
| webhook-signature |
v1, seejärel ID, ajatempli ja töötlemata sisu base64 HMAC-SHA256, mis on ühendatud punktidega ja tehtud teie allkirjastamisvõtmega. Neid võib olla rohkem kui üks, eraldatuna tühikutega. Võtke saadetis vastu, kui ükskõik milline neist klapib. |
Allkirjastamisvõti
See algab kujul whsec_. Eemaldage see ja dekodeerige ülejäänu base64-ga: need baidid on HMAC-võti, mitte tekst, mille kopeerisite. Seda näidatakse ühe korra, kui ühendate webhooki või vajutate avaldamise lehel "New signing key", ja me ei saada seda kunagi.
Kontrollige töötlemata sisu
Arvutage allkiri baitidest täpselt sellisena, nagu need saabusid, enne kui miski neid töötleb. JSON, mis on dekodeeritud ja uuesti kodeeritud, ei ole enam samad baidid ja selle allkiri ei klapi.
PHP
<?php
$raw = getenv('SEONIS_SIGNING_KEY'); // whsec_...
// No key, no deliveries. A missing or empty variable would otherwise become
// an empty HMAC key, and anybody can sign with that.
$secret = is_string($raw) && str_starts_with($raw, 'whsec_')
? base64_decode(substr($raw, strlen('whsec_')), true)
: false;
if ($secret === false || strlen($secret) < 24) {
http_response_code(500);
exit('Signing key not configured.');
}
$id = $_SERVER['HTTP_WEBHOOK_ID'] ?? '';
$timestamp = $_SERVER['HTTP_WEBHOOK_TIMESTAMP'] ?? '';
$header = $_SERVER['HTTP_WEBHOOK_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
if (! ctype_digit($timestamp) || abs(time() - (int) $timestamp) > 300) {
http_response_code(401);
exit('Too old.');
}
$expected = base64_encode(hash_hmac('sha256', "$id.$timestamp.$body", $secret, true));
$valid = false;
foreach (explode(' ', $header) as $signature) {
[$version, $value] = array_pad(explode(',', $signature, 2), 2, '');
$valid = $valid || ($version === 'v1' && hash_equals($expected, $value));
}
if (! $valid) {
http_response_code(401);
exit('Bad signature.');
}
$delivery = json_decode($body, true);
Node.js
import crypto from 'node:crypto';
import express from 'express';
const app = express();
// No key, no server. An empty variable would otherwise become an empty HMAC
// key, and anybody can sign with that.
const raw = process.env.SEONIS_SIGNING_KEY ?? '';
if (!raw.startsWith('whsec_')) throw new Error('SEONIS_SIGNING_KEY is not set.');
const key = Buffer.from(raw.slice('whsec_'.length), 'base64');
if (key.length < 24) throw new Error('SEONIS_SIGNING_KEY is not a valid key.');
// express.raw keeps the body as the bytes we signed.
app.post('/hooks/seonis', express.raw({ type: 'application/json' }), (req, res) => {
const id = req.get('webhook-id') ?? '';
const timestamp = req.get('webhook-timestamp') ?? '';
const header = req.get('webhook-signature') ?? '';
if (!/^\d+$/.test(timestamp) || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.status(401).send('Too old.');
}
const expected = crypto.createHmac('sha256', key)
.update(`${id}.${timestamp}.`)
.update(req.body)
.digest();
const valid = header.split(' ').some((signature) => {
const [version, value = ''] = signature.split(',');
const given = Buffer.from(value, 'base64');
return version === 'v1' && given.length === expected.length && crypto.timingSafeEqual(given, expected);
});
if (!valid) return res.status(401).send('Bad signature.');
const delivery = JSON.parse(req.body);
res.json({ ok: true });
});
Või kasutage teeki
Ametlikud Standard Webhooks teegid PHP, JavaScripti, Pythoni, Go, Ruby ja muu jaoks teevad selle kõik ühe väljakutsega. Andke neile allkirjastamisvõti täpselt nii, nagu seda teile näidati, koos eesliitega whsec_.
github.com/standard-webhooks
Vanemad päised
Saadetised sisaldavad ka allkirjastamise saladust bearer-tokenina ja päist X-AutoSEO-LT-Signature, mis on ainult sisu HMAC, mis on tehtud selle saladusega. Neid saadetakse endiselt, et nendele ehitatud lõpp-punktid töötaksid edasi. Uus lõpp-punkt peaks selle asemel kontrollima päist webhook-signature: vana allkiri ei hõlma aega ega ID-d ja selle võti liigub igas päringus kaasa.
AutoSEO, Outrank ja BabyLoveGrowth vormingud saadavad täpselt seda, mida need teenused saatsid, seega need ei sisalda neid päiseid.