Skip to Content
Webhook'larGenel bakış

Webhook’lar — Genel bakış

Webhook’lar yetkili sinyaldir. Tarayıcı callback’leri (onSuccess) ve panel görünümleri kolaylıktır; webhook’lar gerçek kaynaktır.

Teslim garantileri

  • En az bir kez. Sunucunuz zaman aşımı içinde 2xx döndürmezse, tek bir event en fazla 6 kez teslim edilebilir. Handler’ınızı idempotent yapın — X-Delivery üzerinde dedup yapın (payload’da bir event_id alanı yoktur; stabil teslim UUID’si idempotency anahtarıdır).
  • HTTP isteği başına bir event. Batch yapma yok.
  • Uç nokta başına izolasyon. Birden fazla kayıtlı uç noktanız varsa, her biri kendi teslim + yeniden deneme izini alır. Yavaş bir satıcı URL’si diğerlerini açlığa terk edemez — her host’un kendi devre kesicisi vardır.
  • İmzalı. Her payload bir X-Signature başlığı taşır (ve bir rotation’dan sonraki 24 saatlik pencerede, ayrıca bir X-Signature-Prev). Gövde ile bir şey yapmadan önce doğrulayın. Bkz. İmza doğrulama.

Abone olunabilir event tipleri

EventŞu durumda tetiklenir…
payment.settledZincir üstü transfer, zincirin onay sayısını temizledi. Siparişleri ödendi olarak işaretlemek için bunu kullanın.
payment.failedBir fiat ödeme provider tarafından açıkça reddedildi (şu anda: başarısızlığı sinyalleyen Stripe webhook’u). Kripto zaman aşımları için tetiklenmez — onlar checkout.expired olarak yüzeye çıkar, kısa kripto ödemeleri ise payment.underpaid olarak yüzeye çıkar.
payment.underpaidFonlar geldi ama sipariş toplamından eksik (tipik: stablecoin transfer ücreti tutardan alındı).
payment.overpaidFonlar sipariş toplamının fazlasıyla geldi. Fazlalık kaydedilir ama otomatik olarak iade edilmez.
order.createdYeni bir sipariş açıldı — ya B2B API çağrınız ile ya da bir checkout-oturumu dönüşümüyle.
order.canceledBir sipariş iptal edildi durumuna geçti. Payload’un data.reason’ı manuel iptali payment_timeout (worker tarafından süpürülen eski ödenmemiş sipariş) ile ayırır.
order.resolvedBir PARTIAL_PAID sipariş PAID’e çözümlendi — satıcı eksikliği kabul etti.
order.reopenedÖnceden otomatik-iptal edilmiş bir sipariş (canceled_reason=payment_timeout) satıcı tarafından yeniden açıldı.
checkout.createdBir alıcı bir sipariş için checkout’u açtı.
checkout.completedAlıcı tarafı akış bitti (zincir üstü tahsilatı ima etmez — bunun için payment.settled kullanın).
checkout.expiredAlıcı vazgeçti ve oturum TTL’i doldu.
payment.refund.requestedBir iade kaydı oluşturuldu — satıcı tarafından başlatılan bir API çağrısı veya müşteri-gönderimli bir iade-talep formundan.
payment.refund.approvedBekleyen bir iade onay iş akışınızı geçti.
payment.refund.rejectedBekleyen bir iade reddedildi.
payment.refund.executedİadenin zincir üstü transferi temizlendi ve kayıt nihai executed durumuna geçti.
refund_request.createdBir iade-talep token’ı üretildi. data.source b2b / dashboard / renewal. Abone olmak opsiyoneldir — hangi token’ın sipariş başına şu anda aktif olduğunu takip eden denetim pipeline’ları için kullanışlı.
refund_request.renewal_requestedBir alıcı token süresi dolduktan sonra “Yeni bağlantı talep et” butonuna tıkladı. Abone olmak şiddetle önerilir — bu, satıcının yenileme widget’ında harekete geçmesi gereken yeni bir öğenin olduğuna dair işarettir.
refund_request.renewedBir yenileme onaylandı ve yeni bir token eskisini değiştirdi. data.old_token / data.new_token denetim zincirini oluşturur.
refund_request.canceledBir satıcı panelden bir token’ı CANCELED’a geçirdi (örn. bir yenileme talebini reddetti, aktif bir bağlantıyı sonlandırdı). Idempotent — yalnızca ilk geçiş bir event yayar. data.reason opsiyonel satıcı notudur.

Panel bu listeyi GET /v1/webhooks/event-types üzerinden alır, böylece uç nokta oluşturma / düzenleme formu her zaman platformun fiilen yaydığı ile eşleşir. Göndermediğimiz bir event’e abone olmak, oluşturma zamanında açık bir hata ile reddedilir.

Test event’leri abone olunabilir değildir. Panelin uç nokta başına Send Test butonu, senkron olarak o tek uç noktaya bir webhook.test.ping zarfı POST eder (yeniden deneme pipeline’ını atlayarak) ve eski satıcı-seviyesi “Send test event” yolu, filtresinden bağımsız olarak her aktif uç noktaya bir webhook.test zarfı yayar. Hiçbiri yukarıdaki katalogda görünmez — kayıtlı bir uç noktanız olduğu için alırsınız, abone olduğunuz için değil.

Yalnızca işlediğiniz event’lere abone olun. Her uç noktanın kendi event filtresi vardır; joker "*" “her event, gelecekte eklenecekler dahil” anlamına gelir. Daha az event’e abone olmak handler’ınızı daha temiz tutar ve hata durumunda yeniden denememiz gereken yüzey alanını azaltır.

Payload + başlıklar

HTTP gövdesi doğrudan event’e özgü veri nesnesidir. Stripe stili dış zarf yok — event tipi, teslim ID’si ve emisyon timestamp’i gibi alanlar başlıklarda yaşar. payment.settled için gövde şöyle görünür:

{ "receipt_id": "rcp_…", "order_id": "ord_…", "payment_intent_id": "pin_…", "checkout_session_id": "cst_…", "merchant_id": "mer_…", "customer_id": "cus_…", "total": "49.00", "currency": "USD", "payment_method": "crypto", "token": "USDC", "network": "polygon", "tx_hash": "0x…", "deposit_address": "0x…", "treasury_address": "0x…", "amount_received": "49.00", "confirmations": 5, "metadata": { /* event başına */ } }

Diğer event’ler kendi alan setlerini taşır — event başına dokümanlar gelene kadar kanonik şekil için payment-service/internal/domain/events.go içindeki publisher struct’larına bakın. Alan adları stabildir (lower snake_case); zincir üstü tx hash her zaman tx_hash’tir (transaction_hash değil).

Gelen istekteki başlıklar

Content-Type: application/json X-Event: payment.settled X-Delivery: 7c9e6679-7425-40de-944b-e07fc1f90ae7 Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7 X-Timestamp: 1729536000 X-Signature: sha256=9a8b7c… X-Signature-Prev: sha256=fa31b2… (yalnızca bir rotation kayma penceresinde)
BaşlıkNe olduğu
X-EventEvent tipi (örn. payment.settled). JSON ayrıştırmasını atlamak istiyorsanız proxy katmanında bunun üzerinde yönlendirin.
X-DeliveryTeslim satırını tanımlayan UUID. Aynı (event, endpoint) çiftinin tüm yeniden denemelerinde stabil — idempotency anahtarınız olarak kullanın.
Idempotency-KeyX-Delivery’i yansıtır (aynı değer). Her teslimde ayarlanır — Stripe / GitHub’dan gelen kuralı alır.
X-TimestampDenemenin gönderildiği Unix-saniye. Payload’a imzalanmıştır, böylece yakalanan bir (body, X-Signature) çifti süresiz olarak yeniden oynatılamaz — timestamp’i tolerans pencerenizin dışında olan teslimleri reddedin.
X-SignatureHMAC-SHA256(secret, X-Timestamp + "." + raw_body)’nin sha256=<hex>’i. Bkz. İmza doğrulama.
X-Signature-PrevÖnceki secret ile aynı algoritma. Yalnızca siz rotate ettikten sonraki 24 saatlik pencerede mevcuttur — geçiş sırasında her iki anahtarı da çalıştıran doğrulayıcıların teslimleri kabul etmeye devam etmesini sağlar. Pencere kapandıktan sonra başlık gönderilmeyi durdurur.

Yeniden deneme programı

Uç noktanız zaman aşımı içinde 2xx döndürmezse, bu programda yeniden deneriz (timestamp’ler ilk denemeye göre):

DenemeGecikmeBirikimli
10s0s
2+1 dk1dk
3+5 dk6dk
4+15 dk21dk
5+1 saat1s 21dk
6+6 saat7s 21dk
  1. deneme başarısız olduktan sonra, teslim dead letter’a taşınır ve satıcı hesabı e-postası bilgilendirilir. Dead-letter’lanmış event’ler panelin Geliştiriciler → Webhook’lar → Teslim geçmişi panelinden veya doğrudan POST /v1/webhooks/deliveries/:id/replay üzerinden yeniden oynatılabilir. Her replay kendi X-Delivery’si ile yeni bir teslim satırı oluşturur — denetim zinciri parent_delivery_id üzerinden orijinale geri bağlanır, böylece replay’lerin yeniden denemeleri kaynak event’i gölgelemez.

Bir uç nokta kaydedin

Satıcı panelinden :

  1. Geliştiriciler → Webhook’lar+ Uç nokta ekle
  2. URL’nizi yapıştırın — yalnızca https://… (düz HTTP reddedilir; oluşturma formu ayrıca localhost’u, özel IP aralıklarını ve userinfo taşıyan URL’leri engeller)
  3. Abone olunacak event’leri seçin (veya hepsi için *)
  4. Ortam seçin — test veya canlı (her biri kendi secret’ını alır; asla çapraz geçmezler)
  5. Kaydet → panel imzalama secret’ını (whsec_…) bir kez gösterir. Sunucu tarafında saklayın; sonraki iki özellik için ihtiyacınız olacak.

Satıcı başına ortam başına 10 uç noktaya kadar kaydedebilirsiniz (örn. biri production sipariş karşılama için, biri staging yansıtması için, biri bir Slack bildirici için). Her biri kendi yeniden deneme durumunu, secret’ını ve host başına devre kesicisini korur.

Her uç noktada yaşam döngüsü eylemleri

Her uç nokta kartındaki ⋮ menüsü şunları sunar:

  • Düzenle — URL’yi, açıklamayı veya abonelik listesini değiştir. Yeni URL, oluşturma ile aynı https:///SSRF kurallarıyla yeniden doğrulanır.
  • Send Test — mevcut secret’ınızla imzalanmış bir webhook.test.ping zarfını senkron olarak POST eder. Panel HTTP durumunu, gecikmeyi ve yanıtınızın 512 baytlık bir parçacığını gösterir. RMQ pipeline’ını atlar, böylece cevap anlıktır.
  • Rotate Secret — yeni bir secret oluşturur. Önceki olan 24 saat geçerli kalır (teslimler pencere boyunca hem X-Signature hem de X-Signature-Prev taşır, böylece her iki anahtarı da çalıştıran doğrulayıcılar siz yeniden dağıtırken event’leri kabul etmeye devam eder).
  • Reveal Secret — mevcut secret’ı yeniden gösterir. Yeni 2FA doğrulaması ile korunur ve denetim günlüğüne kaydedilir; yalnızca kopyanızı kaybettiğinizde ve Rotate kabul edilemediğinde kullanın.
  • Etkinleştir / Devre Dışı Bırak — teslim geçmişini kaybetmeden is_active’i değiştirin. Devre dışı bırakılmış uç noktalar panelde kalır ama yeni teslim almaz.
  • Sil — kalıcıdır. Daha sonra yeniden etkinleştirebilirseniz Devre Dışı Bırak’ı kullanın.

Handler’lar için ipuçları

  1. Hızlıca 2xx döndürün. Ağır iş yapmadan önce 200 OK ile onaylayın — sipariş karşılamayı bir arka plan kuyruğuna atın. Deneme başına zaman aşımı 10 saniyedir; yanıtı bundan daha uzun tutmak bir yeniden denemeyi tetikler. Zaman aşımı platform tarafıdır ve satıcı tarafından yapılandırılamaz — handler’ınız gerçekten daha fazla zamana ihtiyaç duyuyorsa destekle iletişime geçin.
  2. X-Delivery üzerinde dedup yapın (veya Idempotency-Key — aynı değer). 2xx döndürseniz bile, yukarı yönlü bir proxy bağlantıyı düşürebilir ve bir yeniden denemeyi tetikleyebilir; teslim ID’si aynı teslim satırının her yeniden denemesinde stabildir, bu yüzden doğru anahtardır.
  3. Bilinmeyen event tiplerine tolerans gösterin. Yeni event’ler görünebilir; 4xx yerine 200 döndürün ve hiçbir şey yapmayın, yoksa yeniden deneme kuyruğunu doldurursunuz.
  4. X-Delivery’yi iş mantığınızın yanında loglayın. Bir şey ters gittiğinde, bu, bizim tarafımız ile sizin tarafınız arasındaki join anahtarıdır.

Sırada ne var