Perilaku pengiriman
Diambil dari dokumentasi resmi vendor, terakhir diperiksa 2026-08-06. Jika vendor tidak menyebut angka, tabel ini juga tidak mencantumkannya.
| Batas waktu respons | tidak dipublikasikan vendor Stripe tidak memublikasikan angkanya. Dokumentasinya hanya meminta Anda mengembalikan 2xx sebelum logika yang lambat. 20 detik adalah angka acuan yang dipakai komunitas |
|---|---|
| Percobaan ulang | Backoff eksponensial hingga 3 hari dalam mode live. Sandbox: 3 upaya selama beberapa jam |
| Berhenti mencoba | Endpoint dinonaktifkan setelah terus gagal, dengan email pemberitahuan lebih dulu. Event tetap ada di Events API selama 30 hari |
| Sumber | https://docs.stripe.com/webhooks |
Tanda tangan
Diverifikasi dengan verifier yang berfungsi dan dibuktikan oleh test suite, bukan dibaca dari dokumentasi. Terakhir diverifikasi 2026-08-20.
| Algoritma | HMAC-SHA256 |
|---|---|
| Payload bertanda tangan | {timestamp}.{body} |
| Encoding | hex |
| Header | stripe-signature = t=X,v1=hex |
| Toleransi | 5 menit |
Verifikasi
Raw body dari permintaan, byte demi byte, sebelum parsing JSON apa pun. Setiap skema di halaman ini rusak begitu framework melakukan serialisasi ulang pada payload.
const crypto = require("node:crypto");
// stripe-signature: "t=1700000000,v1=abc..." — HMAC-SHA256 over "{t}.{body}"
const pairs = Object.fromEntries(
req.headers["stripe-signature"].split(",").map((p) => p.split("=")),
);
const expected = crypto
.createHmac("sha256", endpointSecret) // whsec_... from the endpoint's page
.update(`${pairs.t}.${rawBody}`)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(pairs.t)) < 300;
const received = Buffer.from(pairs.v1 ?? "");
const wanted = Buffer.from(expected);
// timingSafeEqual throws on a length mismatch, so check that first.
const valid =
fresh && received.length === wanted.length && crypto.timingSafeEqual(received, wanted);Atau biarkan SDK yang mengerjakannya: stripe.webhooks.constructEvent(rawBody, sig, secret); fungsi ini butuh raw body, jadi pasang express.raw() di route webhook sebelum parser JSON apa pun.
Yang sering menjebak
Stripe tidak pernah memublikasikan batas waktu respons. Dokumentasinya hanya meminta Anda mengembalikan 2xx sebelum logika yang lambat; 20 detik adalah angka yang dipakai komunitas, dan handler yang menulis ke database lambat secara sinkron nyaris menyentuh batas itu di setiap event.
Setelah 3 hari gagal, event keluar dari antrean percobaan ulang tanpa pemberitahuan. Jika kegagalan berlanjut, endpoint dinonaktifkan, dengan email lebih dulu, dan event tetap dapat diambil dari Events API selama 30 hari.
Baca juga
AnyHook berada di depan endpoint yang menerima webhook dari Stripe: AnyHook menjawab dalam sekitar satu detik, mencoba ulang sesuai jadwalnya sendiri saat server Anda mati, dan menyimpan setiap event agar dapat diputar ulang (replay). Ganti satu URL, kode Anda tetap; agar percobaan ulang dan putar ulang diterima, periksa AnyHook-Signature, karena tanda tangan milik Stripe kedaluwarsa setelah 5 menit.