Kartlı tahsilatta “parayı geri ver” iki ayrı işlemdir ve ayrım gün sonudur:

İptal: POST /v1/payments/{id}/cancel

Yalnızca succeeded durumdaki ödeme iptal edilebilir; aksi istek 409 payment.invalid_state döner. Banka VoidAsync çağrısını onaylarsa deneme voided, ödeme cancelled olur; payment.cancelled olayı ve webhook’u üretilir. Banka gün sonunu çoktan kapatmışsa birleşik hata kodu poyra.void_window_closed gelir ve mesaj yolu gösterir: “Gün sonu kapanmış — iptal yerine iade oluşturun.” Başarısız iptal girişimi de deftere iz bırakır (payment.void_failed olayı).

İade: POST /v1/refunds

amountMinor göndermezseniz kalanın tamamı iade edilir. Kurallar:
  1. Tavan, karttan çekilen tutardır — taksitli işlemde vade farkı dahil chargedAmountMinor, mal bedeli değil.
  2. Kısmi iadeler birikir: daha önce iade edilen (bekleyen + başarılı) toplamı düşülür; aşan istek 400 refund.amount_exceeds_remaining alır ve mesaj kalan tutarı söyler.
  3. İade kaydı banka çağrısından önce pending olarak yazılır — banka yanıt vermeden süreç çökse bile girişimin izi kalır.
  4. Banka onaylarsa succeeded, reddederse failed olur; her iki sonuç da refund.succeeded / refund.failed webhook’u üretir.
İade ödemenin durumunu değiştirmez: ödeme succeeded kalır, iadeler ref_… kimlikli ayrı kayıtlar olarak yaşar ve GET /v1/refunds/{id} ile okunur. Beklenen para defterinde iade, alacağı azaltan negatif satır olarak görünür.
İade ve iptal panelden de yapılır: ödeme detayındaki her iki form da zorunlu onay kutusu ister ve yalnızca Operasyon ve üzeri rollere açıktır.