Mine sisu juurde
Sursa Developers

Veebihaagide vastuvõtmine

Veebihaak teavitab teie süsteemi Sursas toimunud muudatusest kohe, kui see juhtub: kaart avaldati, kontrolliti või arhiveeriti, küsimus jäi vastuseta. Sursa saadab sündmusega HTTPS-päringu POST aadressile, mille registreerite. See juhend loob vastuvõtja, mis töötab õigesti ka korduskatsete, muutunud järjekorra ja duplikaatide korral.

Mida iga sündmus tähendab ja sisaldab, vaadake juhendist Veebihaagide ülevaade ja API teatmiku sündmuste kataloogist.

1. Registreerige veebihaak

Administraator registreerib veebihaagid Sursas jaotises Administration → Integrations → Webhooks and API (haldus → integratsioonid → veebihaagid ja API) või päringuga POST /v1/webhooks võtmega, millel on roll admin ja ulatus webhooks:manage:

curl -X POST https://api.sursa.com/v1/webhooks \
  -H "Authorization: Bearer $SURSA_ADMIN_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/sursa",
    "description": "Sync verified cards to the help center",
    "events": ["card.published", "card.updated", "card.verified", "card.archived"]
  }'

Vastus sisaldab väljal secret allkirjastamise saladust, mis algab eesliitega whsec_. Seda näidatakse üks kord. Hoidke seda koos oma vastuvõtjaga, näiteks keskkonnamuutujas SURSA_WEBHOOK_SECRET.

Aadress peab kasutama protokolli https ja lahenduma avalikeks IP-aadressideks: privaat-, tagasisilmuse ja muude reserveeritud võrkude aadressid lükatakse tagasi nii registreerimisel kui ka iga edastuse korral. Oma arvutis arendamiseks tehke oma kohalik vastuvõtja kättesaadavaks tunneldusteenuse kaudu, mis annab sellele avaliku HTTPS-aadressi.

Saatke testsündmus igal ajal päringuga POST /v1/webhooks/{webhook_id}/test. Vastus näitab, mida teie vastuvõtja vastas.

2. Milline näeb välja edastus

POST /sursa HTTP/1.1
Host: hooks.example.com
Content-Type: application/json
webhook-id: evt_0123456789abcdef0123456789abcdef
webhook-timestamp: 1791194400
webhook-signature: v1,l1LLl/aEl4dQq7Geb383KbyNeZgs7VZpiw6iuoJgunI=
X-KB-Signature: t=1791194400,v1=82aa6b27378d89d7d880d17c3fe96268598443ae0e64d059c0c41e94e5d3ffbe
X-KB-Event-Id: evt_0123456789abcdef0123456789abcdef
X-KB-Event: card.verified
X-KB-Delivery: 99812
X-KB-Attempt: 1
X-KB-Sequence: 1042

{"id":"evt_0123456789abcdef0123456789abcdef","type":"card.verified","created_at":"2026-10-05T10:00:00Z","org_id":1,"api_version":"1.60.0","sequence":1042,"object":{"type":"card","id":"c1"},"payload":"full","data":{"card":{"id":"c1"}},"test":false}
PäisTähendus
webhook-idSündmuse ID. Iga korduskatse puhul sama. Kasutage seda duplikaatide kõrvaldamiseks.
webhook-timestampMillal see katse allkirjastati, Unixi sekundites.
webhook-signatureAllkiri vormingus Standard Webhooks.
X-KB-SignatureSama edastus, allkirjastatud Sursa varasemas vormingus.
X-KB-EventSündmusetüüp.
X-KB-AttemptKatse number, alates 1-st.
X-KB-SequenceSelle edastuse koht veebihaagi edastuste järjekorras.

Päiste nimed on tõstutundetud; teie raamistik võib näidata neid kujul X-Kb-Signature või x-kb-signature.

Keha on sündmus. Selle data sõltub tüübist. Veebihaak, mille sisu režiim on thin, saab sündmuse ilma väljata data; lugege objekt selle asemel oma võtmega API kaudu.

3. Kontrollige allkirja

Kontrollige iga edastuse allkirja enne, kui edastust usaldate. Mõlemad vormingud allkirjastavad keha täpsed baidid, seega lugege toores keha enne mis tahes JSON-i parsimist: JSON-i uuesti serialiseerimine muudab baite ja rikub kontrolli.

VormingAllkirjastatud stringVõtiAllkiri
Standard Webhooks (webhook-signature)<webhook-id>.<webhook-timestamp>.<body>Saladuse osa pärast eesliidet whsec_, base64-dekodeeritudv1, + HMAC-SHA256 base64-kujul
Varasem vorming (X-KB-Signature)<t>.<body>Kogu saladuse string tekstinav1= + HMAC-SHA256 kuueteistkümnendkujul

Piisab neist ühe kontrollimisest. Eelistage päist Standard Webhooks: sama kontroll on saadaval paljudes valmisteekides. Saladuse uuendamise ajal sisaldab iga päis iga kehtiva saladuse kohta ühte allkirja (päises webhook-signature tühikutega eraldatud, päises X-KB-Signature korduvate osadena v1=). Edastus on kehtiv, kui mõni neist sobib.

Lükake tagasi ka ajatempel, mis erineb teie kellast rohkem kui 5 minutit. See ei lase kellelgi salvestatud edastust hiljem uuesti esitada.

# Check a saved delivery by hand: body.json holds the raw body, the values come from its headers.
SECRET="whsec_…"; WEBHOOK_ID="evt_…"; TIMESTAMP="1791194400"

# Standard Webhooks: compare with the value after "v1," in webhook-signature
KEY=$(printf '%s' "${SECRET#whsec_}" | tr '_-' '/+')
while [ $(( ${#KEY} % 4 )) -ne 0 ]; do KEY="$KEY="; done
KEY_HEX=$(printf '%s' "$KEY" | openssl base64 -d -A | xxd -p | tr -d '\n')
{ printf '%s.%s.' "$WEBHOOK_ID" "$TIMESTAMP"; cat body.json; } \
  | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$KEY_HEX" -binary | openssl base64 -A

# Earlier format: compare with the value after "v1=" in X-KB-Signature
{ printf '%s.' "$TIMESTAMP"; cat body.json; } | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1

Testige allkirja kontrollimise koodi

Käivitage oma kood nende väärtustega enne, kui ühendate selle päris edastustega. Kui kell on seatud ajatemplile, peavad mõlemad kontrollid õnnestuma ning peavad ebaõnnestuma, kui keha üks bait muutub.

SisendVäärtus
Saladuswhsec_test_secret_0123456789abcdef
webhook-idevt_0123456789abcdef0123456789abcdef
webhook-timestamp ja t1791194400
Keha{"id":"evt_0123456789abcdef0123456789abcdef","type":"card.verified","created_at":"2026-10-05T10:00:00Z","org_id":1,"data":{"card":{"id":"c1"}}}
webhook-signaturev1,+xxWSXH6weQJ/MVg4+N78a1Dj4y/AQ4p94+PRNzpECg=
X-KB-Signaturet=1791194400,v1=ce26a19cb63cd3ae620217bf7688e1df1044fa7d59d9ae148d215f0292b768dc

4. Vastake kiiresti, tehke töö hiljem

Sursa ootab teie vastust kuni 10 sekundit. Iga olek 2xx tähendab, et edastus õnnestus; kõik muu, sealhulgas ümbersuunamine, ajalõpp või suletud ühendus, tähendab, et edastus ebaõnnestus ja seda proovitakse uuesti.

Seega peaks vastuvõtja ainult kontrollima, sündmuse salvestama ja vastama. Tehke tegelik töö hiljem, oma järjekorrast.

// Node.js 20+, no framework. verifyStandard and verifyLegacy come from step 3.
import http from "node:http";

const SECRET = process.env.SURSA_WEBHOOK_SECRET;

http
  .createServer(async (req, res) => {
    const parts = [];
    for await (const part of req) parts.push(part);
    const body = Buffer.concat(parts); // the raw bytes, before any JSON parsing

    const valid = req.headers["webhook-signature"]
      ? verifyStandard(SECRET, req.headers, body)
      : verifyLegacy(SECRET, req.headers["x-kb-signature"], body);
    if (!valid) {
      res.writeHead(400).end();
      return;
    }

    const event = JSON.parse(body);
    await saveEventOnce(event); // insert into your table or queue, keyed by event.id; ignore a duplicate
    res.writeHead(204).end();
  })
  .listen(3000);

Vastake 2xx alles siis, kui sündmus on turvaliselt salvestatud. Kui vastate enne ja teie protsess jookseb seejärel kokku, on sündmus teie jaoks kadunud, sest Sursa on selle juba edastatuks lugenud.

5. Korduskatsed

Ebaõnnestunud edastust proovitakse uuesti üha pikemate vahedega: umbes 1 minuti, 5 minuti, 30 minuti, 2 tunni, 5 tunni, 10 tunni, 24 tunni ja 24 tunni järel, kokku üheksa katset peaaegu kolme päeva jooksul. Iga paus varieerub kuni 20% võrra, et paljude veebihaakide korduskatsed ei saabuks samal hetkel.

  • Vastus 429 või 503 päisega Retry-After lükkab järgmise katse vähemalt selle ajani, kuid mitte rohkem kui 24 tundi edasi. Kasutage seda, kui teie süsteem on üle koormatud või hoolduses.
  • Vastus 410 Gone keelab veebihaagi: saatke see ainult siis, kui te ei soovi sellele aadressile enam edastusi.
  • Pärast 10 järjestikust ebaõnnestunud katset veebihaak peatatakse ja organisatsiooni administraatoreid teavitatakse. Sündmused kogunevad edasi ja kui veebihaagi töö jätkatakse haldusliideses või päringuga POST /v1/webhooks/{webhook_id}/resume, edastatakse need järjekorras.
  • Pärast viimast katset märgitakse edastus olekuga exhausted. Saate selle käsitsi uuesti saata.

Veebihaagi edastused koos iga katse, teie vastuse koodi ja ajastusega loetleb päring GET /v1/webhooks/{webhook_id}/deliveries, samuti näeb neid haldusliideses. POST /v1/webhooks/{webhook_id}/deliveries/{delivery_id}/redeliver saadab ühe edastuse uuesti. Uuesti edastamisel on sama webhook-id.

6. Järjekord ja duplikaadid

  • Järjekord. Ühe veebihaagi edastused toimuvad rangelt üksteise järel väärtuse sequence järjekorras. Kuni ühte edastust proovitakse uuesti, ootavad hilisemad. Erinevad veebihaagid üksteist ei oota.
  • Duplikaadid. Sama sündmus võib saabuda rohkem kui üks kord, näiteks kui teie vastus läks tagasiteel kaotsi. Salvestage iga töödeldud sündmuse webhook-id (see on ka keha väli id) ja jätke vahele sündmus, mida olete juba näinud.
  • Mõelge olekutes. Sama objekti muudatuste puhul võrrelge väärtust created_at või sequence sellega, mille olete salvestanud, ja eirake sündmust, mis on vanem kui teie olemasolev olek. Kahtluse korral lugege praegune objekt API kaudu: sündmus ütleb teile, et midagi muutus, API ütleb, mis see praegu on.

7. Viige andmed vastavusse sündmuste lindiga

Iga sündmust säilitatakse 30 päeva ka sündmuste lindis, olenemata sellest, kas mõni veebihaak oli selle tellinud. Kui teie vastuvõtja ei töötanud kauem, kui korduskatsed katavad, või soovite kontrollida, et midagi ei jäänud vahele, lugege linti võtmega, millel on roll admin ja ulatus webhooks:manage:

curl -G https://api.sursa.com/v1/webhook-events \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  --data-urlencode "type=card.*" \
  --data-urlencode "created_since=2026-10-20T00:00:00Z" \
  --data-urlencode "limit=200"

Lindis oleval sündmusel on sama id ja kuju mis edastuses, ilma edastuse väljadeta sequence, payload ja test. Kuna teie vastuvõtja jätab juba nähtud sündmused vahele, võite vastavusse viimist käivitada nii tihti, kui soovite, näiteks kord tunnis.

GET /v1/webhook-events/{event_id} loeb ühe sündmuse selle ID järgi.

8. Uuendage saladust

POST /v1/webhooks/{webhook_id}/rotate-secret väljastab uue saladuse ja jätab eelmise kattuvusajaks kehtima: vaikimisi 24 tundi, kuni 7 päeva. Kattuvusaja jooksul allkirjastatakse iga edastus mõlema saladusega.

  1. Uuendage saladust ja salvestage uus saladus oma vastuvõtjas vana kõrvale.
  2. Aktsepteerige edastus, kui see läbib kontrolli kummagi saladusega.
  3. Pärast kattuvusaega eemaldage vana saladus.

Kui vana saladus on lekkinud, lõpetage kattuvusaeg kohe päringuga POST /v1/webhooks/{webhook_id}/revoke-previous-secret või uuendage saladust väärtusega "overlap_hours": 0.

Kontroll-loend

  • Kontrollige toorest keha kasutades üht allkirjadest ja kontrollige ajatemplit.
  • Salvestage sündmus võtmega webhook-id, seejärel vastake 10 sekundi jooksul olekuga 2xx.
  • Jätke vahele duplikaadid ja vananenud sündmused; kui see on oluline, lugege praegune objekt API kaudu.
  • Vastake 429 või 503 päisega Retry-After, kui vajate, et Sursa saatmist aeglustaks; ärge kunagi vastake 410 kogemata.
  • Jätke vahele tundmatud sündmusetüübid ja väljad.
  • Viige andmed regulaarselt vastavusse sündmuste lindiga.