📊 Analiz 25 Aralık 2025

PayTR Ödeme Süreci

Ödeme yapıldıktan sonra sistemde nasıl işleniyor?

📝 Basit Anlatım (Herkes İçin)

Kullanıcı kredi kartı bilgilerini PayTR'ye girer ve ödeme yapar. PayTR ödemeyi işledikten sonra sistemimize bir bildirim gönderir (webhook).

Sistemimiz bu bildirimi alır ve şu kontrolleri yapar:

  • Ödeme gerçekten PayTR'den mi geliyor? (Güvenlik kontrolü)
  • Tutar doğru mu? (Ödenen miktar sipariş tutarıyla eşleşiyor mu?)
  • Bu ödeme daha önce işlendi mi? (Tekrar kontrolü)

Tüm kontroller başarılıysa:

  • Ödeme durumu "completed" (tamamlandı) olarak işaretlenir
  • Sipariş durumu güncellenir
  • Kullanıcıya email/SMS bildirimi gider
  • Abonelik varsa aktif edilir

🔧 Teknik Detaylar (Geliştiriciler İçin)

📁 İlgili Dosyalar:

Modules/Payment/app/Http/Controllers/PayTRCallbackController.php
Modules/Payment/app/Services/PayTRCallbackService.php
Modules/Payment/app/Models/Payment.php
app/Http/Middleware/VerifyCsrfToken.php (CSRF bypass)

🔗 Callback URL:

POST https://tuufi.com/payment/paytr/callback

📊 Database Tabloları:

payments (Central DB)
subscriptions (Central DB)
shop_orders (Tenant DB - İxtif)

🔄 Adım Adım İşlem Akışı

1

PayTR Webhook (POST Request)

PayTR ödeme sonucunu sisteme bildirir

Gönderilen Veriler:
merchant_oid: "T2PAY202500010" (Sipariş numarası)
status: "success" veya "failed"
total_amount: "9900" (kuruş olarak)
hash: "abc123..." (Güvenlik hash'i)
2

Tenant ID Parse

merchant_oid'den hangi tenant'a ait olduğu belirlenir

T2PAY202500010 → Tenant ID: 2 (İxtif)
T1001PAY202500020 → Tenant ID: 1001 (Muzibu)
Kod: PayTRCallbackController.php:103-119
3

Tenant Context Başlatma

Tenant database'e bağlanılır

tenancy()->initialize($tenant);
Bu noktadan sonra tüm database işlemleri tenant database'de yapılır
4

Payment Kaydı Bulma

merchant_oid kullanılarak payment kaydı bulunur

3 Farklı Yöntemle Arama:
1. gateway_transaction_id ile ara
2. Reconstruct edilmiş payment_number ile ara
3. Stripped merchant_oid ile ara
Kod: PayTRCallbackService.php:38-59
5

Güvenlik Kontrolleri

Duplicate, Hash, ve Tutar kontrolleri

✓ Duplicate Kontrolü:
Payment zaten işlenmiş mi? (completed, failed, refunded)
✓ Hash Doğrulama:
hash = base64(hmac_sha256(
  merchant_oid + salt + status + total_amount,
  merchant_key
))
✓ Tutar Kontrolü:
PayTR'den gelen tutar ile payment tutarı eşleşmeli
6

Payment Güncelleme

Status "success" ise payment completed olarak işaretlenir

payment.status = "completed"
payment.paid_at = now()
payment.gateway_response = $callbackData
Kod: PayTRCallbackService.php:145-149
7

Payable İşlemleri (onPaymentCompleted)

İlgili model'in onPaymentCompleted metodu çağrılır

Payable Model Örnekleri:
🛒 ShopOrder (E-Ticaret):
• Sipariş durumu "pending" → "processing" olur
• Stok düşülür
• Müşteriye "sipariş alındı" maili gider
🔄 Subscription (Abonelik):
• Status "pending_payment" → "active" olur
• started_at, current_period_start tarihleri set edilir
• Kullanıcıya "abonelik aktif" maili gider
Kod: PayTRCallbackService.php:166-169
8

PayTR'ye Yanıt Gönderme

İşlem sonucu PayTR'ye bildirilir

Başarılı: return response("OK", 200);
Hatalı: return response("FAIL: {reason}", 400);
PayTR bu yanıtı almazsa veya hata alırsa webhook'u tekrar gönderir

⚠️ Olası Hata Durumları

❌ Tenant ID Parse Edilemedi
merchant_oid formatı yanlış veya tanımsız
❌ Payment Bulunamadı
Veritabanında eşleşen payment kaydı yok
❌ Hash Doğrulama Hatası
Güvenlik hash'i eşleşmiyor (merchant_key/salt yanlış)
❌ Tutar Uyumsuzluğu
PayTR'den gelen tutar ile payment tutarı farklı

📋 Log Takibi

Tüm PayTR callback işlemleri detaylı loglanır:

📨 PayTR callback received
🔵 PayTR callback: Processing
🔵 Payment update result
🔵 Payable check
✅ onPaymentCompleted called
📨 PayTR callback processed
Log Dosyası: storage/logs/laravel-{date}.log