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 tipleri
Bölüm başlığı “Event tipleri”| 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
Bölüm başlığı “Payload”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.
İşlem / iade ailesi
Bölüm başlığı “İşlem / iade ailesi”{ "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). |
Payout ailesi
Bölüm başlığı “Payout ailesi”{ "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.
Ödeme linki ailesi
Bölüm başlığı “Ödeme linki ailesi”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. |
Test ailesi
Bölüm başlığı “Test ailesi”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.
Başlıklar (headers)
Bölüm başlığı “Başlıklar (headers)”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 doğrulama
Bölüm başlığı “İmza doğrulama”İ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 requestdeliveryId = 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 üzerindenif 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 sorgulamarkProcessed(deliveryId)return 200Endpoint gereksinimleri
Bölüm başlığı “Endpoint gereksinimleri”- Hızlı
2xxdöndürün. Endpoint’iniz teslimatı 5 saniye içindeHTTP 2xxile 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-Idbirden 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/paymentsile sorgulayın ve kararınızı sorgu sonucuna göre verin.
Yeniden deneme ve teslimat
Bölüm başlığı “Yeniden deneme ve teslimat”-
Başarı:
HTTP 2xx. Teslimat tamamlanmış sayılır. -
Kalıcı hata:
4xxistemci hatası → yeniden denenmez. Endpoint’inizin geçerli teslimatlara2xxdöndürdüğünden emin olun. -
Yeniden deneme:
5xxve 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/paymentssonucuna göre belirleyin.
Yapılandırma
Bölüm başlığı “Yapılandırma”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.