Wszystkie artykuły
Shopifywebhook debugginglocal testinge-commerce

Testuj webhooki Shopify lokalnie bez niespodzianek

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

  1. Uruchom aplikację lokalnie na używanym porcie (3000 jest częsty).
  2. Wykonaj npx portpreview 3000 i skopiuj wypisany URL HTTPS.
  3. W panelu Shopify Partners otwórz aplikację i przejdź do Configuration → Webhooks.
  4. Ustaw endpoint webhooka na https://your-tunnel.portpreview.dev/api/webhooks/shopify (lub ścieżkę, której używa twoja aplikacja).
  5. Zainstaluj aplikację na sklepie dev, potem wyzwól zdarzenie — utwórz szkic zamówienia, zrealizuj pozycję, zmień inwentarz.
  6. 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ą.

Najczęściej zadawane pytania

Jak testować webhooki Shopify na localhost?
Uruchom tunel jak PortPreview, uzyskaj publiczny URL HTTPS i zarejestruj go jako endpoint webhooka w panelu Shopify Partners. Zainstaluj aplikację na sklepie developmentowym, wyzwalaj zdarzenia, a dostawy docierają do twojego lokalnego handlera.
Dlaczego moja weryfikacja HMAC Shopify zawsze zawodzi?
Najczęściej to kodowanie. Shopify podpisuje HMAC SHA-256 i koduje wynik base64. Jeśli twój kod używa .digest('hex') zamiast .digest('base64'), każde porównanie zawodzi, nawet gdy sekret jest poprawny.
Czy potrzebuję shopify app dev, czy mogę użyć dowolnego tunelu?
Dowolny tunel działa. shopify app dev zawiera własny tunel dla wygody, ale tunel ogólnego przeznaczenia z przechwytywaniem i powtórką żądań jest bardziej przydatny przy długotrwałym developmencie.