Усі статті
Shopifywebhook debugginglocal testinge-commerce

Тестуйте вебхуки Shopify локально без сюрпризів

Більшість багів вебхуків Shopify у локальній розробці зводяться до одного рядка: HMAC кодується в base64, а не hex. Якщо ви викликаєте .digest('hex') і порівнюєте з X-Shopify-Hmac-Sha256, перевірка ніколи не пройде — навіть з правильним спільним секретом. Ми бачили, як senior-інженери втрачали півдня через цей один символ.

Пастка base64

Stripe використовує hex. GitHub використовує hex (з префіксом sha256=). Shopify використовує base64. Три провайдери, три кодування. Ваша перша версія верифікатора майже напевно скопіює сніпет з іншого проєкту й тихо провалиться.

Ось як має виглядати перевірка:

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']),
);

Окрім кодування важливі дві речі. Тіло має бути сирими, непарсеними байтами. І порівняння має бути timing-safe — рівність рядків витікає інформацію по байту за раз.

Чому тунель це спрощує

Можна також використати команду Shopify shopify app dev, яка піднімає внутрішній тунель. Працює. Але вона обгортає ваш dev-сервер у власний процес, ковтає логи певним чином і не дає кнопки повтору. Для розробки застосунку складнішого за «hello world» стабільний публічний URL плюс тунель localhost із захопленням запитів економить більше часу, ніж CLI економить на початковому налаштуванні.

npx portpreview 3000

Ви вставляєте HTTPS-URL у конфігурацію вебхуків застосунку в дашборді Partners, тригерите подію з тестового магазину, і запит приземляється у вашому локальному обробнику з усіма заголовками недоторканими.

Тестові магазини: частина, яку документація Shopify пробігає

Дві речі, які треба знати, перш ніж щось під'єднувати:

  • Магазини розробки шлють усі події вебхуків. Створення замовлення, фулфілмент, інвентар — усе. Не треба нічого підробляти; просто встановіть застосунок на dev-магазин і клікайте.
  • Секрет вебхука відрізняється за застосунком і за каналом доставки. Якщо ви також підписані на EventBridge чи Pub/Sub, поведінка HMAC інша. Тут ідеться про звичайну HTTPS-доставку вебхуків.

Покрокове налаштування

  1. Запустіть застосунок локально на потрібному порту (3000 — частий вибір).
  2. Виконайте npx portpreview 3000 і скопіюйте надрукований HTTPS-URL.
  3. У дашборді Shopify Partners відкрийте застосунок і перейдіть до Configuration → Webhooks.
  4. Встановіть endpoint вебхука на https://your-tunnel.portpreview.dev/api/webhooks/shopify (або шлях, який використовує застосунок).
  5. Встановіть застосунок на dev-магазин, потім тригерніть подію — створіть чернетку замовлення, виконайте товар, змініть інвентар.
  6. Дивіться, як запит приземляється. Інспектуйте заголовки й тіло. Повторюйте захоплений запит після кожного фіксу обробника.

Помилки, які ми постійно бачимо

Тіло розпарсене до верифікації

Якщо ви ставите app.use(express.json()) перед маршрутом вебхука, сирі байти зникають до моменту перевірки. Монтуйте парсер сирого тіла лише на шлях вебхука або витягуйте тіло вручну з потоку запиту до будь-якого JSON-парсингу.

Переплутані секрети

Секрет застосунку Partners — не те саме, що токен Storefront API. HMAC вебхука використовує секрет застосунку. Якщо ви дивитесь на shp_xxx в env-файлі, ви взяли не той.

Тестові події, що виглядають однаково

Кнопка Shopify «Send test notification» доставляє синтетичну подію з тілом-заглушкою. Підпис на цій тестовій події справжній, але payload фіксований. Для реалістичного тестування форми payload тригерте події з самого dev-магазину.

Повтор не обговорюється для розробки застосунків

Shopify повторює невдалі вебхуки до 48 годин з експоненційним backoff. Це щедро, але під час ітерацій ви не хочете чекати наступного повтору. Захопіть першу доставку в історії запитів вашого тунелю й повторюйте на вимогу проти локального обробника.

Коли локального стає замало

Потоки реєстрації магазину, GDPR-вебхуки та зміни білінгу підписок легше валідувати проти розгорнутого середовища, бо вони взаємодіють із власним станом акаунта Shopify. Для всього іншого — парсинг payload, верифікація підпису, бізнес-логіка — локально швидше.

Щодо базової математики підпису для всіх провайдерів прочитайте наш посібник із верифікації підпису вебхуків. Приєднайтеся до списку очікування PortPreview, якщо хочете тунель із вбудованим повтором.

Поширені запитання

Як тестувати вебхуки Shopify на localhost?
Запустіть тунель на кшталт PortPreview, отримайте публічний HTTPS-URL і зареєструйте його як endpoint вебхука в дашборді Shopify Partners. Встановіть застосунок на магазин розробки, тригерте події, і доставки досягають вашого локального обробника.
Чому моя верифікація HMAC Shopify завжди падає?
Найчастіше це кодування. Shopify підписує через HMAC SHA-256 і кодує результат у base64. Якщо ваш код використовує .digest('hex') замість .digest('base64'), будь-яке порівняння падає, навіть якщо секрет правильний.
Чи потрібен shopify app dev, чи можна будь-який тунель?
Будь-який тунель працює. shopify app dev включає власний тунель для зручності, але універсальний тунель із захопленням і повтором запитів корисніший для тривалої розробки.