Webhooky

Koncept

Webhooky jsou volání vývojářem zadaného URL pomocí HTTPS protokolu v okamžiku, kdy v eshopu nastane určitá událost, například vznik nové objednávky. O jejich doručení se stará Shoptet. Seznam dostupných událostí je v Apiary.

Příklad použití webhooku

Nejdříve je potřeba si webhook zaregistrovat. To se dělá pomocí endpointu POST /api/webhooks. Například pokud chcete být informování o nových objednávkách, zašlete:

{
  "data": [
    {
      "event": "order:create",
      "url": "https://myapplication.tld/new_order.php"
    }
  ]
}

API odpoví přibližně takto:

{
  "data": {
    "id": 123,
    "event": "order:create",
    "url": "https://myapplication.tld/new_order.php",
    "created": "2018-08-02T17:22:02+0200",
    "updated": null
  },
  "errors": null
}

Od této chvíle, kdykoliv v eshopu vznikne nová objednávka, Shoptet vyvolá URL https://myapplication.tld/new_order.php jako POST s následujícím obsahem:

{
    "eshopId": 222651,
    "event": "order:create",
    "eventCreated": "2019-01-08T15:13:39+0100",
    "eventInstance": "2018000057"
}

Oznámení o vzniklé události obsahuje identifikaci obchodu (eshopId), typ události (order:create = vytvoření objednávky), čas vzniku a dotčenou instanci (eventInstance) – v našem případě je to objednávka s číslem 2018000057.

Pravděpodobně nás teď bude zajímat detail této objednávky – podle eshopId dohledáme správná OAuth-Access-Token, vyžádáme si Access-Token a standardní cestou se zeptáme na objednávku pomocí GET /api/orders/2018000057.

Registrace webhooků

Jak zaregistrovat nový webhook jsme si již ukázali výše. K tomu ještě dodejme, že je možné pro jednu událost (např. order:update) zaregistrovat více než jedno URL POST /api/webhooks, ovšem pro jednu událost se nesmí opakovat. Povolená jsou URL s porty 80, 8080 a 443.

Dále je důležité mít na paměti, že webhooky se registrují pro každou instalaci (tedy každý eshop a doplněk) samostatně. Není tedy možné zaregistrovat jeden webhook pro doplněk, který by pak zasílal notifikace ze všech eshopů, které si ho nainstalují. Máte tím danou flexibilitu, že webhooky registrujete jen pro ty eshopy, kde je to třeba (například uživatel vypne notifikace) a můžete použít URL specifická pro eshop (a tím si usnadnit identifikaci eshopu), například https://call.me/order/shopId134.

Registrace ani další úpravy těchto „Událostí doplňků“ nepodléhají žádnému procesu schvalování, jsou platné okamžitě. Má je plně ve své režii autor doplňku.

Další endpointy pro obsluhu webhooků

Zaregistrované webhooky jsou platné vždy pro jeden doplněk a jeden eshop. Není možné registrovat ani číst webhooky pro jiný doplněk, ani kdyby byl od stejného vývojáře a pro stejný eshop – je vázaný na konkrétní instalaci doplňku.

Oznámení

Zaslané oznámení na URL webhooku musí být webhookem potvrzeno HTTP kódem 200. V opačném případě budeme oznámení opakovaně zasílat po 15 minutách ještě 2x (celkem max. 3 pokusy). Po nepotvrzeném posledním oznámení označíme oznámení jako neaktivní.

Realizovaná oznámení na webhooky jsou logovaná, vč. počtu opakování, stavu, časových razítek a zda jsou aktivní. Autor doplňku má možnost číst log realizovaných requestů na webhooky pomocí endpointu GET /api/webhooks/notifications.

Oznámení od Shoptetu budou posílána výhradně z IP adres 78.24.15.64/26.

Oznámení by mělo být z vaší strany zpracováno rychle a dělat jen nejnutnější činnosti – jinak se zvyšuje riziko, že dojde k chybě a webhook bude volán znovu, popř. vyprší čas, do kterého očekáváme odpověď (4 sec). V ideálním případě byste měli jen uložit identifikaci změny (např. „objednávka/nová/číslo“) a vlastní ošetření (načtení detailu, interní zapracování, zaslání emailu atd.) již provést asynchronně.

Počítejte také s tím, že oznámení vám nebudou posílána jedno po druhém, ale mohou chodit paralelně.

Podepisování webhooků

Pro ověření, že oznámení o události poslal opravdu Shoptet, a že zpráva nebyla cestou pozměněna, je možné pomocí hlavičky Shoptet-Webhook-Signature, která obsahuje hash dat zaslaných v těle oznámení.

Nejdříve je potřeba zavolat endpoint [POST /api/webhooks/renew-signature-key], který vygeneruje signatureKey. Ten si uložte.

Shoptet si ho uloží pro daný doplněk a eshop také. V okamžiku emitování oznámení o proběhlé události vypočítá hash takto:

ShoptetWebhookSignature = hash_hmac('sha1', $messageBody, $signatureKey);

Tento kontrolní součet (hash) je vložen do HTTP hlavičky Shoptet-Webhook-Signature před voláním zadaného URL.

Je doporučeno, aby hned po přijetí zprávy byl podpis ověřen. To znamená vzít tělo došlé zprávy, s použitím signatureKey získaného výše vytvořit vlastní výpočet podpisu (pomocí hash_hmac, resp. sha1) a ten pak ověřit s hodnotou Shoptet-Webhook-Signature doručenou v HTTP hlavičce.

Příklad ověření v PHP:

<?php
$webhookBody = '{"eshopId":315185,"event":"addon:uninstall","eventCreated":"2019-09-23T22:01:36+0200","eventInstance":"315185"}';
$signatureKey = '61d1175f54c47dd67df14c17002a17b2';
$calculated = hash_hmac('sha1', $webhookBody, $signatureKey);
$expected = 'a0e0a3e7689bd4c80e4d6ffcccb05235b864e1d0';

printf('calculated: %s %s', $calculated, PHP_EOL);
printf('expected: %s %s', $expected, PHP_EOL);
printf('is equal: %s %s', $calculated === $expected ? 'yes' : 'no', PHP_EOL);

Příklad ověření v Pythonu:

import base64
import hmac
import hashlib

key = '61d1175f54c47dd67df14c17002a17b2'
message = '{"eshopId":315185,"event":"addon:uninstall","eventCreated":"2019-09-23T22:01:36+0200","eventInstance":"315185"}'
digest = hmac.new(key.encode('UTF-8'), message.encode('UTF-8'), hashlib.sha1).hexdigest();
expected = 'a0e0a3e7689bd4c80e4d6ffcccb05235b864e1d0'

print "calculated: {}".format(digest)
print "expected: {}".format(expected)
print "is equal: {}".format(digest == expected)
Facebook
Twitter