Replaced `NEXT_PUBLIC_APP_URL` with `APP_URL` in the payment processing logic to ensure proper runtime access. Updated related documentation to clarify the distinction between build-time and runtime environment variables, emphasizing the importance of using `APP_URL` for callback and webhook URLs. Adjusted references in the codebase to reflect this change, enhancing clarity and functionality in the payment flow.
5.4 KiB
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 |
APP_URL |
callback ve yönlendirme URL'lerinin kökü; https ve geçerli SSL şart. Verilmezse BETTER_AUTH_URL'e düşer |
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ı.
Kök adres NEXT_PUBLIC_APP_URL ile verilemez: NEXT_PUBLIC_* değişkenleri
build sırasında koda gömülür, Docker build'i ise .env.production'ı görmez
(.dockerignore .env*'i dışlar). Sonuç, env doğru girilmiş olsa bile imaja
http://localhost:3000 çakılması ve iyzico'nun initialize'ı reddetmesiydi.
Ayrıntı: src/lib/app-url.ts.
Lokal
http://localhost:3000ile uçtan uca test edilemez: iyzico callback adresinden geçerli SSL ister. Sandbox testinde tünel (cloudflared/ngrok) açıpAPP_URL'i o https adrese ayarla.
Akış
baslatOdeme(src/features/odeme/odeme-actions.ts) —orderssatırınıpendingolarak yazar,checkoutFormInitializeçağırır, dönentoken'ı siparişe iliştirir ve kullanıcıyıpaymentPageUrl'e yönlendirir.conversationId=basketId= sipariş id'miz.- Kullanıcı ödemeyi bitirince iyzico
/api/odeme/callbackadresine cross-site POST atar; gövdede yalnızcatokenvardır. SameSite=Lax nedeniyle session çerezi gelmez, bu yüzden kullanıcı token'dan çözülür. odemeyiSonuclandir(src/lib/odeme.ts) iyzico'yacheckoutForm.retrieveile sorar ve krediyi idempotent tanımlar. Kullanıcı 303 ile/odeme/sonuc?siparis=…sayfasına düşer./odeme/sonucself-healing'dir: sipariş hâlâpendingise aynı fonksiyonu tekrar çağırır (callback kaybolduysa kurtarır)./api/odeme/webhookiyzico bildirimini karşılar — sekmesini kapatan ya da fraud incelemesinde bekleyen ödemeler için yedek yol.
Doğruluk kuralları (bunlara dokunurken dikkat)
- Kredi yalnızca
retrieveyanı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. paidgeçişi koşulludur (WHERE status != 'paid'): eşzamanlı callback + sayfa render'ı ikinci kez kredi yazamaz.grantCredits'tekiUNIQUE(reason, ref_id)ikinci katman güvencedir.- Ara durumlar
faileddamgalanmaz.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:1onaylı → kredi verilir.0incelemede →pendingbırakılır (çekim kesinleşmemiştir).-1reddedildi →failed.- Erken
failedkurtarılabilir: geçiş koşulustatus != 'paid'olduğu için yanlışlıklafaileddamgalanmış bir sipariş, iyzico SUCCESS derse yinepaid'e döner. Para çekildiyse kredi mutlaka tanımlanır. - Tutar kontrolü:
paidPricesipariş 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.