Перейти до вмісту
На сайт

Як надійно отримувати вебхуки Adyen

Adyen надсилає вебхуки на джерело Railhook. Джерело перевіряє HMAC, зберігає кожен вебхук таким, яким той надійшов, і пересилає його у ваш сервіс із повторними спробами. Railhook одразу підтверджує Adyen отримання, тож швидкість вашого платіжного обробника для Adyen більше не важлива.

Чому вебхукам Adyen потрібен буфер

Section titled “Чому вебхукам Adyen потрібен буфер”

Adyen чекає на 2xx протягом 10 секунд. Якщо не дочекався, пробує ще раз через 9, 18 і 27 секунд, а далі переводить сповіщення в чергу повторів: 2 хвилини, 5, 10, 15, 30, година, дві, чотири, вісім і далі з дедалі більшими інтервалами, аж до 30 днів. (Adyen: Troubleshoot webhooks)

Черга окрема для кожного ендпоінта, і вебхук, що застряг у ній, чекає ваша звірка. Коли попереду стоїть Railhook:

  • Railhook відповідає Adyen, щойно збереже вебхук, задовго до спливу 10 секунд, тож через ваш застосунок у чергу повторів Adyen нічого не потрапляє.
  • Ваш сервіс отримує до 5 спроб на кожне пересилання з інтервалами від 1 хвилини до 1 години, а те, що так і не вдалося доставити, потрапляє в «Недоставлені пересилання».
  • Дублікат (той самий pspReference і eventCode) отримує у відповідь збережену копію й не пересилається вдруге.
  • Будь-що збережене можна відтворити за вашим розкладом, а не за розкладом Adyen.

Знадобляться проєкт Railhook і API-ключ. Ті самі кроки є в панелі керування, у розділі «Вхідні».

Terminal window
export RAILHOOK_URL=https://railhook.io # or your own instance
export RAILHOOK_API_KEY=...
export PROJECT_ID=...
  1. Створіть вебхук в Adyen. У Customer Area відкрийте Developers → Webhooks і натисніть Create new webhook. Для звичайних платіжних подій виберіть тип Standard notification. Для цього потрібна роль Merchant Technical Integrator або Merchant Admin. (Adyen: Configure and manage webhooks)

  2. Створіть джерело Railhook, щоб отримати адресу, на яку Adyen має надсилати запити:

    Terminal window
    curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources" \
    -H "X-API-Key: $RAILHOOK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"Adyen","providerType":"ADYEN","verificationMode":"NONE"}'

    Збережіть id та ingressUrl, а ingressUrl вставте в Server configuration → URL вебхука в Adyen.

  3. Згенеруйте ключ HMAC. У секції Security того самого екрана натисніть Generate new HMAC key і одразу його скопіюйте: Adyen показує ключ повністю лише один раз. Далі лишається видимим тільки його key check value.

  4. Передайте ключ Railhook і ввімкніть перевірку:

    Terminal window
    curl -X PUT "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources/$SOURCE_ID" \
    -H "X-API-Key: $RAILHOOK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"Adyen","verificationMode":"PROVIDER","hmacSecret":"'"$ADYEN_HMAC_KEY"'"}'

    Вставляйте ключ точно таким, як його надрукував Adyen: це довгий шістнадцятковий рядок. Railhook декодує його в байти, перш ніж використати як ключ HMAC; так само роблять і власні бібліотеки Adyen.

  5. Додайте призначення, адресу вашого сервісу:

    Terminal window
    curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources/$SOURCE_ID/destinations" \
    -H "X-API-Key: $RAILHOOK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"url":"https://api.example.com/webhooks/adyen","authType":"BEARER","authConfig":"{\"token\":\"...\"}","enabled":true}'
  6. Перевірте з Customer Area. Відкрийте збережений вебхук, натисніть Test configuration, виберіть подію, і Adyen надішле зразкові сповіщення та покаже результат тут же. Вони з’являться в розділі «Вхідні → Отримані», з одним пересиланням на кожне призначення.

Як перевіряється підпис

Section titled “Як перевіряється підпис”

Adyen підписує у двох різних формах, і одне джерело Railhook перевіряє обидві, бо сам запит каже, яка з них перед ним.

Стандартні платіжні вебхуки не мають заголовка з підписом узагалі. Кожен notificationItems[].NotificationRequestItem підписує вісім власних полів, з’єднаних двокрапками:

pspReference:originalReference:merchantAccountCode:merchantReference:value:currency:eventCode:success

Відсутнє поле записують як порожній рядок, і нічого не екранують. HMAC-SHA256 цього рядка в Base64 потрапляє в additionalData.hmacSignature того самого елемента. Railhook перевіряє кожен елемент запиту: сповіщення приймається або відхиляється цілком, тож один підроблений елемент не проїде разом зі справжнім. (Adyen: Verify HMAC signatures)

Вебхуки Management, Banking і Balance Platform кладуть HMAC-SHA256 усього необробленого тіла в Base64 у заголовок hmacsignature, з тим самим шістнадцятковим ключем.

Запит, який не пройшов перевірку, отримує 401 і не зберігається.

Adyen не описує ані мітки часу, ані допустимого вікна, тож ніщо не прив’язує підпис до моменту. Повтор обмежує вікно повторів, а перед ним пара pspReference і eventCode, яку Adyen називає спільною для двох копій однієї події. Сповіщення рівно з одним елементом дедуплікується за цією парою; сповіщення з кількома не дедуплікується, бо ключ, узятий із першого елемента, відповів би на пізніший запит раніше збереженим і втратив би елементи, яких не називав.

Тіло точно таким, яким його надіслав Adyen, байт у байт, разом із notificationItems. Ваш сервіс відповідає Railhook, а не Adyen, тож повертати підтвердження для Adyen йому не треба: Railhook уже його надіслав. Див. Призначення.

Якщо ваш обробник волів би отримувати один елемент, а не конверт, задайте призначенню payloadTransform зі значенням $.notificationItems[0].NotificationRequestItem, і пересилатися буде сам елемент. Робіть так лише там, де ви певні, що Adyen надсилає по одному елементу на запит: вираз лишає перший і відкидає решту. Див. Трансформації.

  1. Встановіть CLI й увійдіть, як описано в розділі CLI, а потім відкрийте тунель до порту застосунку:

    Terminal window
    railhook listen 3000
  2. Додайте джерелу друге призначення з надрукованою публічною адресою й вашим маршрутом у кінці, наприклад https://<host>/tunnel/<slug>/webhooks/adyen. Вона веде на http://localhost:3000/webhooks/adyen.

  3. Натисніть Test configuration у Customer Area, і зразкові сповіщення прийдуть у ваш локальний застосунок. Вимкніть це призначення, коли закриєте тунель.

Відтворення після збою

Section titled “Відтворення після збою”

Кожне відтворене сповіщення йде на всі призначення джерела як нове пересилання:

Terminal window
curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-events/bulk-replay" \
-H "X-API-Key: $RAILHOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sourceId":"'"$SOURCE_ID"'","from":"2026-09-18T10:00:00Z","to":"2026-09-18T14:00:00Z","verified":true}'

Відтворити можна все, що ще зберігається: 7 днів у Railhook Cloud і скільки налаштуєте на власному сервері. Обробник має лишатися ідемпотентним за pspReference і eventCode, бо відтворення може надіслати сповіщення, які ваш сервіс уже обробив. Див. Відтворення.