Payment Gateway Nedir, Backend Tarafında Nasıl Tasarlanır?
Payment Gateway mimarisinin backend tarafındaki temel bileşenleri, transaction yönetimi, idempotency, hata yönetimi, loglama ve entegrasyon akışları.
Payment Gateway, ödeme sistemlerinde uygulama ile banka, POS sağlayıcısı veya ödeme kuruluşu arasında konumlanan merkezi entegrasyon katmanıdır.
Basit bir bakışla gateway, ödeme isteğini alır, ilgili sağlayıcıya yönlendirir ve sonucu uygulamaya döner. Fakat gerçek sistemlerde konu bundan daha geniştir. Finansal işlem üreten yapılarda transaction durumu, hata senaryoları, tekrar deneme mekanizmaları, idempotency, loglama, mutabakat ve operasyonel izlenebilirlik tasarımın temel parçalarıdır.
Bu yazıda Payment Gateway yapısını özellikle backend geliştirici gözüyle ele alıyorum.
Payment Gateway Ne İşe Yarar?
Bir uygulama doğrudan her banka veya POS sağlayıcısına bağlanmak yerine gateway katmanı üzerinden iletişim kurabilir. Böylece farklı sağlayıcıların teknik detayları uygulama kodundan ayrıştırılır.
Gateway katmanı genellikle şu sorumlulukları üstlenir:
- Ödeme başlatma
- Ödeme doğrulama
- POS / banka / ödeme kuruluşu seçimi
- İşlem durumunun yönetilmesi
- Hata kodlarının normalize edilmesi
- İptal, iade ve sorgulama akışları
- Loglama ve izlenebilirlik
- Mutabakat süreçlerine veri sağlama
- Operasyonel destek için anlamlı kayıt üretme
Bu yapı doğru tasarlanırsa uygulama tarafı sadeleşir, sağlayıcı değişiklikleri daha kontrollü yönetilir ve ödeme akışları merkezi olarak izlenebilir hale gelir.
Temel Mimari Bileşenler
Backend tarafında bir Payment Gateway genellikle aşağıdaki bileşenlerden oluşur.
1. Payment API
Uygulama veya farklı servisler ödeme işlemini bu API üzerinden başlatır.
Örnek endpointler:
POST /api/payments
GET /api/payments/{transactionId}
POST /api/payments/{transactionId}/cancel
POST /api/payments/{transactionId}/refund
Bu API, dış dünyadan gelen isteği doğrular ve işlem akışını başlatır.
2. Provider Adapter Katmanı
Her banka veya POS sağlayıcısının API yapısı farklı olabilir. Bir sağlayıcı SOAP kullanırken diğeri REST kullanabilir. Alan adları, hata kodları, response formatı ve güvenlik yapısı değişebilir.
Bu nedenle gateway içinde adapter yaklaşımı kullanmak mantıklıdır.
IPaymentProvider
├── BankAProvider
├── BankBProvider
├── PosXProvider
└── PaymentInstitutionYProvider
Bu sayede ana ödeme akışı sağlayıcı detaylarına bağımlı kalmaz.
3. Transaction Store
Her ödeme işlemi mutlaka kalıcı olarak takip edilmelidir.
Transaction kaydında genellikle şu bilgiler bulunur:
- TransactionId
- OrderId / ExternalId
- Amount
- Currency
- Provider
- Status
- Request payload özeti
- Response payload özeti
- Provider transaction id
- Hata kodu ve hata mesajı
- CreatedAt / UpdatedAt
Finansal sistemlerde “istek atıldı ama cevap alınamadı” gibi durumlar sık yaşanabilir. Bu yüzden işlem durumunu sadece response’a göre değil, transaction kaydına göre yönetmek gerekir.
4. Status Management
Ödeme işlemlerinde durum yönetimi çok önemlidir.
Örnek durumlar:
Created
Pending
ProviderRequested
Success
Failed
Cancelled
Refunded
Unknown
Özellikle Unknown gibi ara durumlar önemlidir. Çünkü dış servise istek gönderilmiş ama timeout alınmış olabilir. Bu durumda işlem gerçekten başarısız mı, yoksa sağlayıcı tarafında başarılı mı oldu, ayrıca sorgulanmalıdır.
Idempotency Neden Önemlidir?
Ödeme sistemlerinde aynı isteğin iki kere çalışması ciddi problemlere neden olabilir. Kullanıcı butona iki kez basabilir, frontend retry yapabilir, network kopabilir veya servis tekrar denenebilir.
Bu yüzden ödeme başlatma akışında idempotency mantığı kurulmalıdır.
Örnek yaklaşım:
ExternalId + MerchantId + Amount
veya
Idempotency-Key
Aynı işlem anahtarıyla tekrar istek geldiğinde sistem yeni ödeme üretmek yerine mevcut transaction sonucunu dönmelidir.
Basit akış:
1. İstek geldi
2. Idempotency key kontrol edildi
3. Aynı key ile kayıt varsa mevcut sonuç döndü
4. Yoksa yeni transaction oluşturuldu
5. Provider çağrısı yapıldı
6. Sonuç kaydedildi
Bu yapı mükerrer ödeme riskini azaltır.
Hata Yönetimi
Payment Gateway tarafında hata yönetimi sadece exception yakalamak değildir. Teknik hata ile business hata ayrılmalıdır.
Örnek hata türleri:
- Timeout
- Connection error
- Authentication error
- Invalid card
- Insufficient funds
- Provider system error
- Duplicate transaction
- Invalid amount
- Unknown response
Sağlayıcıdan gelen hata kodları normalize edilmelidir.
Örneğin:
Provider A: 51 → Insufficient funds
Provider B: 1004 → Insufficient funds
Provider C: INSUFFICIENT_BALANCE → Insufficient funds
Gateway kendi içinde ortak hata modeli kullanırsa, uygulama tarafı sağlayıcı bazlı karmaşadan etkilenmez.
Retry Mekanizması
Retry ödeme sistemlerinde dikkatli kullanılmalıdır.
Her hata retry edilebilir değildir. Örneğin kart limiti yetersizse tekrar denemek anlamsızdır. Ama network timeout veya geçici servis hatalarında kontrollü retry düşünülebilir.
Ancak ödeme üreten işlemlerde retry yapmadan önce şu sorular sorulmalıdır:
- Provider tarafında işlem oluşmuş olabilir mi?
- İşlem sorgulanabiliyor mu?
- Aynı external id ile tekrar istek güvenli mi?
- Provider idempotency destekliyor mu?
- Timeout sonrası status inquiry yapılmalı mı?
Çoğu durumda ödeme isteğini körlemesine tekrar göndermek yerine önce işlem sorgulama akışı çalıştırmak daha güvenlidir.
Loglama ve İzlenebilirlik
Payment Gateway sistemlerinde loglama operasyonel açıdan kritik öneme sahiptir.
Her işlem için izlenebilir olması gereken bilgiler:
- CorrelationId
- TransactionId
- Provider
- Request zamanı
- Response zamanı
- Duration
- Status
- Hata kodu
- Hata mesajı
- Provider transaction id
Loglar sadece geliştiriciler için değil, operasyon ekipleri, müşteri destek ve mutabakat süreçleri için de kullanılır.
Loglama yapılırken hassas veriler maskelenmelidir. Kart numarası, CVV, kişisel veri veya güvenlik bilgileri açık şekilde loglanmamalıdır.
Transaction Yönetimi
Ödeme işleminde veritabanı transaction’ı ile finansal transaction aynı şey değildir.
Veritabanı transaction’ı kısa tutulmalıdır. Dış servis çağrısı yapılırken uzun süre açık DB transaction tutmak lock, timeout ve performans problemlerine neden olabilir.
Daha sağlıklı yaklaşım:
1. Transaction kaydını Created olarak oluştur
2. DB transaction kapat
3. Provider çağrısını yap
4. Sonucu ayrı update işlemiyle kaydet
5. Gerekirse status inquiry veya reconciliation akışına bırak
Bu yapı özellikle yüksek trafikli sistemlerde daha sürdürülebilir olur.
Mutabakat ve Sorgulama Akışları
Payment Gateway sadece ödeme başlatma katmanı değildir. İşlem sonrasındaki sorgulama ve mutabakat süreçleri de mimarinin önemli parçasıdır.
Özellikle şu durumlar için sorgulama mekanizması gerekir:
- Timeout sonrası işlem durumu bilinmiyor
- Provider response eksik geldi
- Kullanıcı ödeme sonucunu göremedi
- Operasyon ekibi işlem durumunu doğrulamak istiyor
- Gün sonu mutabakat farkı oluştu
Bu nedenle payment inquiry veya transaction status check endpointleri gateway tasarımında mutlaka düşünülmelidir.
.NET Backend Tarafında Tasarım Önerisi
.NET tarafında sade bir yapı şu şekilde kurulabilir:
Application
├── PaymentService
├── PaymentProviderResolver
├── PaymentStatusService
└── PaymentLogService
Infrastructure
├── Providers
│ ├── BankAProvider
│ ├── BankBProvider
│ └── PosProvider
├── Persistence
└── ExternalClients
Provider adapter yapısı, ana ödeme akışını sağlayıcı detaylarından ayırır. Böylece yeni bir banka veya POS sağlayıcısı eklendiğinde ana iş akışı bozulmadan yeni adapter geliştirilebilir.
Sonuç
Payment Gateway tasarlamak yalnızca “ödeme isteğini bankaya gönderip cevap almak” değildir.
İyi bir gateway yapısı şu konuları birlikte ele almalıdır:
- Sağlayıcı bağımsız mimari
- Transaction state yönetimi
- Idempotency
- Hata kodu normalize etme
- Kontrollü retry
- Status inquiry
- Loglama ve izlenebilirlik
- Hassas veri güvenliği
- Mutabakat desteği
Backend geliştirici açısından en kritik nokta, finansal işlem akışını güvenli, izlenebilir ve tekrar çalıştırılabilir şekilde tasarlamaktır.