WooCommerce sitelerinde Türk e-ticaretinin varsayılan ödeme altyapısı iyzico ve PayTR. İlk iyzico entegrasyonumu yaparken 5 gün harcadım, sandbox konfigürasyonu, form submit akışı, error handling, webhook doğrulama birer birer mayın gibi patladı. Son projede aynı entegrasyonu 1 günde bitirdim. Bu yazıda nasıl kısalttığımı anlatıyorum.
Sandbox önce, prod sonra
iyzico merchant panelde iki ortam var: sandbox ve production. Sandbox test kart numaraları ile çalışıyor, production gerçek kart. Yeni gelen developer genelde şunu yapıyor: production credentials’ı alıp kod yazıyor, test ediyor, gerçek para hareketi yaratmaya başlıyor.
Her zaman sandbox’ta başlayın:
- iyzico merchant panele login olun
- Sandbox API key + secret key’i alın
IYZICO_ENV=sandboxenvironment variable’ı ile kodunuzu yapılandırın- Sandbox endpoint’i:
sandbox-api.iyzipay.com, production:api.iyzipay.com
Kod tarafında config class’ınız environment’a göre endpoint seçsin. Prod’a geçişte sadece env variable değiştirilir, kod değişmez.
3D Secure: default yap
iyzico’nun iki ödeme akışı var:
- Non-3D: kart bilgisi → charge → sonuç. Basit ama BIN bankası 3D zorunluluğu koyarsa hata alırsınız.
- 3D Secure: kart bilgisi → bankaya redirect → kullanıcı OTP girer → callback’e dönüş → charge complete.
Türkiye’de BDDK regülasyonları nedeniyle 2020 sonrası neredeyse tüm kartlar 3D gerektiriyor. Non-3D yolunu implement etmenin kazancı yok, zahmeti var. Default 3D Secure başlayın.
3D akışı daha karmaşık ama production-ready:
- Client’tan kart bilgisi alırsınız (iyzico’nun checkout form’u veya kendi form’unuz)
initialize3DSendpoint’ine POST edersiniz- iyzico HTML içeriği döner (bankayla kullanıcının etkileşime geçmesi için iframe)
- HTML’i kullanıcıya render edersiniz
- Kullanıcı OTP girer, banka callbackURL’inize POST eder
auth3DSile ödemeyi finalize edersiniz
Webhook’suz yapmayın
iyzico webhook’ları (callback URL’ler) güvenilir. Callback URL’ine gelen request başarısız olursa iyzico 24 saate kadar retry ediyor. Bu retry discipline olmadan kullanıcı ödemesini kaybedebilir, webhook kaybolur.
Webhook handler’ınız:
- Signature doğrula. iyzico
Authorizationheader’ında HMAC-SHA1 imza gönderiyor.random-string + request-body‘nin secret key ile HMAC’ini hesaplayıp karşılaştırın. Manuel olmayan yerde güvensiz değilsiniz. - Idempotent ol. Aynı webhook 2 kere gelebilir.
conversationIdile daha önce işlenmiş mi kontrol edin. - Hızlı cevap ver. 200 OK dönmeden işin bitmesini beklemeyin. Webhook’u queue’ya atıp async işleyin, 200 hemen dönsün. 30 saniye timeout var.
- Logla. Her webhook’u log’a yazın. Destek ticket’larında bu logları göreceksiniz.
Error code’ları tanıyın
iyzico error code’ları çok fazla. Her biri için farklı kullanıcı mesajı göstermek fark yaratıyor.
Yaygın error’lar:
10005: Geçersiz kart numarası → “Kart numaranızı kontrol edin”10034: Bakiye yetersiz → “Kartınızın bakiyesi yetersiz”10051: Yetersiz bakiye / limit → “Bankanızla iletişime geçin”10057: 3D şifre hatalı → “SMS şifreyi hatalı girdiniz”10201: İşlem reddedildi → “İşleminiz onaylanmadı, farklı bir kart deneyin”fraud: Fraud suspect → “Güvenlik kontrolünde takıldınız, desteğe yazın”
Bütün error’ları “Ödeme başarısız” ile geçmek kullanıcıyı terkediyor. Spesifik mesaj vermek retry oranını arttırıyor.
BIN kontrolü: UX kazancı
iyzico BIN inquiry endpoint’i var. Kart numarasının ilk 6 hanesini gönderirsiniz, size bankayı, kart tipini (debit/credit), taksit sayısını döner.
Bunu kullanarak:
- Taksit seçeneklerini o bankaya göre göster
- Debit kartta “taksit yok” uyarısı
- Yabancı kart ise TRY’dan dönüştürme bilgisi
UX tarafında küçük ama fark yaratan detay. Kullanıcı kartını yazar yazmaz taksit seçenekleri dinamik update ediyor.
Retry pattern’ı
Odeme başarısız olunca doğru davranışı belirtmek kritik:
- Network error / timeout: Aynı request’i retry edin (idempotency key ile). Ödeme gerçekleşti mi bilmiyorsanız iyzico’dan “retrieve” endpoint ile durumu sorgulayın.
- User error (yanlış kart, yanlış OTP): Retry, farklı kart dene imkanı
- Bank decline: Retry, başka kart öner (retry aynı kart anlamlı değil)
- Fraud: Kullanıcıyı uyar, manuel inceleme yönlendir
Yanlış pattern: herhangi bir error’da retry. Bu çok kötü deneyim yaratır, fraud limit’i tetikler, kullanıcı hesabı bloke olabilir.
WooCommerce plugin vs custom
iyzico’nun resmi WooCommerce plugin’i var. Temel kullanım için yeterli: checkout’ta ödeme, order status güncelleme, webhook handling.
Custom implementation gerekenler:
- Marketplace (çoklu satıcı): sub-merchant akışı
- Subscription billing: recurring charge with card on file
- Custom checkout UX: iyzico’nun form’unu değil kendi form’unuzu
- B2B fatura-based ödeme
Resmi plugin bu senaryoları karşılamıyor. Custom implement etmek gerekiyor. iyzico’nun PHP SDK’sı (iyzico/iyzipay-php composer paketi) tabanı iyi.
Ortak pitfall’lar
Locale problemi. API request’inde locale alanı var. tr veya en. Yanlış gönderirseniz iyzico error mesajlarını İngilizce veriyor, kullanıcı anlamıyor.
Price formatı. iyzico String bekliyor ama ondalık ayraç . olmalı. PHP number_format($price, 2, '.', '') kullanın.
TCKN/vergi kimliği alanları. B2B satışlarda TCKN veya vergi kimlik gerekli. Fraud score düşüyor, konvertasyon artıyor.
IP address alanı. Request’te userIp alanına gerçek IP gönderin. Fraud engine bu bilgiyi kullanıyor.
Son tavsiye
5 günlük entegrasyon 1 güne iniyor, çünkü şunları biliyorsunuz:
- Sandbox ile başla
- 3D Secure default
- Webhook + signature verification
- Error code-specific mesajlar
- BIN inquiry ile UX
- Retry pattern doğru
Bir sonraki projede iyzico entegrasyonu yapacaksanız bu listeyi önceden yazın, ağır kayıplardan kaçının.