Większość bugów webhooków Shopify w lokalnym developmencie sprowadza się do jednej linii: HMAC jest kodowany base64, nie hex. Jeśli wywołasz .digest('hex') i porównasz z X-Shopify-Hmac-Sha256, weryfikacja nigdy nie przejdzie — nawet z poprawnym współdzielonym sekretem. Widzieliśmy, jak senior inżynierowie tracili popołudnie przez ten jeden znak.
Pułapka base64
Stripe używa hex. GitHub używa hex (z prefiksem sha256=). Shopify używa base64. Trzech dostawców, trzy kodowania. Twoja pierwsza wersja weryfikatora prawie na pewno skopiuje snippet z innego projektu i cicho zawiedzie.
Tak powinna wyglądać weryfikacja:
const hmac = crypto
.createHmac('sha256', SHOPIFY_API_SECRET)
.update(rawBody) // raw body, not JSON-parsed
.digest('base64'); // base64, not hex
const valid = crypto.timingSafeEqual(
Buffer.from(hmac),
Buffer.from(req.headers['x-shopify-hmac-sha256']),
);
Poza kodowaniem liczą się dwie rzeczy. Ciało musi być surowymi, nieprzeparsowanymi bajtami. A porównanie musi być timing-safe — równość stringów wycieka informację bajt po bajcie.
Dlaczego tunel to ułatwia
Możesz też użyć komendy Shopify shopify app dev, która podnosi wewnętrzny tunel. Działa. Ale owija twój serwer dev we własny proces, połyka logi w określony sposób i nie daje przycisku powtórki. Do developmentu aplikacji poza „hello world” stabilny publiczny URL plus tunel localhost z przechwytywaniem żądań oszczędza więcej czasu niż CLI oszczędza przy początkowej konfiguracji.
npx portpreview 3000
Wklejasz URL HTTPS do konfiguracji webhooków aplikacji w panelu Partners, wyzwalasz zdarzenie ze sklepu testowego, a żądanie ląduje w twoim lokalnym handlerze z nienaruszonymi nagłówkami.
Sklepy testowe: część, którą dokumentacja Shopify pomija
Dwie rzeczy do wiedzy przed podłączeniem czegokolwiek:
- Sklepy developmentowe wysyłają wszystkie zdarzenia webhooków. Tworzenie zamówienia, fulfillment, inwentarz — wszystko. Nie musisz niczego fałszować; po prostu zainstaluj aplikację na sklepie dev i klikaj.
- Sekret webhooka różni się per aplikacja i per kanał dostawy. Jeśli subskrybujesz też EventBridge lub Pub/Sub, zachowanie HMAC jest inne. Tu mówimy o zwykłej dostawie HTTPS webhooków.
Konfiguracja krok po kroku
- Uruchom aplikację lokalnie na używanym porcie (3000 jest częsty).
- Wykonaj
npx portpreview 3000i skopiuj wypisany URL HTTPS. - W panelu Shopify Partners otwórz aplikację i przejdź do Configuration → Webhooks.
- Ustaw endpoint webhooka na
https://your-tunnel.portpreview.dev/api/webhooks/shopify(lub ścieżkę, której używa twoja aplikacja). - Zainstaluj aplikację na sklepie dev, potem wyzwól zdarzenie — utwórz szkic zamówienia, zrealizuj pozycję, zmień inwentarz.
- Obserwuj, jak żądanie ląduje. Inspektuj nagłówki i ciało. Powtórz przechwycone żądanie po każdej poprawce handlera.
Błędy, które ciągle widzimy
Ciało przeparsowane przed weryfikacją
Jeśli umieścisz app.use(express.json()) przed trasą webhooka, surowe bajty znikają zanim spróbujesz zweryfikować. Zamontuj parser surowego ciała tylko na ścieżce webhooka, albo pobierz ciało ręcznie ze strumienia żądania przed jakimkolwiek parsowaniem JSON.
Pomylone sekrety
Sekret aplikacji Partners to nie to samo co token Storefront API. HMAC webhooka używa sekretu aplikacji. Jeśli wpatrujesz się w shp_xxx w pliku env, wziąłeś niewłaściwy.
Zdarzenia testowe wyglądające identycznie
Przycisk Shopify „Send test notification” dostarcza syntetyczne zdarzenie z ciałem zastępczym. Podpis na tym zdarzeniu testowym jest prawdziwy, ale payload jest stały. Do realistycznego testowania kształtu payloadu wyzwalaj zdarzenia z samego sklepu dev.
Powtórka nie podlega negocjacji w dev aplikacji
Shopify ponawia nieudane webhooki do 48 godzin z wykładniczym backoff. To hojne, ale przy iteracji nie chcesz czekać na następną próbę. Przechwyć pierwszą dostawę w historii żądań twojego tunelu i powtarzaj na żądanie do lokalnego handlera.
Kiedy lokalne przestaje wystarczać
Przepływy rejestracji sklepu, webhooki GDPR i zmiany rozliczeń subskrypcji łatwiej walidować na wdrożonym środowisku, bo wchodzą w interakcję z własnym stanem konta Shopify. Do reszty — parsowania payloadu, weryfikacji podpisu, logiki biznesowej — lokalne jest szybsze.
Po matematykę podpisu u wszystkich dostawców przeczytaj nasz przewodnik weryfikacji podpisu webhooków. Dołącz do listy oczekujących PortPreview, jeśli chcesz tunel z wbudowaną powtórką.