İçeriğe geç

Webhooks

Paytalya, bir ödeme ya da iade durumu değiştikçe endpoint’inize bir webhook gönderir. Payload minimaldir: yalnızca olay tipi + paymentCode. Webhook bir tetikleyicidir, sonucun kendisi değildir; detayı ve nihai durumu GET /v1/payments ile çekersiniz.

Event tipiNe zaman gönderilir
payment.capturedTahsilat onaylandı (ödeme captured).
payment.failed3D ya da tahsilat reddedildi (ödeme failed).
payment.expiredÖdeme süresi doldu / 3D yarıda bırakıldı (ödeme expired).
refund.approvedBir iade ya da iptal onaylandı.
refund.declinedBir iade ya da iptal reddedildi.

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ü.

{
"id": "whd_a1b2c3",
"type": "payment.captured",
"paymentCode": "pay_7Hq2bL",
"occurredAt": "2026-06-14T12:05:11Z"
}
AlanAçıklama
idTeslimat kimliği (delivery-id). Idempotency için kullanılır.
typeEvent tipi (yukarıdaki tablo).
paymentCodeİlgili ödemenin kodu; detayı sorgulamak için kullanın.
occurredAtOlayın gerçekleştiği an (UTC, ISO 8601).

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 ödemeyi sorgulayın.

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

BaşlıkAçıklama
X-Paytalya-Signaturesha256=<hex>: ham (raw) istek gövdesinin HMAC-SHA256 imzası.
X-Paytalya-TimestampOlayın gerçekleştiği anın epoch saniyesi (gövdedeki occurredAt ile aynı an, saniye biçiminde). İsteğe bağlı replay sertleştirmesi içindir; imzaya dahil değildir. 5 dakikadan eski istekleri reddedebilirsiniz (replay koruması), ama bu kontrol imzadan bağımsızdır.
X-Paytalya-Delivery-IdTeslimat 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
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) (opsiyonel) replay sertleştirmesi: çok eski olayları reddet (imzadan BAĞIMSIZ)
timestamp = header["X-Paytalya-Timestamp"]
if abs(now() - timestamp) > 5 minutes:
return 400
# imza geçerli → 2xx döndür, sonra ödemeyi GET ile sorgula
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ı ve zaman damgasını 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.