Files
kolaytercih/docs/odeme/iyzico.md
bilalgursen 08419e6d1c
All checks were successful
Deploy / deploy (push) Successful in 7m0s
chore: update iyzico integration and enhance payment processing logic
Refactored the iyzico payment integration to improve the handling of payment callbacks and order status updates. Added signature validation for responses to ensure data integrity. Enhanced the `initializeCheckoutForm` function to include buyer's name and surname, and updated the order schema to enforce unique constraints on iyzico tokens. Improved error handling and logging for payment processing, ensuring better tracking of payment states and issues. Updated the app database to reflect these changes.
2026-08-11 00:30:53 +03:00

5.1 KiB
Raw Blame History

iyzico ödeme entegrasyonu

Ödeme akışı iyzico Checkout Form (CF) üzerinden yürür: kart bilgisi hiçbir zaman bize ulaşmaz, kullanıcı iyzico'nun barındırdığı ödeme sayfasına gider.

Ortam değişkenleri

Değişken Açıklama
IYZICO_API_KEY Merchant Portal → Ayarlar → API anahtarları
IYZICO_SECRET_KEY Aynı ekran. İmza doğrulamasında da kullanılır
IYZICO_BASE_URL Sandbox: https://sandbox-api.iyzipay.com · Canlı: https://api.iyzipay.com
NEXT_PUBLIC_APP_URL callback ve webhook URL'lerinin kökü; https ve geçerli SSL şart

IYZICO_BASE_URL verilmezse sandbox'a düşülür. Prod'da bu durum log'a uyarı basar — canlıya çıkarken bu satır mutlaka ayarlanmalı.

Lokal http://localhost:3000 ile uçtan uca test edilemez: iyzico callback adresinden geçerli SSL ister. Sandbox testinde tünel (cloudflared/ngrok) açıp NEXT_PUBLIC_APP_URL'i o https adrese ayarla.

Akış

  1. baslatOdeme (src/features/odeme/odeme-actions.ts) — orders satırını pending olarak yazar, checkoutFormInitialize çağırır, dönen token'ı siparişe iliştirir ve kullanıcıyı paymentPageUrl'e yönlendirir. conversationId = basketId = sipariş id'miz.
  2. Kullanıcı ödemeyi bitirince iyzico /api/odeme/callback adresine cross-site POST atar; gövdede yalnızca token vardır. SameSite=Lax nedeniyle session çerezi gelmez, bu yüzden kullanıcı token'dan çözülür.
  3. odemeyiSonuclandir (src/lib/odeme.ts) iyzico'ya checkoutForm.retrieve ile sorar ve krediyi idempotent tanımlar. Kullanıcı 303 ile /odeme/sonuc?siparis=… sayfasına düşer.
  4. /odeme/sonuc self-healing'dir: sipariş hâlâ pending ise aynı fonksiyonu tekrar çağırır (callback kaybolduysa kurtarır).
  5. /api/odeme/webhook iyzico bildirimini karşılar — sekmesini kapatan ya da fraud incelemesinde bekleyen ödemeler için yedek yol.

Doğruluk kuralları (bunlara dokunurken dikkat)

  • Kredi yalnızca retrieve yanıtına göre tanımlanır. Ne callback gövdesine ne webhook gövdesine güvenilir; ikisi de sadece "iyzico'ya tekrar sor" tetikleyicisidir.
  • paid geçişi koşulludur (WHERE status != 'paid'): eşzamanlı callback + sayfa render'ı ikinci kez kredi yazamaz. grantCredits'teki UNIQUE(reason, ref_id) ikinci katman güvencedir.
  • Ara durumlar failed damgalanmaz. INIT_THREEDS, CALLBACK_THREEDS, PENDING_CREDIT, INIT_BANK_TRANSFER … ödemenin sonuçlanmadığı anlamına gelir; damgalarsak dakikalar sonra SUCCESS'e dönen ödemede kredi kaybolur.
  • fraudStatus: 1 onaylı → kredi verilir. 0 incelemede → pending bırakılır (çekim kesinleşmemiştir). -1 reddedildi → failed.
  • Erken failed kurtarılabilir: geçiş koşulu status != 'paid' olduğu için yanlışlıkla failed damgalanmış bir sipariş, iyzico SUCCESS derse yine paid'e döner. Para çekildiyse kredi mutlaka tanımlanır.
  • Tutar kontrolü: paidPrice sipariş tutarıyla eşleşmiyorsa kredi otomatik tanımlanmaz, log'a düşer.

İmza doğrulaması

iyzico yanıtlarında HMAC-SHA256 signature döner; alanlar : ile birleşir ve fiyatlarda sondaki sıfırlar atılır (299.00 → 299). Tümü src/lib/iyzico.ts içinde:

Yer Alan sırası
initImzaDurumu conversationId:token
retrieveImzaDurumu paymentStatus:paymentId:currency:basketId:conversationId:paidPrice:price:token
webhookImzaDurumu (V3, HPP) HMAC(secret, secret + iyziEventType + iyziPaymentId + token + paymentConversationId + status)

Karar kuralı: imza tutmuyorsa işlem reddedilir; imza alanı hiç yoksa (hesapta kapalıysa) akış sürer ve log'a uyarı düşer — retrieve zaten kimliği doğrulanmış sunucu-sunucu çağrısıdır, bu yüzden imza yokluğu ödemeyi bloklamaz.

Webhook kurulumu

Merchant Portal → Ayarlar → İşyeri Ayarları → İşyeri Bildirimleri → https://<alan-adı>/api/odeme/webhook (HTTPS zorunlu).

X-IYZ-SIGNATURE-V3 başlığının gönderilmesi ayrıca aktifleştirilmelidir (entegrasyon@iyzico.com). Aktif değilse başlık gelmez; route yine güvenlidir çünkü durumu gövdeden değil retrieve'den okur.

iyzico 2xx alana kadar 15 dakika arayla 3 kez dener — bu yüzden işleyemediğimiz durumlarda bile 200 döneriz, yalnızca geçersiz imzada 401.

Test

Sandbox test kartları: https://docs.iyzico.com/en/add-ons/test-cards. Son kullanma tarihi gelecekte olmak kaydıyla SKT ve CVV serbesttir.

Dev panelinden (src/components/dev/dev-panel.tsx) iyzico'ya hiç gitmeden "ödenmiş sahte sipariş" üretilebilir — sonuç ekranını denemek için.

Kaynaklar