Türkiye'de bir e-ticaret sitesi veya SaaS ürünü kuruyorsanız erken ya da geç ödeme alma sorununa çözüm bulmanız gerekir. iyzico, Node.js/Express tabanlı uygulamalara entegre edilebilen, kredi kartı + 3D Secure + havale/EFT destekli bir ödeme altyapısıdır. Bu rehberde sandbox hesabı açmaktan canlı webhook doğrulamasına kadar gerçek bir entegrasyonu adım adım anlatıyoruz.
İlgili içerikler: REST API güvenlik rehberi · OAuth 2.0 ve OIDC · API rate limiting stratejileri
iyzico Nedir?
iyzico, Türkiye merkezli bir ödeme hizmet sağlayıcısıdır (PSP). Kredi/banka kartı, 3D Secure, BKM Express, havale/EFT, taksit ve pazaryeri (marketplace) alt üye işyeri dağıtımı gibi ödeme yöntemlerini tek bir API üzerinden sunar. PHP, Node.js, Python, Java ve .NET için resmi SDK'ları vardır; Shopify, WooCommerce, Magento gibi hazır platformlara da eklenti olarak kurulabilir.
API Key ve Secret Key Nasıl Alınır?
iyzico Merchant Panel'e kayıt olduktan sonra Ayarlar > API Entegrasyonu bölümünden hem sandbox (test) hem de canlı (production) ortam için ayrı apiKey ve secretKey çifti alırsınız. Bu iki ortamın anahtarları birbirinden tamamen bağımsızdır — sandbox anahtarıyla canlı işlem yapamazsınız ve bu kasıtlıdır.
.env dosyasında saklayın ve .gitignore'a ekleyin — bu, iyzico API'sinin imza doğrulaması gerektiren her isteğinde kullandığınız tek gizli bilgidir.Sandbox ile Geliştirme
Geliştirme ve test sürecinin tamamı sandbox ortamında (https://sandbox-api.iyzipay.com) yapılır; gerçek kartlarla işlem sandbox'ta desteklenmez. iyzico, başarılı ödeme, yabancı kart ve çeşitli hata senaryolarını simüle eden onlarca test kartı sağlar — kodunuzu canlıya almadan önce hem mutlu yol hem hata yollarını test edebilirsiniz.
Node.js ile Kurulum
npm install iyzipay
Resmi Node.js SDK'sını kur
Örnek: npm install iyzipay --save
const Iyzipay = require('iyzipay');
const iyzipay = new Iyzipay({
apiKey: process.env.IYZICO_API_KEY,
secretKey: process.env.IYZICO_SECRET_KEY,
uri: process.env.IYZICO_BASE_URL // sandbox: https://sandbox-api.iyzipay.com
});
Ödeme Formu (Checkout Form) ile Entegrasyon
En hızlı ve PCI-DSS yükünü en çok azaltan yöntem Ödeme Formu'dur: kart bilgileri hiçbir zaman sizin sunucunuza dokunmaz, iyzico'nun barındırdığı güvenli forma yönlendirilir. Sunucu tarafında yalnızca bir token üretir, kullanıcıyı bu token ile forma yönlendirirsiniz.
const request = {
locale: Iyzipay.LOCALE.TR,
conversationId: orderId, // kendi sipariş ID'niz
price: '100.0', // sepet toplamı
paidPrice: '100.0', // tahsil edilecek tutar (kampanya/indirim sonrası)
currency: Iyzipay.CURRENCY.TRY,
basketId: 'B' + orderId,
paymentGroup: Iyzipay.PAYMENT_GROUP.PRODUCT,
callbackUrl: 'https://example.com/odeme/callback',
buyer: {
id: String(user.id),
name: user.firstName,
surname: user.lastName,
gsmNumber: user.phone,
email: user.email,
identityNumber: user.tckn, // TC kimlik no zorunlu alandır
ip: req.ip,
city: user.city,
country: 'Turkey'
},
basketItems: cart.items.map(i => ({
id: String(i.id),
name: i.name,
category1: i.category,
itemType: Iyzipay.BASKET_ITEM_TYPE.PHYSICAL,
price: String(i.price)
}))
};
iyzipay.checkoutFormInitialize.create(request, (err, result) => {
if (err || result.status !== 'success') return res.status(400).json({ error: result?.errorMessage });
res.json({ checkoutFormContent: result.checkoutFormContent, token: result.token });
});
Dönen checkoutFormContent bir <script> bloğudur; sayfanızda boş bir <div> içine basarak gömersiniz. Kullanıcı ödemeyi tamamladığında iyzico, belirttiğiniz callbackUrl'e yönlendirir; o adreste token ile sonucu sorgularsınız:
iyzipay.checkoutForm.retrieve({
locale: Iyzipay.LOCALE.TR,
conversationId: orderId,
token: req.body.token
}, (err, result) => {
if (result.paymentStatus === 'SUCCESS') {
// siparişi 'ödendi' olarak işaretle, faturayı oluştur
}
});
3D Secure Akışı
Ödeme Formu kullandığınızda 3D Secure akışı iyzico tarafından otomatik yönetilir; kendi kart formunuzu (API ile direkt ödeme) kullanıyorsanız iki aşamalı bir akış uygularsınız: önce threeds.initialize ile kullanıcıyı bankanın 3D doğrulama sayfasına yönlendirirsiniz, kullanıcı SMS/şifre ile onayladıktan sonra banka sizi callbackUrl'e geri yönlendirir ve threeds.create çağrısıyla ödemeyi tamamlarsınız. Çoğu yeni entegrasyon için Ödeme Formu'nun bu karmaşıklığı sizin yerinize yönetmesi tercih edilir.
Webhook ile Ödeme Bildirimi Alma
Kullanıcı tarayıcıyı kapatırsa veya callback isteği bir nedenle sunucunuza ulaşmazsa, ödeme sonucunu kaçırmamak için webhook kritik öneme sahiptir. iyzico, ilk ödeme girişiminden 10-15 saniye sonra sunucunuza bir HTTP POST bildirimi gönderir; sunucunuz 2xx ile yanıt verene kadar 15 dakikada bir, en fazla 3 kez tekrar dener.
| Alan | Açıklama |
|---|---|
| paymentId | İlgili ödemenin kimliği |
| status | SUCCESS, FAILURE, INIT_THREEDS, CALLBACK_THREEDS vb. |
| iyziEventType | İstek tipi (PAYMENT_API, THREE_DS_AUTH, BALANCE…) |
| iyziReferenceCode | İstek için üretilen benzersiz iyzico referansı |
X-IYZ-SIGNATURE-V3 değeri, secretKey + iyziEventType + paymentId + paymentConversationId + status dizisinin HMAC-SHA256 ile hash'lenmiş halidir; kendi tarafınızda aynı hesaplamayı yapıp eşleştirmeden bildirimi güvenilir saymayın.Sandbox Test Kartları
Sandbox ortamında gerçek kart kullanılamaz; iyzico üç kategoride test kartı sağlar — başarılı yanıt veren kartlar, yabancı kartlar ve kasıtlı olarak hata üreten kartlar. Birkaç örnek:
| Kart Numarası | Senaryo |
|---|---|
| 5528790000000008 | Mastercard kredi kartı — başarılı ödeme |
| 4543590000000006 | Visa kredi kartı — başarılı ödeme |
| 4111111111111129 | Yetersiz bakiye hatası (NOT_SUFFICIENT_FUNDS) |
| 4125111111111115 | Süresi dolmuş kart hatası (EXPIRED_CARD) |
| 4121111111111119 | Fraud şüphesi hatası (FRAUD_SUSPECT) |
Sık Karşılaşılan Hata Kodları
Başarısız bir istekte iyzico size errorCode, errorGroup ve okunabilir bir errorMessage döner. En sık görülenler:
| Kod | Hata Grubu | Anlamı |
|---|---|---|
| 10051 | NOT_SUFFICIENT_FUNDS | Kart limiti/bakiyesi yetersiz |
| 10054 | EXPIRED_CARD | Kartın son kullanma tarihi geçmiş |
| 10084 | INVALID_CVC2 | CVV hatalı veya geçersiz |
| 1000 | Geçersiz imza | Hesapladığınız hash, iyzico ile eşleşmiyor |
| 1006 | api key gönderilmesi zorunludur | İstekte apiKey eksik veya yanlış |
Güvenlik ve Best Practice
- Tutarı her zaman sunucu tarafında hesaplayın — sepet toplamını istemciden gelen değere değil, veritabanındaki gerçek fiyatlara göre belirleyin
- conversationId'yi sipariş ID'nizle eşleştirin — webhook ve callback'i doğru siparişle eşlemenin tek güvenilir yolu budur
- Kart numarasını asla kendi veritabanınızda saklamayın — tokenize/cüzdan özelliği gerekiyorsa iyzico'nun kart saklama servisini kullanın
- Aynı ödemeyi hem callback hem webhook'tan işlerken idempotent olun — paymentId üzerinden tekrar eden bildirimleri filtreleyin
- secretKey'i ortam değişkeninde tutun, sandbox ve canlı anahtarları net biçimde ayırın (örn.
.env/.env.production)
Sıkça Sorulan Sorular
iyzico entegrasyonu için sunucu mu gerekli, yoksa sadece frontend yeterli mi?
Sunucu taraflı bir backend zorunludur. secretKey tarayıcıya asla gönderilemez; ödeme başlatma, sonuç sorgulama ve webhook doğrulama işlemlerinin tamamı sunucunuzda yapılmalıdır.
Ödeme Formu mu yoksa direkt API entegrasyonu mu tercih edilmeli?
Çoğu proje için Ödeme Formu önerilir: kart verisi sizin sunucunuza hiç dokunmaz, bu da PCI-DSS kapsamınızı önemli ölçüde küçültür ve 3D Secure akışını sizin yerinize yönetir. Direkt API entegrasyonu yalnızca tam özelleştirilmiş bir ödeme arayüzü gerektiren ileri seviye senaryolarda tercih edilmelidir.
Webhook olmadan sadece callbackUrl yeterli mi?
Hayır, güvenilir değildir. Kullanıcı ödeme sonrası tarayıcıyı kapatabilir, bağlantısı kesilebilir veya yönlendirme bir nedenle başarısız olabilir. Webhook, bu durumlarda dahi ödeme sonucunun sunucunuza ulaşmasını garanti eden tek mekanizmadır.
iyzico veya başka bir ödeme sağlayıcı entegrasyonu için profesyonel destek alın — API tasarımından webhook güvenliğine kadar. Teklif Alın