Як надійно отримувати вебхуки Stripe
Stripe надсилає вебхуки на джерело Railhook. Джерело перевіряє підпис, зберігає кожну подію такою, якою вона надійшла, і пересилає її у ваш сервіс. Невдалі пересилання повторюються, а те, що так і не доставлено, можна відтворити пізніше.
Чому повторних спроб самого Stripe недостатньо
Section titled “Чому повторних спроб самого Stripe недостатньо”У live-режимі Stripe до трьох днів повторює невдалу подію з експоненційною затримкою; у пісочниці тричі за кілька годин. З Dashboard подію можна надіслати повторно протягом 15 днів, через Stripe CLI протягом 30. Події можуть надходити не по порядку і більше одного разу. (Stripe: Receive Stripe events in your webhook endpoint)
Що лишається на вас:
- Швидка відповідь. Stripe чекає
2xxдо будь-якої складної логіки, інакше доставка завершиться тайм-аутом і вважатиметься невдалою. Railhook відповідає Stripe, щойно збереже подію; ваш сервіс має стільки часу, скільки дозволяє тайм-аут призначення. - Відновлення після збою. Dashboard надсилає події повторно по одній. Railhook відтворює всі збережені події за проміжок часу одним викликом.
- Дублікати. Railhook розпізнає ідентифікатор
evt_…: на повторну доставку тієї самої події він відповідає202зі збереженою копією і вдруге її не пересилає.
Підключення Stripe
Section titled “Підключення Stripe”Знадобляться проєкт Railhook і API-ключ. Ті самі кроки є в панелі керування, у розділі «Вхідні».
export RAILHOOK_URL=https://railhook.io # or your own instanceexport RAILHOOK_API_KEY=...export PROJECT_ID=...-
Створіть джерело. Stripe показує секрет підпису лише після того, як ви зареєструєте URL, тож спершу створіть джерело без секрету. Із
verificationMode:PROVIDERі без секрету воно відповідає401на кожен запит, доки ви не додасте секрет, тож нічого неперевіреного не зберігається.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":"Stripe","providerType":"STRIPE","verificationMode":"PROVIDER"}'Збережіть
idіingressUrlіз відповіді. -
Зареєструйте URL у Stripe. У Workbench відкрийте Webhooks і натисніть Create an event destination. Виберіть Your account, позначте типи подій, які обробляєте, виберіть Webhook endpoint і вставте
ingressUrlу поле Endpoint URL. -
Передайте Railhook секрет підпису. На сторінці ендпоінта в Stripe натисніть Reveal secret і скопіюйте значення, що починається з
whsec_. Додайте його в джерело: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":"Stripe","hmacSecret":"whsec_..."}'Змінюються лише ті поля, які ви надіслали; секрет доступний лише для запису, і API ніколи його не повертає.
-
Додайте призначення, URL вашого сервісу:
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/stripe","authType":"BEARER","authConfig":"{\"token\":\"...\"}","enabled":true}' -
Надішліть тестову подію зі Stripe або виконайте
stripe trigger payment_intent.succeeded. Вона з’явиться в розділі «Вхідні» → «Отримані» з одним пересиланням на кожне призначення.
Як перевіряється підпис
Section titled “Як перевіряється підпис”Railhook читає Stripe-Signature, обчислює HMAC-SHA256 від <t>.<raw body> у hex із секретом whsec_ і порівнює результат із кожним значенням v1. t має відрізнятися від часу на годиннику Railhook не більш ніж на 300 секунд. Поки ви ротуєте секрет у Stripe, той надсилає по одному v1 на кожен активний секрет; запит проходить перевірку, якщо збігається будь-який із них, тож оновіть секрет у джерелі одразу після ротації. На запит, що не пройшов перевірку, Railhook відповідає 401 і не зберігає його, а Stripe повторює спробу.
Що отримує ваш сервіс
Section titled “Що отримує ваш сервіс”Тіло точно таке, яким його надіслав Stripe, байт у байт, з оригінальним Content-Type. Stripe-Signature не пересилається: ваш сервіс автентифікує Railhook за обліковими даними призначення, тож секрет Stripe йому взагалі не потрібен. Кожен запит містить Idempotency-Key, однаковий для всіх спроб, і X-Forward-Attempt. Див. Призначення.
Після 408, 429, будь-якого 5xx, тайм-ауту чи помилки з’єднання Railhook повторює пересилання, усього до 5 спроб. Будь-який інший 4xx одразу переносить його в «Недоставлені пересилання», звідки його можна повторити, коли виправите сервіс.
Локальна розробка з CLI
Section titled “Локальна розробка з CLI”Спрямуйте призначення на свій комп’ютер через тунель, щоб отримувати перевірені тестові події Stripe локально.
-
Встановіть CLI й увійдіть, як описано в CLI, а потім відкрийте тунель до порту, який слухає ваш застосунок:
Terminal window railhook listen 3000 -
Додайте джерелу друге призначення: публічну адресу, яку вивела команда, з вашим маршрутом у кінці, наприклад
https://<host>/tunnel/<slug>/webhooks/stripe. Шлях після адреси тунелю зберігається, тож запит потрапить наhttp://localhost:3000/webhooks/stripe. -
Згенеруйте подію в пісочниці Stripe. Коли закриєте тунель, вимкніть або видаліть це призначення, щоб його пересилання не накопичувалися в «Недоставлених пересиланнях».
Відтворення після збою
Section titled “Відтворення після збою”Якщо ваш сервіс лежав довше, ніж тривали повторні спроби, відтворіть те, що надійшло за цей час. Railhook створить нові пересилання на кожне призначення джерела, кожне зі спроби 1:
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}'Тримайте обробник ідемпотентним за ідентифікатором події Stripe: відтворення надсилає й події, які сервіс, можливо, уже обробив. Відтворити можна все, що ще зберігається: 7 днів у Railhook Cloud і скільки налаштуєте на власному сервері. Див. Відтворення.