top of page

Sanal POS Entegrasyonu: Teknik Adımlar ve API Rehberi 2025

Güncelleme tarihi: 22 May


Özet: - Sanal POS entegrasyonu üç temel bileşen gerektirir: API anahtarı, test ortamı erişimi ve SSL sertifikası. Bunlar olmadan ödeme akışı çalışmaz. - iyzico, API isteklerini HMACSHA256 algoritmasıyla imzalar; her istek için benzersiz bir randomKey üretilmeli ve Authorization başlığı "IYZWSv2" önekiyle gönderilmelidir. - 3D Secure akışı iki endpoint üzerinden yürür: önce `/payment/3dsecure/initialize` ile oturum başlatılır, dönen Base64 HTML içeriği kullanıcıya gösterilir; doğrulama sonrası `/payment/3dsecure/auth` ile ödeme tamamlanır. - Test ortamından canlıya geçişte API anahtarları ortam değişkenlerine taşınmalı, webhook imzaları doğrulanmalı ve kart verisi hiçbir zaman kendi sunucunuzda saklanmamalıdır.


Sanal POS entegrasyonu, teknik açıdan doğru adımlar atılmadan girişildiğinde hem geliştirme takvimi şişer hem de güvenlik zafiyetleri kaçınılmaz olur. Pek çok e-ticaret projesi, "entegrasyon tamamlandı" kararı verildikten sonra canlıya geçişte 3D Secure kaynaklı bir hata ya da çalışmayan callback URL yüzünden günlerce sürüncemede kalır. Bu rehber, Türkiye'de yaygın kullanılan sanal POS sağlayıcılarının (iyzico, PayTR, Stripe) resmi teknik dökümanlarından derlenen bir uygulama kılavuzudur. Hangi altyapıyı seçeceğinizden bağımsız olarak entegrasyonun omurgasını kavramanıza destek olacak.


Teknik entegrasyon, kabaca beş aşamaya ayrılır: sandbox kurulumu, API kimlik doğrulama, SSL yapılandırması, 3D Secure akışı ve canlı ortama geçiş. Her aşamada farklı riskler beliriyor; aşağıdaki bölümlerde bunları ayrı ayrı ele aldık.


Ön Hazırlık ve Sandbox Hesabı Oluşturma


Entegrasyona başlamadan önce gerçek ödeme trafiği üretmeyen, yalıtılmış bir test ortamına ihtiyaç vardır. Banka kartı hareketlerini simüle eden bu yapıya sandbox ya da kum havuzu denir. Büyük sağlayıcıların tamamı sandbox erişimini ücretsiz sunar.


iyzico'da sandbox kaydı `sandbox-merchant.iyzipay.com/auth/register` adresinden yapılır. Kayıt tamamlandığında kontrol paneli üç kimlik bilgisi verir: Merchant ID, API Key ve Secret Key. API Key, sandbox ortamında "sandbox-" önekini taşır; üretim ortamında bu önek bulunmaz. PayTR ve Stripe'ta ayrım yöntemi benzer biçimde çalışır. Stripe test anahtarları `sk_test_` ve `pk_test_` önekiyle gelir; canlı anahtarlar `sk_live_` ve `pk_live_` kullanır.


Kurulum sırasında sık yapılan hata, sandbox ve canlı ortam URL'lerini aynı konfigürasyon dosyasında iç içe bırakmaktır. iyzico için sandbox API adresi `https://sandbox-api.iyzipay.com`, canlı ortam adresi `https://api.iyzipay.com`'dur. Bu iki değer kod içine doğrudan yazılırsa test aşamasında yanlış ortama istek gönderme riski kalır. Ortam adresini her zaman bir yapılandırma değişkeninde tutun.


API Anahtarı Yönetimi ve Güvenli Saklama


API anahtarları ödeme sisteminin en hassas parçasıdır. Kaynak koda ya da açık bir depoya sızdığında hesap yetkisiz işlemlere açık hale gelir ve sağlayıcı hesabı derhal askıya alabilir.


Stripe iki türlü anahtar dağıtır. Publishable Key (`pk_...`) yalnızca istemci tarafında çalışır; Stripe.js kütüphanesini başlatmak için kullanılır ve kamuya açık olmasında sorun yoktur. İzinleri kasıtlı olarak kısıtlıdır. Secret Key (`sk_...`) ise yalnızca sunucu tarafında, güvenli bir ortamda kullanılır. Tarayıcıya asla gönderilmez, Git geçmişine kesinlikle işlenmez. iyzico'da da yapı özdeştir: API Key ve Secret Key çifti backend çağrılarına özeldir, hiçbir koşulda ön yüze taşınmaz.


Pratik saklama yapısı şu şekilde kurulur:


```

# .env dosyası — version control'e dahil edilmez

IYZICO_API_KEY=sandbox-xxxxxxxxxxxxxxxxxxxxxxxx

IYZICO_SECRET_KEY=sandbox-yyyyyyyyyyyyyyyyyyyy

IYZICO_BASE_URL=https://sandbox-api.iyzipay.com

```


Değerleri uygulama içinden `process.env.IYZICO_API_KEY` referansıyla çekin. Docker ya da bulut altyapılarında secrets vault tercih edin; `.env` dosyasını sunucuya kopyalamak yerine ortam değişkeni olarak enjekte edin. Stripe, 180 günü aşkın süre kullanılmayan anahtarları otomatik olarak kısıtlamaya alır. Bu nedenle düzenli anahtar rotasyonu da güvenlik planının bir parçası olmalıdır.


İstek Kimlik Doğrulama: HMAC İmzalama


Sanal POS API'lerinin büyük çoğunluğu, her isteğin imzalanmasını zorunlu tutar. Bu, istek içeriğinin yolda değiştirilmediğini kanıtlar.


iyzico, HMACSHA256 algoritmasını üç adımlı bir süreçle uygular:


Adım 1, Şifrelenmiş veri oluşturma:

```

HMACSHA256(randomKey + uri.path + request.body, secretKey)

```

`randomKey`, her istek için üretilen benzersiz bir değerdir; zaman damgası + rastgele dize kombinasyonu kullanılabilir.


Adım 2, Base64 kodlama:

```

base64("apiKey:" + apiKey + "&randomKey:" + randomKey + "&signature:" + encryptedData)

```


Adım 3, Authorization başlığı oluşturma:

```

Authorization: IYZWSv2 [base64EncodedAuthorization]

x-iyzi-rnd: [randomKey]

Content-Type: application/json

```


PayTR'de işlem sıralaması farklıdır. `merchant_id`, `merchant_key` ve `merchant_salt` değerleri birleştirilerek bir token üretilir; bu token form gövdesiyle birlikte gönderilir. Sağlayıcıdan bağımsız olarak imzalama mantığı şu prensibe dayanır: her iki taraf aynı girdilerden aynı imzayı üretebiliyorsa istek geçerlidir, aksi hâlde reddedilir. Bu nedenle imzayı oluşturan parametrelerin sırası ve kodlaması dökümanla birebir örtüşmelidir; küçük bir karakter farkı bile doğrulamanın başarısız olmasına yeter.


Hata ayıklamayı kolaylaştırmak için geliştirme aşamasında imzayı ayrı bir fonksiyona taşıyın ve log'layın. Canlı ortamda ise bu log'ları kapatın; imza verisini açıkta bırakmak güvenlik açığı oluşturur.


SSL Sertifikası ve HTTPS Zorunluluğu


Ödeme entegrasyonunda SSL sertifikası, sağlayıcıların göndermeyi reddettiği bir ön koşuldur; isteğe bağlı bir güvenlik katmanı değildir.


iyzico, callback URL'lerinin geçerli bir SSL sertifikası taşımasını ve HTTPS üzerinden yanıt vermesini zorunlu tutar. Stripe, canlı webhook endpoint'leri için TLS 1.2 veya 1.3 desteği arar. HTTP'e yönlendiren 302 response'lar webhook iletimini keser; Stripe bu durumu hata olarak raporlar.


Üretim ortamına geçmeden önce üç noktayı kontrol edin:


  1. Sertifika geçerlilik tarihi dolmamış olmalıdır. Otomatik yenileme (auto-renewal) kurulumu yapılmamışsa bu tarih gözden kaçabilir.

  2. Callback ve webhook adreslerinin tamamı domain veya subdomain ile bire bir eşleşen bir sertifikayla korunmalıdır. Wildcard sertifikalar bu ihtiyacı karşılar.

  3. Self-signed sertifikalar test ortamında çalışsa bile üretim ortamında sağlayıcılar tarafından tanınmaz. Let's Encrypt ya da ticari bir CA'dan sertifika alınmalıdır.


Let's Encrypt, çoğu barındırma altyapısında ücretsiz ve otomatik sertifika sunar. NGINX veya Apache sunucularda Certbot aracıyla birkaç komutla kurulabilir. Sunucusuz ya da konteyner tabanlı mimarilerde sağlayıcı genellikle SSL yönetimini üstlenir; yine de özel domain tanımlarken sertifika durumunu ayrıca doğrulayın.


Test Ortamı Kurulumu ve Test Kartları


Test ortamı, gerçek bir kart hareketi başlatmadan ödeme akışının her dalını doğrulamanızı sağlar. Sandbox'ta yapılan işlemler banka ağlarına hiç ulaşmaz; her şey sağlayıcının kendi altyapısında simüle edilir.


iyzico sandbox'ında OTP değeri her zaman 123456 olarak sabitlenmiştir. 3D Secure akışını test ederken banka doğrulama ekranına bu kodu girin. CVV ve son kullanma tarihi formata uygun herhangi bir değer olabilir; gerçek kart bilgisi sandbox ortamında işlenmez.


Stripe'ta başarılı ödeme senaryosu için `4242424242424242` numaralı Visa kart kullanılır. Mastercard testi için `5555555555554444` numarası çalışır. Her iki kartta da CVC herhangi üç rakam, son kullanma tarihi ilerleyen herhangi bir ay ve yıl olabilir.


Hata senaryolarını da test etmek gerekir; başarılı akış tek başına yeterli değildir. Yetersiz bakiye, kart kayıp bildirimi, geçersiz CVV ve sahte işlem şüphesi gibi durumlar için sağlayıcılar ayrı kart numaraları sunar. Bu senaryolar test edilmeden canlıya geçilirse reddedilen ödeme veya dolandırıcılık şüphesi gibi edge case'ler kullanıcıya ham hata mesajı olarak yansır.


iyzico dökümanına göre sandbox'ta otuzdan fazla hata senaryosu test kartı mevcuttur. Stripe'ta ise `pm_card_chargeDeclined` gibi PaymentMethod nesneleri bu testler için özelleştirilmiş seçenekler sunar.


Stripe CLI ile yerel ortamda webhook testleri yapılabilir:


```bash

stripe listen --forward-to localhost:4242/webhook

```


Bu komut, Stripe'tan gelen olayları yerel sunucunuza iletir. Ödeme olayını tetiklemek için:


```bash

stripe trigger payment_intent.succeeded

```


3D Secure Entegrasyon Akışı


3D Secure, kart sahibinin kimliğini banka tarafında doğrulayan ekstra bir güvenlik katmanıdır. Türkiye'de bankalar 3DS'i neredeyse tüm kart işlemlerinde zorunlu tutar.


iyzico üzerinde 3DS entegrasyonu iki adımda tamamlanır:


Başlatma isteği:

```

POST https://api.iyzipay.com/payment/3dsecure/initialize

```

Bu isteğin gövdesinde kart bilgileri, alıcı bilgileri, sepet içeriği ve `callbackUrl` parametresi yer alır. `callbackUrl`, banka doğrulama ekranından döndükten sonra kullanıcının yönlendirileceği sayfa URL'sidir.


Başarılı yanıtta `threeDSHtmlContent` alanı döner. Bu alan, Base64 kodlu bir HTML içeriğidir. Değeri decode edip kullanıcıya göstermeniz gerekir; genellikle bir iframe içinde ya da yeni sayfada render edilir.


Tamamlama isteği:

Kullanıcı OTP'yi girdikten sonra banka isteği `callbackUrl` adresine yönlendirir. Callback'i alan sayfa hemen tamamlama çağrısı yapar:

```

POST https://api.iyzipay.com/payment/3dsecure/auth

```

`paymentId` parametresi, initialize adımından dönen değerdir.


Tamamlama yanıtında üç alan kritiktir:


  • `status` "success" dönerse ödeme onaylanmıştır.

  • `mdStatus` "1" ise 3DS kimlik doğrulaması geçti.

  • `fraudStatus` 1 ise sipariş kargoya verilebilir, 0 ise iyzico'dan bildirim bekleyin, -1 ise işlem reddedilmiştir.


Bu üç kontrolü atlamak, doğrulama tamamlanmadan siparişi sisteme işleme riski taşır. iyzico, hem v1 (`/payment/3dsecure/auth`) hem de v2 (`/payment/v2/3dsecure/auth`) endpoint'i sunar. v2, 3DS 2.0 protokolünü destekler ve yeni entegrasyonlar için önerilir.


Webhook Kurulumu ve Ödeme Sonucu İşleme


Webhook, ödeme sağlayıcısının sunucunuzu işlem olayları hakkında doğrudan haberdar ettiği asenkron bir bildirim mekanizmasıdır. Kullanıcı ödeme sayfasını kapattıktan sonra bile işlem tamamlanmış olabilir. Bunu webhook almadan tespit etmek mümkün değildir; sipariş sistemi o ödemenin varlığından haberdar olamaz.


Stripe'ta webhook kurulumu Dashboard üzerinden yürür. Webhooks sekmesinde endpoint URL'nizi tanımlayın. En az iki olayı dinlemeniz gerekir: `payment_intent.succeeded` ve `payment_intent.payment_failed`. Checkout kullanıyorsanız `checkout.session.completed` olayı da eklenmelidir.


Webhook güvenliği imza doğrulamasına dayanır. Stripe, her gelen isteğe `Stripe-Signature` başlığı ekler. Bu başlık, webhook signing secret kullanılarak HMAC-SHA256 algoritmasıyla oluşturulan bir imza içerir. Sunucunuzda imzayı doğrulamadan gelen veriyi işlemek, sahte webhook saldırısına kapı aralar.


Sağlam bir webhook handler dört sıradan oluşur:


```

  1. POST isteği alınır

  2. İmza doğrulanır (HMAC-SHA256)

  3. HTTP 200 yanıt hızla döndürülür (30 sn timeout aşılırsa Stripe yeniden dener)

  4. Sipariş onayı, stok güncellemesi ve bildirim e-postası asenkron kuyruğa alınır

```


iyzico ve PayTR benzer callback mimarisini kullanır. PayTR, entegrasyon sırasında tanımladığınız notification URL'sine POST gönderir; `merchant_oid` ve `status` parametrelerini taşır. iyzico'da callback dönüşünde paymentId ile auth çağrısı yapılarak sonuç kesinleştirilir.


Canlı Ortama Geçiş Kontrol Listesi


Test ortamı sorunsuz çalışsa bile canlıya geçmeden önce aşağıdaki adımları sırayla kontrol edin:


API anahtarları:

  • Sandbox anahtarlarını canlı anahtarlarla değiştirin.

  • Değişikliği ortam değişkeni üzerinden yapın; kod içindeki hardcoded değerleri kaldırın.

  • Secret key'i kaynak koduna, log dosyasına veya frontend tarafına kesinlikle dahil etmeyin.


SSL ve domain:

  • Tüm callback ve webhook URL'lerinin HTTPS üzerinden çalıştığını doğrulayın.

  • Sertifika son kullanma tarihini kontrol edin.


Webhook:

  • Canlı ortam webhook signing secret'ini güncelleyin.

  • İmza doğrulamasının aktif olduğunu test edin.

  • Hata senaryolarında (ödeme başarısız, kart reddedildi) sistemin doğru tepki verdiğini kontrol edin.


Güvenlik:

  • Kart numarası, CVV veya son kullanma tarihi kendi veritabanınızda saklanmamalıdır. Bunları saklamak PCI DSS kapsamı açar ve ciddi sorumluluk doğurur.

  • Kullanıcı form verisinin doğrudan API'ye gitmediği, sağlayıcının sunucularına iletildiği akışı tercih edin.


API limitleri:

  • iyzico'da ödeme başlatma ve sonuç sorgulama için dakika başına 50 istek sınırı geçerlidir. Sınır aşıldığında 50000 hata kodu döner. Yoğun trafik beklentisinde rate limit yönetimi planlanmalıdır.


Geliştirme başlangıcından canlıya geçişe uzanan süre, adımlar doğru sırayla atıldığında çoğunlukla beklenenden kısa olur. Sahada karşılaştığımız sorunların büyük bölümü üç kaynaktan beslenir: HMAC imzalama hatası, HTTPS sertifikası olmayan callback URL'si veya test anahtarlarının canlı ortama taşınmadan bırakılması. Bu üç madde temizse ilk gerçek ödeme testi nadiren takılır.


Bir sanal POS entegrasyonu teknik açıdan tamamlandığında sistem şunu garantilemelidir: kullanıcı 3DS ekranını geçip bankayla oturum kapattığında sunucunuz hem callback'i aldı hem webhook'u işledi hem de siparişi doğruladı. Bu üç olayın senkronize çalıştığını ayrı bir uçtan uca testle doğrulamak, canlıya geçiş öncesindeki son ve en önemli adımdır.


Kaynaklar:

  • iyzico Geliştirici Dökümanları: docs.iyzico.com (Mayıs 2026)

  • Stripe API Referansı: docs.stripe.com (Mayıs 2026)

  • PayTR Geliştirici Merkezi: dev.paytr.com (Mayıs 2026)


bottom of page