Blog'a dön
•
ByteGurus

Güvenli Ödeme Sistemleri: Modern Uygulamalar İçin Rehber

PCI DSS, tokenizasyon, şifreleme, 3D Secure ve dolandırıcılık izleme ile güvenli ödeme sistemi kurmanın temel ilkeleri ve uygulama örnekleri.

Ödeme Fintech Güvenlik

Ödeme altyapısı, çevrim içi satış yapan her ürünün en hassas parçasıdır. Fintech platformu, e-ticaret sitesi ya da abonelik hizmeti kuruyor olun, kart verisinin nerede durduğu ve kimin ona dokunabildiği işin geri kalanından önce gelir. Bu rehber, güvenli bir ödeme sisteminin temel ilkelerini ve bunları koda nasıl dökeceğinizi anlatıyor.

Ödeme güvenliği neyi kapsar

Ödeme sistemleri üç kaygının kesiştiği yerde çalışır: verinin korunması, mevzuata uyum ve dolandırıcılığın önlenmesi. Güvenli bir sistemin temeli de üç ayaklıdır: şifreleme, tokenizasyon ve uyum. Üçü birlikte, kart verisinin işlemin her aşamasında korunmasını sağlar.

PCI DSS: sektörün asgari standardı

Ödeme Kartı Endüstrisi Veri Güvenliği Standardı (PCI DSS), kart verisi işleyen her sistem için başlangıç çizgisidir. Geçerli sürüm 4.0.1’dir; 3.2.1 Mart 2024’te kullanımdan kalktı. Standart 12 ana gereksinim altında toplanır.

Öne çıkan gereksinimler:

  • Güvenli ağ mimarisi: Güvenlik duvarları, ağ bölümleme ve kart verisi ortamıyla güvenilmeyen ağlar arasında doğrudan yol olmaması
  • Güçlü erişim denetimi: Kimlik doğrulama, kişiye özel kullanıcı hesapları ve kart verisine yalnız gereken kişilerin erişmesi
  • Düzenli güvenlik testi: Zafiyet taramaları, sızma testleri ve kod incelemeleri
  • Farkındalık eğitimi: Ödeme verisiyle çalışan herkes için

Pratikte ihlallerin çoğu karmaşık saldırılardan değil, atlanan temel adımlardan çıkar. PCI DSS’in temellerini düzgün kurmak saldırı yüzeyinin büyük kısmını kapatır.

Tokenizasyon: kart verisini sisteminizden uzak tutun

Kart verisini korumanın en etkili yolu ona hiç dokunmamaktır. Tokenizasyonda kart bilgisi ödeme sağlayıcısının kasasında kalır; sizin sisteminiz yalnız o karta karşılık gelen bir token saklar.

Önemli ayrıntı: token tarayıcıda üretilmelidir. Kart numarası sizin sunucunuza hiç gelmemeli, doğrudan sağlayıcının alanına (Stripe Elements, iyzico ödeme formu, PayTR iFrame gibi) girilmelidir. Sunucunuz yalnız token ya da ödeme yöntemi kimliğiyle çalışır:

// Sunucu: kart numarasını değil, tarayıcıda üretilmiş ödeme yöntemi kimliğini alır
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

async function chargeCustomer(paymentMethodId, amountMinor, currency) {
  return stripe.paymentIntents.create({
    amount: amountMinor,          // kuruş/sent cinsinden tam sayı
    currency,                     // 'try', 'eur', 'usd'
    payment_method: paymentMethodId,
    confirm: true,
    automatic_payment_methods: { enabled: true, allow_redirects: 'never' },
  });
}

Tokenizasyonun getirdikleri:

  • Sistemleriniz ham kart verisi işlemez
  • Ele geçirilen token, yalnız sizin üye işyeri hesabınızda geçerli olduğu için tek başına işe yaramaz
  • PCI DSS kapsamınız ciddi biçimde daralır (çoğu durumda SAQ A seviyesine iner)
  • Tekrarlayan ödemeleri güvenle alabilirsiniz

Şifreleme: iletimde ve depoda

Ödemeyle ilgili saklamak zorunda olduğunuz her veri hem ağda taşınırken hem de depoda şifreli olmalıdır.

İletimde: Ödeme verisi taşıyan her bağlantıda TLS 1.2 ya da üstü kullanın, eski protokolleri sunucuda kapatın.

Depoda: Hassas alanları uygulama katmanında, kimlik doğrulamalı bir şifreleme kipiyle (AES-256-GCM) şifreleyin. Anahtarı kodda ya da veritabanında değil, bir anahtar yönetim servisinde (KMS, Vault) tutun:

const crypto = require('crypto');

// key: KMS'ten alınan 32 baytlık veri anahtarı
function encrypt(plaintext, key) {
  const iv = crypto.randomBytes(12);
  const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
  const data = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
  const tag = cipher.getAuthTag();
  return [iv, tag, data].map((b) => b.toString('base64')).join('.');
}

function decrypt(payload, key) {
  const [iv, tag, data] = payload.split('.').map((s) => Buffer.from(s, 'base64'));
  const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
  decipher.setAuthTag(tag); // değiştirilmiş veri burada reddedilir
  return Buffer.concat([decipher.update(data), decipher.final()]).toString('utf8');
}

GCM’nin CBC’ye üstünlüğü, verinin değiştirilip değiştirilmediğini de doğrulamasıdır.

3D Secure ile kimlik doğrulama

3D Secure (3DS), kart işlemine ek bir doğrulama katmanı ekler. 3DS2, riski düşük işlemlerde kullanıcıyı ek adıma göndermeden doğrulama yapabildiği için deneyimi daha az bozar. Türkiye’de kartla yapılan çevrim içi ödemelerin büyük çoğunluğu 3DS ile yürür; Avrupa’da PSD2’nin güçlü müşteri doğrulaması (SCA) da benzer bir adım ister.

// Sunucu: ödeme niyetini oluşturur, doğrulamayı tarayıcı tamamlar
async function createPaymentIntent(amountMinor, currency, customerId) {
  const intent = await stripe.paymentIntents.create({
    amount: amountMinor,
    currency,
    customer: customerId,
    automatic_payment_methods: { enabled: true },
  });
  // client_secret tarayıcıya gider; 3DS gerekiyorsa sağlayıcının SDK'sı açar
  return { clientSecret: intent.client_secret };
}

Dolandırıcılık tespiti ve izleme

Güvenli bir ödeme sistemi şüpheli işlemi gerçek zamanlı yakalamalıdır. Uygulanabilecek kontroller:

  • Sıklık kontrolü: Kullanıcı ya da kart başına kısa sürede yapılan işlem sayısı
  • Konum analizi: Alışılmadık ülke ya da IP’den gelen işlemler
  • Tutar eşikleri: Belirli tutarı aşan işlemlerin incelemeye düşmesi
  • Cihaz parmak izi: İşlemi yapan cihazın takibi
  • Makine öğrenmesi: Geçmiş veriden şüpheli örüntüleri çıkaran modeller
// Basit bir risk değerlendirmesi
async function assessRisk(db, userId, amount, ipAddress) {
  const factors = [];

  const lastHour = await db.countTransactions(userId, { withinMinutes: 60 });
  if (lastHour > 5) factors.push('high_velocity');

  const user = await db.getUser(userId);
  if (user.lastCountry && user.lastCountry !== geoCountry(ipAddress)) {
    factors.push('unusual_location');
  }

  if (amount > user.averageTransactionAmount * 3) factors.push('unusual_amount');

  return {
    level: factors.length === 0 ? 'low' : factors.length === 1 ? 'medium' : 'high',
    factors,
    requiresReview: factors.length > 1,
  };
}

Ödeme API’lerinin güvenliği

Ödeme uçlarınız yaygın zafiyetlere karşı sertleştirilmelidir:

  • Hız sınırı: Kart deneme (card testing) saldırılarına karşı uç başına sınır
  • Girdi doğrulama: Tutar, para birimi ve kimlikler sunucuda doğrulanır; tutar asla istemciden olduğu gibi alınmaz
  • API kimlik doğrulaması: OAuth 2.0 ya da benzeri bir mekanizma
  • Webhook imzası: Sağlayıcıdan gelen bildirimlerin imzası doğrulanmadan işlenmez
// Webhook imza doğrulaması (Stripe örneği)
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  let event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      req.headers['stripe-signature'],
      process.env.STRIPE_WEBHOOK_SECRET,
    );
  } catch (err) {
    return res.status(400).send('Geçersiz imza');
  }

  if (event.type === 'payment_intent.succeeded') {
    // Ödemeyi idempotent biçimde işle: aynı olay iki kez gelebilir
  }
  res.json({ received: true });
});

Özet: sekiz temel kural

  1. Ham kart verisini saklamayın, sunucunuza bile almayın; tokenizasyon kullanın
  2. Her şeyi şifreleyin, iletimde ve depoda
  3. PCI DSS uyumunu sürdürün, düzenli denetim ve güncellemeyle
  4. Güçlü doğrulama kullanın, 3DS ve yönetim tarafında çok faktörlü giriş
  5. Sürekli izleyin, gerçek zamanlı dolandırıcılık tespiti ve kayıt
  6. Bağımlılıkları güncel tutun, güvenlik yamalarını bekletmeyin
  7. Test edin, sızma testleri ve güvenlik incelemeleriyle
  8. Ekibi eğitin, güvenlik farkındalığı bir kerelik iş değildir

Güvenli ödeme sistemi bir kez kurulup bırakılmaz; tehditler değiştikçe o da güncellenir. Bir ödeme sistemi tasarlıyorsanız ve tasarıma ikinci bir göz istiyorsanız bize yazın.

B

ByteGurus

Yazar

Tüm yazılara dön
Başlamaya hazır mısınız?

Projenize başlamaya hazır mısınız?

Fikirlerinizi hayata geçirmek için size nasıl yardımcı olabileceğimizi konuşalım.