Gereksinimler ve Ön Hazırlık
Projenize başlamadan önce sisteminizde Laravel 11 veya üzeri bir sürümün kurulu olduğundan emin olmalısınız. Dinamik bir sepet yapısı için veritabanı ilişkileri (One-to-Many) ve servis sağlayıcı yapısı hakkında temel bilgi sahibi olmanız süreci hızlandıracaktır.
- PHP 8.3 veya üzeri sürüm.
- Composer paket yöneticisi.
- MySQL veya PostgreSQL veritabanı sunucusu.
- Ödeme entegrasyonu için bir test API anahtarı (Iyzico, Stripe veya benzeri).
Adım 1: Sepet Veritabanı Modellerini ve İlişkilerini Kurma
Dinamik bir sepet için "Cart" (Sepet) ve "CartItem" (Sepet Kalemi) tablolarına ihtiyacımız vardır. Bu yapı, kullanıcının sepetindeki ürünleri kalıcı olarak saklamamıza olanak tanır. Öncelikle modellerimizi ve migration dosyalarımızı oluşturalım.
// Terminal üzerinden modelleri oluşturma
php artisan make:model Cart -m
php artisan make:model CartItem -m
Migration dosyalarımızda ürünlerin fiyatını, miktarını ve sepetle olan ilişkisini tanımlamalıyız. Veri bütünlüğünü sağlamak için foreign key (yabancı anahtar) kullanmak kritiktir.
// database/migrations/xxxx_create_cart_items_table.php
public function up(): void
{
Schema::create('cart_items', function (Blueprint $table) {
$table->id();
$table->foreignId('cart_id')->constrained()->onDelete('cascade');
$table->foreignId('product_id')->constrained();
$table->integer('quantity')->default(1);
$table->decimal('price', 10, 2);
$table->timestamps();
});
}
Adım 2: Sepet Yönetimi İçin Servis Sınıfı Oluşturma
İş mantığını Controller'dan ayırmak, kodun sürdürülebilirliği için şarttır. "CartService" sınıfı, sepete ürün ekleme, çıkarma ve toplam tutarı hesaplama işlemlerini üstlenecektir.
namespace App\Services;
use App\Models\Cart;
use App\Models\CartItem;
class CartService {
public function addToCart($cartId, $productId, $price, $quantity = 1) {
return CartItem::updateOrCreate(
['cart_id' => $cartId, 'product_id' => $productId],
['quantity' => \DB::raw("quantity + $quantity"), 'price' => $price]
);
}
}
Bu yapı, aynı ürün sepete tekrar eklendiğinde yeni bir satır oluşturmak yerine mevcut miktarı artırarak veritabanı yükünü optimize eder.
Adım 3: Dinamik Sepet Kontrolcüsü
Kullanıcı sepete bir ürün eklediğinde, Controller üzerinden servis sınıfımızı çağırmalıyız. Burada dikkat etmemiz gereken en önemli nokta, kullanıcı oturumunun (session) yönetilmesidir.
public function store(Request $request, CartService $cartService) {
$cart = Cart::firstOrCreate(['user_id' => auth()->id()]);
$cartService->addToCart($cart->id, $request->product_id, $request->price);
return response()->json(['message' => 'Ürün sepete eklendi.']);
}
Adım 4: Ödeme Entegrasyonu ve Güvenlik Protokolleri
Ödeme işlemleri, hassas veri içerdiği için doğrudan sunucu tarafında işlenmelidir. Ödeme sağlayıcısının SDK'sını kullanarak bir "PaymentIntent" oluşturmak, kart bilgilerinin sunucunuzda saklanmadan doğrudan sağlayıcıya gitmesini sağlar.
Kritik Güvenlik Uyarısı: Müşterilerin kredi kartı bilgilerini asla kendi veritabanınızda saklamayın. PCI-DSS uyumluluğu için her zaman tokenizasyon yöntemini veya ödeme sağlayıcısının sunduğu güvenli ödeme formlarını kullanın.
// Ödeme işlemi örneği
public function processPayment(Request $request) {
$paymentGateway = new \App\Services\PaymentGateway();
$result = $paymentGateway->charge($request->amount, $request->payment_token);
if ($result->successful()) {
return redirect()->route('order.success');
}
return back()->withErrors(['message' => 'Ödeme başarısız.']);
}
Adım 5: Yöntemlerin Karşılaştırılması
Sepet ve ödeme süreçlerini yönetirken kullanabileceğiniz farklı yaklaşımları aşağıdaki tabloda inceleyebilirsiniz.
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Session Tabanlı | Hızlı ve basit uygulama | Kullanıcı çıkış yapınca sepet silinir |
| Veritabanı Tabanlı | Kalıcı ve senkronize sepet | Daha fazla veritabanı sorgusu |
| Redis Tabanlı | Çok yüksek performans | Sunucu yapılandırması gerektirir |
Adım 6: Test Etme ve Hata Ayıklama
Uygulamanızı canlıya almadan önce mutlaka "Unit Test" yazmalısınız. Laravel'in sunduğu TestCase sınıfı ile sepetin toplam tutarını ve ödeme akışını simüle edebilirsiniz.
public function test_cart_total_calculation() {
$cart = Cart::factory()->create();
$cart->items()->create(['price' => 100, 'quantity' => 2]);
$this->assertEquals(200, $cart->total());
}
Sıkça Sorulan Sorular
Sepet verilerini ne zaman temizlemeliyim?
Ödeme işlemi başarıyla tamamlandığında veya kullanıcı sepeti manuel olarak boşalttığında veritabanındaki ilgili kayıtları silmelisiniz.
Ödeme sırasında oluşabilecek hataları nasıl yönetirim?
Try-catch blokları kullanarak ödeme sağlayıcısından dönen istisnaları yakalamalı ve kullanıcıya anlamlı hata mesajları göstermelisiniz.
Kullanıcı giriş yapmadan sepeti kullanabilir mi?
Evet, oturum ID'sini (session ID) kullanarak giriş yapmamış kullanıcılar için de geçici bir sepet oluşturabilirsiniz.
Veritabanı tabanlı sepet performansı etkiler mi?
Doğru indeksleme (index) yapıldığı sürece modern veritabanları milyonlarca satırı hızlıca işleyebilir; performans sorunu yaşanmaz.
Ödeme formunda hangi güvenlik önlemleri şarttır?
Mutlaka SSL sertifikası kullanmalı ve CSRF (Cross-Site Request Forgery) korumasını aktif tutmalısınız.
İleri Seviye İpuçları: Sepet Verilerini Redis ile Önbelleğe Alma
Veritabanı tabanlı sepet yönetimi, yüksek trafikli e-ticaret sitelerinde zamanla I/O darboğazlarına yol açabilir. Laravel'in sunduğu güçlü önbellekleme (caching) mekanizmalarını kullanarak, sepet verilerini Redis üzerinde tutmak uygulama performansını ciddi oranda artırır.
Redis Kullanarak Sepet Performansını Optimize Etme
Redis, verileri RAM üzerinde tuttuğu için veritabanı sorgularına kıyasla milisaniyeler seviyesinde yanıt verir. Aşağıdaki örnekte, sepet verisini Redis'te nasıl saklayacağınızı görebilirsiniz:
use Illuminate\Support\Facades\Redis;
public function addToCartRedis($userId, $productData)
{
$key = "cart:{$userId}";
// Sepet verisini JSON formatında Redis'e ekle
Redis::hset($key, $productData['id'], json_encode($productData));
// Sepetin 24 saat sonra silinmesini sağla
Redis::expire($key, 86400);
}
Ödeme Süreçlerinde Webhook Kullanımı ve Senkronizasyon
Ödeme entegrasyonlarında en kritik nokta, ödeme sağlayıcısından gelen yanıtın (callback) güvenli bir şekilde işlenmesidir. Kullanıcı tarayıcıyı kapatsa bile işlemin tamamlandığından emin olmak için Webhook mekanizmasını kullanmalısınız.
Webhook Doğrulama ve İşleme
Ödeme sağlayıcınızdan gelen isteğin gerçekten onlardan geldiğini doğrulamak için imza (signature) kontrolü yapmanız şarttır. İşte temel bir Webhook kontrolcüsü yapısı:
public function handleWebhook(Request $request)
{
$signature = $request->header('X-Payment-Signature');
if (!$this->verifySignature($request->getContent(), $signature)) {
return response()->json(['error' => 'Geçersiz imza'], 403);
}
$payload = $request->all();
if ($payload['status'] === 'success') {
$order = Order::where('transaction_id', $payload['id'])->first();
$order->update(['status' => 'paid']);
// Stok güncelleme ve e-posta tetikleme işlemleri burada yapılır
}
return response()->json(['status' => 'ok']);
}
Entegrasyon İçin İleri Düzey Kontrol Listesi
- Stok Rezerve Etme: Kullanıcı ödeme sayfasına gittiğinde, ürünü geçici olarak "rezerve" durumuna getirin (örneğin 10 dakika).
- Loglama: Ödeme sırasında oluşan tüm hataları
storage/logs/laravel.logyerine özel bir log kanalına yazın. - İş Kuyrukları (Queues): Ödeme sonrası e-posta gönderme veya fatura oluşturma gibi işlemleri
Jobsınıfları ile arka plana atın. - İşlem İptali: Ödeme başarısız olduğunda sepeti temizlemeyin, kullanıcıya "Tekrar Dene" butonu sunun.
Sonuç
Laravel ile dinamik bir sepet ve ödeme entegrasyonu yapmak, doğru mimari kararlar alındığında oldukça güvenli ve sürdürülebilirdir. Bu rehberde, veritabanı modellemesinden ödeme güvenliğine kadar temel adımları tamamladık. Bir sonraki adım olarak, ödeme sonrası e-posta bildirimleri ve stok yönetimi (inventory management) entegrasyonlarını projenize dahil edebilirsiniz.
Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Ödeme sistemleri ve finansal işlemler yüksek güvenlik gerektirir. Üretim ortamında (production) kullanmadan önce mutlaka PCI-DSS uyumluluk standartlarını gözden geçirin ve profesyonel güvenlik denetimlerinden geçin.


Yorumlar (0)
Yorum Yaz