Laravel İle Stripe Üzerinden Abonelik Tabanlı Ödeme Sistemi Nasıl Yapılır?

Laravel İle Stripe Üzerinden Abonelik Tabanlı Ödeme Sistemi Nasıl Yapılır?
Laravel İle Stripe Üzerinden Abonelik Tabanlı Ödeme Sistemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Başlamadan önce sisteminizde PHP 8.3 veya üzeri bir sürümün, Laravel 11 veya 12'nin kurulu olduğundan emin olun. Ayrıca, Stripe Dashboard üzerinden API anahtarlarınızı (Public ve Secret Key) almanız gerekecektir.

  • Stripe hesabı (Test modu aktif olmalı).
  • Composer paket yöneticisi.
  • Laravel Cashier paketi.

Projenize Laravel Cashier paketini kurmak için terminalinizde şu komutu çalıştırın:

composer require laravel/cashier

Bu komut, abonelik yönetimi için gerekli olan veritabanı tablolarını ve Stripe ile haberleşme katmanını projenize dahil eder.

Veritabanı Yapılandırması ve Cashier Kurulumu

Cashier, kullanıcılarınızın abonelik durumlarını takip etmek için subscriptions ve subscription_items tablolarını kullanır. Kurulumdan sonra bu tabloları oluşturmak için migration dosyalarını yayınlamanız ve çalıştırmanız gerekir.

php artisan vendor:publish --tag="cashier-migrations"
php artisan migrate

Ardından, User modelinize Billable trait'ini eklemelisiniz. Bu trait, modelinize abonelik başlatma, iptal etme ve ödeme yöntemi güncelleme gibi yetenekler kazandırır.

namespace App\Models;

use Laravel\Cashier\Billable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Billable;
}
Güvenlik Uyarısı: Stripe API anahtarlarınızı asla doğrudan kod içerisinde paylaşmayın. .env dosyanızda STRIPE_KEY ve STRIPE_SECRET değişkenlerini tanımlayın ve bu dosyanın versiyon kontrol sistemine (Git) dahil edilmediğinden emin olun.

Ödeme Yöntemi Ekleme ve Abonelik Başlatma

Kullanıcıların abonelik başlatabilmesi için öncelikle bir ödeme yöntemi (kredi kartı vb.) tanımlamaları gerekir. Laravel Cashier, Stripe Elements kullanarak güvenli bir ödeme formu sunar.

Aşağıdaki örnekte, bir kullanıcıyı Stripe üzerinde müşteri olarak oluşturup aboneliğini başlatıyoruz:

use Illuminate\Http\Request;

public function subscribe(Request $request)
{
    $user = $request->user();
    $paymentMethod = $request->payment_method;

    // Kullanıcı için abonelik başlatma
    $user->newSubscription('premium', 'price_123456789')
         ->create($paymentMethod);

    return response()->json(['message' => 'Abonelik başarıyla başlatıldı.']);
}

Burada price_123456789, Stripe Dashboard üzerinde oluşturduğunuz ürünün fiyat ID'sini temsil eder.

Abonelik Durumunu Kontrol Etme

Kullanıcının aboneliğinin aktif olup olmadığını kontrol etmek, uygulamanızdaki kısıtlı içeriklere erişimi yönetmek için temel bir adımdır. Cashier, bunun için oldukça okunaklı yöntemler sunar.

Yöntem Açıklama
subscribed() Kullanıcının aktif bir aboneliği var mı?
onGracePeriod() Abonelik iptal edildi ancak süre dolmadı mı?
cancelled() Abonelik iptal edilmiş mi?

Örnek bir kontrol yapısı şu şekildedir:

if ($user->subscribed('premium')) {
    // Kullanıcı premium içeriğe erişebilir
} else {
    // Kullanıcıyı ödeme sayfasına yönlendir
}

Webhooks ile Ödeme Güncellemelerini Yönetme

Stripe'tan gelen bildirimleri (ödeme başarılı, abonelik iptal edildi vb.) dinlemek için Webhook'lar kullanılır. Laravel, CashierController ile bu süreci otomatik yönetir. routes/web.php dosyanıza rotayı ekleyin:

use Laravel\Cashier\Http\Controllers\WebhookController;

Route::post('/stripe/webhook', [WebhookController::class, 'handle']);

Bu rota üzerinden Stripe, uygulamanıza abonelik durum değişikliklerini anlık olarak iletir. Güvenlik için Stripe Dashboard'da bu URL'i "Webhook Endpoint" olarak tanımlamayı unutmayın.

Abonelik İptali ve Yenileme

Kullanıcıların aboneliklerini iptal etmeleri veya durdurmaları gerekebilir. İptal edilen bir abonelik, dönem sonuna kadar aktif kalmaya devam eder.

// Aboneliği iptal et
$user->subscription('premium')->cancel();

// İptal edilen aboneliği devam ettir
$user->subscription('premium')->resume();

İptal işlemi, veritabanındaki ends_at sütununu günceller ve Stripe üzerindeki otomatik yenilemeyi durdurur.

Kritik Uyarı: Ödeme sistemlerinde hata ayıklama yaparken mutlaka Stripe CLI aracını kullanın. stripe listen --forward-to localhost:8000/stripe/webhook komutu ile yerel ortamınızda canlıymış gibi testler yapabilirsiniz.

Sıkça Sorulan Sorular

Stripe Test Modu ile Canlı Mod Arasındaki Fark Nedir?

Test modu, gerçek para çekmeden ödeme süreçlerini simüle etmenizi sağlar. Canlı moda geçmek için Stripe Dashboard üzerinden Secret anahtarınızı güncellemeniz yeterlidir.

Kullanıcı Ödeme Yöntemini Nasıl Günceller?

Cashier'ın updateDefaultPaymentMethod() metodunu kullanarak veya Stripe'ın sunduğu "Customer Portal" özelliğini entegre ederek kullanıcıların kart bilgilerini güvenle güncellemelerini sağlayabilirsiniz.

Abonelik Fiyatı Değiştirilebilir mi?

Evet, $user->subscription('premium')->swap('price_new_id'); komutu ile kullanıcının mevcut abonelik planını kolayca yükseltebilir veya düşürebilirsiniz.

Ödeme Başarısız Olursa Ne Olur?

Stripe, ödeme başarısız olduğunda bir "invoice.payment_failed" webhook'u gönderir. Cashier bu durumu otomatik olarak yönetir; siz de bu webhook'u dinleyerek kullanıcıya e-posta gönderebilirsiniz.

Verilerim Güvende mi?

Evet, Stripe tüm kart verilerini kendi sunucularında saklar (PCI-DSS uyumlu). Sizin veritabanınızda sadece Stripe'ın sağladığı "token" veya "customer_id" bilgileri tutulur, bu da güvenlik riskini minimize eder.

Stripe Webhook Hata Ayıklama ve Loglama Stratejileri

Ödeme sistemlerinde en kritik nokta, Stripe'tan gelen bildirimlerin (webhook) doğru işlenip işlenmediğini takip etmektir. Bazen ağ hataları veya veritabanı kilitlenmeleri nedeniyle webhook'lar başarısız olabilir. Bu durumda Stripe, belirli bir süre boyunca tekrar deneme yapar; ancak uygulamanızın bu hataları loglaması, sorunu hızlıca tespit etmenizi sağlar.

Laravel'in varsayılan Log sınıfını kullanarak, gelen webhook isteklerini ve oluşan hataları kayıt altına alabilirsiniz. Özellikle App\Http\Middleware\VerifyCsrfToken içerisinde Stripe webhook rotalarını hariç tuttuğunuzdan emin olun.

// app/Http/Controllers/WebhookController.php
use Illuminate\Support\Facades\Log;

public function handleWebhook(Request $request)
{
    try {
        // Stripe'tan gelen payload'u işle
        $payload = $request->all();
        Log::info('Stripe Webhook Alındı: ' . $payload['type']);
        
        // İşlem mantığı...
        
    } catch (\Exception $e) {
        Log::error('Stripe Webhook Hatası: ' . $e->getMessage());
        return response()->json(['error' => 'İşlem başarısız'], 400);
    }
}

Stripe CLI ile Yerel Geliştirme Ortamında Test

Canlıya geçmeden önce Stripe webhook'larını yerel makinenizde test etmek, geliştirme sürecini hızlandırır. Stripe CLI, uygulamanıza gelen webhook olaylarını simüle etmenize ve kodunuzun bu olaylara nasıl tepki verdiğini görmenize olanak tanır.

Öncelikle Stripe CLI'ı bilgisayarınıza kurun ve ardından terminal üzerinden şu komutu çalıştırarak yerel sunucunuzu Stripe ile eşleştirin:

# Stripe CLI ile yerel sunucuyu dinlemeye başla
stripe listen --forward-to http://localhost:8000/stripe/webhook

# Belirli bir olayı tetikleyerek kodunuzu test edin
stripe trigger invoice.payment_succeeded

Bu yöntem, özellikle invoice.payment_succeeded veya customer.subscription.deleted gibi olayların veritabanınızda tetiklediği güncellemeleri anlık olarak görmenizi sağlar. Test aşamasında, Stripe Dashboard üzerindeki "Developers > Webhooks" sekmesinden gönderilen JSON yapısını inceleyerek, Laravel tarafındaki handle metodlarınızın bu yapıya uygun olup olmadığını doğrulayın.

İleri Düzey İpucu: Webhook Güvenliği

Webhook uç noktalarınızın sadece Stripe'tan gelen istekleri kabul ettiğinden emin olmak için Cashier tarafından sağlanan VerifyStripeSignature middleware'ini kullandığınızdan emin olun. Bu, kötü niyetli kişilerin sahte webhook istekleri göndererek abonelik durumlarını manipüle etmesini engeller.

// routes/web.php
Route::post(
    '/stripe/webhook',
    [WebhookController::class, 'handle']
)->middleware(\Laravel\Cashier\Http\Middleware\VerifyWebhookSignature::class);

Bu yapılandırma, Stripe'ın gönderdiği Stripe-Signature başlığını doğrular ve sadece güvenilir kaynaklardan gelen verilerin işlenmesini sağlar.

Sonuç

Laravel ile Stripe entegrasyonu, doğru araçlar kullanıldığında oldukça güvenli ve yönetilebilir bir süreçtir. Bu rehberde abonelik başlatma, kontrol etme, webhook yönetimi ve iptal süreçlerini adım adım işledik. Bir sonraki adım olarak, Stripe'ın "Customer Portal" özelliğini projenize entegre ederek kullanıcılarınıza kendi faturalarını yönetebilecekleri bir arayüz sunmanızı öneririm.

Sorumluluk Reddi: Bu makalede yer alan kod örnekleri eğitim amaçlıdır. Ödeme sistemleri hassas veriler içerir; üretim ortamına almadan önce mutlaka kapsamlı güvenlik testleri yapın ve Laravel'in resmi dökümantasyonunu düzenli olarak takip edin.
Bu yazıya tepkinizi paylaşın:
Selin Yılmaz

Verimlilik ve zaman yönetimi odaklı pratik bilgiler konusunda içerik üretiyorum. Okuyuculara günlük rutinlerinde hız kazandıracak uygulanabilir stratejiler sunuyorum.

Yorumlar (0)

Yorum Yaz