İçeriğe geç

Webhooks

Lydia Gate; bir ödeme, iade, payout kalemi ya da ödeme linki durumu değiştikçe endpoint’inize bir webhook gönderir. Payload minimaldir: yalnızca olay tipi ve ilgili kaynağın referansı (aileye göre paymentCode, payoutBatchId+partnerId ya da paymentLinkId). Webhook bir tetikleyicidir, sonucun kendisi değildir; detayı ve nihai durumu ilgili sorgu ile çekersiniz — işlem/iade için GET /v1/payments, ödeme linki için GET /v1/payment-links/{id}; payout detayını merchant panelinizden takip edersiniz.

Event tipi Aile Ne zaman gönderilir
payment.captured İşlem Tahsilat onaylandı (ödeme captured).
payment.failed İşlem 3D ya da tahsilat reddedildi (ödeme failed).
payment.expired İşlem Ödeme süresi doldu / 3D yarıda bırakıldı (ödeme expired).
refund.approved İşlem Bir iade ya da iptal onaylandı.
refund.declined İşlem Bir iade ya da iptal reddedildi.
payout.paid_out Payout Bir payout kalemi partnere ödendi (bağlı hakedişler PAID_OUT’a geçer).
payout.failed Payout Bir payout kalemi başarısız oldu (fon partnere ulaşmadı; ops/insan çözer).
payment_link.completed Ödeme linki Bir ödeme linkine bağlı tahsilat onaylandı (link completed).
payment_link.expired Ödeme linki Bir ödeme linkinin süresi doldu (link expired).
webhook.test Test Panelde “Test webhook gönder” tetiklendiğinde gönderilir; iş verisi taşımaz — entegrasyonunuzu (URL erişimi + imza doğrulama) canlı veri olmadan sınamak içindir.

Banka ham olayları (yetkilendirme adımları, ara durumlar) webhook olarak gönderilmez. Ödeme durumlarının tam listesi için Ödeme Yaşam Döngüsü; ödeme linki durumları için Ödeme Linkleri.

Payload, kesin sonucu veya tutarı taşımaz; bunlar kasıtlıdır. Ham banka yanıtı, kart verisi ya da başka bir hassas alan içermez. Karar vermek için her zaman ilgili kaynağı sorgulayın. Alan seti aileye göre değişir.

{
"id": "whd_a1b2c3",
"type": "payment.captured",
"paymentCode": "pay_7Hq2bL",
"occurredAt": "2026-06-14T12:05:11Z"
}
Alan Açıklama
id Teslimat kimliği (delivery-id). Idempotency için kullanılır.
type Event tipi (yukarıdaki tablo).
paymentCode İlgili ödemenin kodu; detayı sorgulamak için kullanın.
occurredAt Olayın gerçekleştiği an (UTC, ISO 8601).
{
"id": "whd_9f3e21",
"type": "payout.paid_out",
"payoutBatchId": "pob_4c7a19",
"partnerId": "prt_8b2d4f",
"occurredAt": "2026-06-15T09:02:33Z"
}
Alan Açıklama
payoutBatchId İlgili payout partisinin (batch) kimliği.
partnerId İlgili partnerin kimliği.

paymentCode bu ailenin gövdesinde yer almaz; payout, tek bir ödeme değil bir partner×parti hakedişi seviyesindedir. Detayını merchant panelinizden takip edersiniz.

payment_link.completed / payment_link.expired gövdesi paymentCode yerine paymentLinkId taşır:

{
"id": "whd_c9f01e",
"type": "payment_link.completed",
"paymentLinkId": "01J9K5QATN6M1PXG7VYSD3HZWB",
"occurredAt": "2026-06-21T09:15:40Z"
}
Alan Açıklama
paymentLinkId İlgili ödeme linkinin kalıcı kimliği; detayını GET /v1/payment-links/{id} ile sorgulayın.

webhook.test gövdesi yalnızca id, type ve occurredAt taşır; iş verisine referans yoktur:

{
"id": "whd_1a2b3c",
"type": "webhook.test",
"occurredAt": "2026-06-15T09:02:33Z"
}

Panelde “Test webhook gönder” ile tetiklenir; entegrasyonunuzu (URL erişimi + imza doğrulama) canlı veri olmadan sınamak içindir.

Her teslimat üç imza başlığı taşır:

Başlık Açıklama
X-Paytalya-Signature sha256=<hex>: ham (raw) istek gövdesinin HMAC-SHA256 imzası.
X-Paytalya-Timestamp Olayın gerçekleştiği anın (occurredAt) epoch saniyesi; gövdedeki occurredAt ile birebir aynı andır. Gönderim anı değildir: aynı olay yeniden denendiğinde bu değer sabit kalır (ilk occurredAt). İmzaya dahil değildir. Bu yüzden “belirli bir süreden eski istekleri reddet” gibi bir kontrol kurmayın; yeniden denemeler saatler sonra bile aynı eski timestamp’i taşıdığından meşru teslimatları reddedersiniz. Replay koruması için timestamp yerine X-Paytalya-Delivery-Id ile idempotency kullanın.
X-Paytalya-Delivery-Id Teslimat kimliği (gövdedeki id ile aynı). Aynı teslimat tekrar gelebilir; idempotency için kullanın.

İmzada kullanılan secret, API anahtarından ayrı bir webhook secret’ıdır ve onboarding sırasında size verilir. Bu secret’ı asla loglamayın, istemciye göndermeyin ya da reponuzda saklamayın.

İmza, yalnızca ham (raw) istek gövdesi üzerinden hesaplanır; timestamp imzaya dahil edilmez, herhangi bir birleştirme yapılmaz. Doğrulamayı sabit-zamanlı karşılaştırma ile yapın (zamanlama saldırılarına karşı). Dil-agnostik sözde-kod:

rawBody = exact bytes received on the request
deliveryId = header["X-Paytalya-Delivery-Id"]
expected = "sha256=" + lowercase_hex( HMAC_SHA256(webhookSecret, rawBody) )
# 1) imza eşleşmeli (sabit-zamanlı karşılaştırma): yalnızca ham gövde üzerinden
if not constantTimeEquals(expected, header["X-Paytalya-Signature"]):
return 400
# 2) idempotency + replay koruması: bu delivery-id daha önce işlendiyse yeniden işleme
# (imzadan BAĞIMSIZ; timestamp'e göre "eski" reddi YAPMAYIN — retry'ları öldürür)
if alreadyProcessed(deliveryId):
return 200 # sessizce onayla; iş mantığını tekrar çalıştırma
# imza geçerli → 2xx döndür, sonra ödemeyi GET ile sorgula
markProcessed(deliveryId)
return 200
  • Hızlı 2xx döndürün. Endpoint’iniz teslimatı 5 saniye içinde HTTP 2xx ile yanıtlamalıdır; aksi halde teslimat timeout sayılır ve yeniden denenir. Ağır işi (sorgu, sipariş güncelleme) yanıttan sonra asenkron yapın.
  • İmzayı doğrulayın. Yukarıdaki adımlarla imzayı doğrulamadan gövdeye güvenmeyin.
  • Idempotent olun. Aynı X-Paytalya-Delivery-Id birden fazla gelebilir (retry’da delivery-id sabittir). İşleme mantığınız aynı teslimatı iki kez almaya dayanıklı olmalıdır.
  • Tetikleyici olarak kullanın. Bildirim gelince ödemenin detayını GET /v1/payments ile sorgulayın ve kararınızı sorgu sonucuna göre verin.
  • Başarı: HTTP 2xx. Teslimat tamamlanmış sayılır.

  • Kalıcı hata: 4xx istemci hatası → yeniden denenmez. Endpoint’inizin geçerli teslimatlara 2xx döndürdüğünden emin olun.

  • Yeniden deneme: 5xx ve timeout → exponential backoff ile tekrar denenir:

    30 sn → 2 dk → 10 dk → 1 sa → 6 sa

    İlk teslimattan itibaren 24 saat boyunca başarı alınamazsa teslimat kalıcı olarak bırakılır.

  • Sıra garantisi yok: Olaylar gönderildikleri sırada gelmeyebilir. Durumu webhook tipine değil, GET /v1/payments sonucuna göre belirleyin.

Webhook URL’iniz ve secret’ınız hesabınıza onboarding sırasında tanımlanır. Webhook URL’i tanımlı değilse hiçbir bildirim gönderilmez; bu durumda ödeme durumlarını yalnızca GET /v1/payments ile takip edin.