Gereksinimler ve Ön Hazırlık
Bu projeyi hayata geçirmek için sisteminizde PHP 8.4 veya üzeri bir sürümün ve Laravel 12.x framework'ünün kurulu olması gerekmektedir. Veritabanı yönetimi için MySQL veya PostgreSQL kullanılması önerilir. Ayrıca, abonelik süreçlerini yönetmek için Laravel'in resmi paketi olan Laravel Cashier (Stripe tabanlı) kullanacağız.
- PHP 8.4+
- Laravel 12.x
- Composer (Paket yöneticisi)
- Stripe hesabı (Ödeme işlemleri için)
Kuruluma başlamadan önce terminalinizde projenizi oluşturduğunuzdan ve veritabanı bağlantı ayarlarınızı .env dosyasında yapılandırdığınızdan emin olun.
Veritabanı Şeması ve Planların Tanımlanması
Dinamik bir abonelik sistemi için ilk adım, planları ve kullanıcı aboneliklerini tutacak veritabanı tablolarını oluşturmaktır. Laravel Migration (veritabanı göçü) kullanarak plans tablosunu oluşturalım.
// Migration: Create plans table
Schema::create('plans', function (Blueprint $table) {
$table->id();
$table->string('name'); // Örn: Gold, Silver
$table->string('slug')->unique(); // URL dostu isim
$table->string('stripe_plan_id'); // Stripe üzerindeki plan ID
$table->decimal('price', 8, 2);
$table->integer('billing_interval_days');
$table->timestamps();
});
Bu tablo, abonelik paketlerinizin temelini oluşturur. stripe_plan_id alanı, ödeme sağlayıcınızla senkronizasyonu sağlar. Bu sayede veritabanı üzerinden planları dinamik olarak güncelleyebilir veya yeni planlar ekleyebilirsiniz.
Kullanıcı Modeline Abonelik Yeteneklerinin Eklenmesi
Laravel Cashier, User modelinize Billable trait'ini ekleyerek abonelik yönetimi için gerekli tüm metodları sağlar. Bu, kullanıcıların aktif aboneliklerini kontrol etmeyi ve ödeme geçmişlerini sorgulamayı kolaylaştırır.
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
// Kullanıcının aktif bir aboneliği olup olmadığını kontrol eder
public function isSubscribedTo($planName)
{
return $this->subscribed($planName);
}
}
Bu yapı, uygulamanızın farklı noktalarında $user->isSubscribedTo('gold') şeklinde basit kontroller yapmanıza olanak tanır. Bu yöntem, kodunuzun okunabilirliğini artırır ve karmaşık sorgulardan sizi kurtarır.
Abonelik Planları İçin Kontrolcü (Controller) Oluşturma
Kullanıcıların abonelik satın alma sürecini yönetmek için bir SubscriptionController oluşturmalıyız. Bu kontrolcü, ödeme formundan gelen veriyi işler ve Stripe üzerinden abonelik işlemini başlatır.
public function subscribe(Request $request, Plan $plan)
{
$request->user()->newSubscription('default', $plan->stripe_plan_id)
->checkout([
'success_url' => route('dashboard'),
'cancel_url' => route('plans.index'),
]);
}
checkout metodu, kullanıcıyı güvenli bir şekilde Stripe ödeme sayfasına yönlendirir. Ödeme başarılı olduğunda, Stripe uygulamanıza bir Webhook gönderir ve Laravel bu Webhook'u dinleyerek veritabanındaki abonelik durumunu günceller.
Abonelik Yönetimi Yöntemlerinin Karşılaştırılması
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Laravel Cashier | Hızlı entegrasyon, güvenli ödeme | Stripe bağımlılığı |
| Manuel Entegrasyon | Tam kontrol, düşük komisyon | Yüksek güvenlik riski, karmaşık bakım |
Güvenlik ve Yetkilendirme (Middleware)
Abonelik gerektiren sayfalara erişimi kısıtlamak için özel bir Middleware (ara katman) oluşturmalısınız. Bu, ödemesi olmayan kullanıcıların premium içeriklere erişmesini engeller.
public function handle(Request $request, Closure $next)
{
if ($request->user() && $request->user()->subscribed('default')) {
return $next($request);
}
return redirect()->route('plans.index')->with('error', 'Bu içeriğe erişmek için abonelik gereklidir.');
}
Güvenlik Uyarısı: Ödeme verilerini asla kendi veritabanınızda saklamayın. PCI-DSS uyumluluğu için her zaman Stripe veya benzeri bir ödeme sağlayıcısının sağladığı güvenli token sistemlerini kullanın. XSS saldırılarına karşı tüm kullanıcı girdilerini Blade şablonlarında
{{ $variable }}sözdizimi ile escape ederek yazdırın.
Sıkça Sorulan Sorular
Abonelik iptal süreçlerini nasıl yönetmeliyim?
Laravel Cashier ile $user->subscription('default')->cancel() metodunu kullanarak aboneliği kolayca iptal edebilirsiniz. Bu işlem, bir sonraki fatura dönemine kadar aboneliğin aktif kalmasını sağlar.
Farklı para birimleri ile çalışabilir miyim?
Evet, Stripe ayarlarınız üzerinden ve .env dosyanızdaki yapılandırmalarla farklı para birimlerini destekleyebilirsiniz. Ancak, veritabanınızda fiyatları saklarken kur değişimlerini göz önünde bulundurmalısınız.
Kullanıcı aboneliği bittiğinde verileri ne yapmalıyım?
Abonelik süresi dolduğunda verileri silmek yerine, kullanıcıyı bir "Free" plana düşürmek veya erişimini sınırlamak en iyi pratik olarak kabul edilir.
Webhook'lar neden gereklidir?
Webhook'lar, ödeme sağlayıcınızdan gelen asenkron bildirimleri dinler. Örneğin, kredi kartı reddedildiğinde sisteminizin otomatik olarak aboneliği durdurması için Webhook kullanımı zorunludur.
Test ortamında nasıl ödeme yapabilirim?
Stripe'ın sunduğu test kart numaralarını kullanarak, gerçek para çekilmeden tüm ödeme akışınızı test edebilirsiniz.
Abonelik Sistemlerinde Performans Optimizasyonu ve Önbellekleme
Dinamik abonelik sistemlerinde, her sayfa yüklemesinde veritabanına giderek kullanıcının abonelik durumunu kontrol etmek, özellikle yüksek trafikli uygulamalarda ciddi bir performans darboğazı yaratabilir. Laravel'in sunduğu önbellekleme mekanizmalarını kullanarak bu sorgu yükünü minimize edebilirsiniz.
Kullanıcının abonelik durumunu User modeli içerisinde bir metot olarak tanımlayıp, bu veriyi Redis veya Memcached üzerinde tutmak en verimli yöntemdir. Aşağıdaki örnekte, abonelik durumunun nasıl önbelleğe alınacağı gösterilmiştir:
public function isSubscribed()
{
return Cache::remember('user_sub_status_' . $this->id, 3600, function () {
return $this->subscriptions()->active()->exists();
});
}
Bu yapıyı kullandığınızda, abonelik durumu değiştiğinde (örneğin ödeme alındığında veya iptal edildiğinde) ilgili önbellek anahtarını temizlemeyi unutmamalısınız:
public function updateSubscriptionStatus($userId)
{
// Abonelik güncelleme işlemleri...
Cache::forget('user_sub_status_' . $userId);
}
Abonelik Süreçlerinde Hata Ayıklama (Debugging)
Ödeme sistemleri asenkron çalıştığı için (webhook'lar üzerinden), hataları takip etmek bazen zorlayıcı olabilir. Laravel'in Log sınıfını kullanarak, Stripe'tan gelen her isteği ve sistemin verdiği tepkiyi kayıt altına almanız, olası bir ödeme başarısızlığında sorunu hızlıca tespit etmenizi sağlar.
Webhook rotanızda gelen veriyi şu şekilde loglayabilirsiniz:
use Illuminate\Support\Facades\Log;
public function handleWebhook(Request $request)
{
$payload = $request->all();
Log::info('Stripe Webhook Alındı:', [
'event' => $payload['type'] ?? 'unknown',
'data' => $payload['data']['object']['id'] ?? 'N/A'
]);
// İşleme devam et...
}
Ayrıca, Stripe Dashboard üzerinde bulunan "Events" sekmesini kullanarak, başarısız olan webhook isteklerini tekrar tetikleyebilir ve uygulamanızın verdiği hata kodlarını inceleyebilirsiniz. Geliştirme aşamasında stripe listen --forward-to localhost:8000/stripe/webhook komutunu kullanarak yerel ortamınıza gelen istekleri canlı olarak izlemek, hata ayıklama sürecini büyük ölçüde hızlandıracaktır.
Önemli İpuçları ve En İyi Uygulamalar
- Grace Period (İzin Süresi): Kullanıcının ödemesi başarısız olduğunda aboneliği hemen kapatmak yerine, 3-5 günlük bir "grace period" tanımlayarak kullanıcıya ödeme bilgilerini güncellemesi için zaman tanıyın.
- Veri Tutarlılığı: Veritabanınızdaki abonelik tablosu ile Stripe üzerindeki verilerin eşleştiğinden emin olmak için günlük "cron job"lar ile senkronizasyon kontrolleri yapın.
- Güvenlik: Webhook uç noktalarınızın sadece Stripe'tan gelen istekleri kabul ettiğinden emin olmak için imza doğrulama (signature verification) yöntemini mutlaka aktif edin.
Sonuç
Laravel ile dinamik bir abonelik sistemi kurmak, Cashier gibi güçlü araçlar sayesinde oldukça verimli bir süreçtir. Bu rehberde, veritabanı tasarımından başlayarak, kullanıcı yetkilendirme ve ödeme entegrasyonuna kadar kritik adımları inceledik. Bir sonraki adım olarak, Stripe Webhook'larını detaylıca yapılandırarak abonelik yenileme ve iptal süreçlerini tam otomatize etmeyi deneyebilirsiniz.
Sorumluluk Reddi: Bu makalede paylaşılan kodlar eğitim amaçlıdır. Canlıya almadan önce ödeme sisteminizin güvenliğini ve veri gizliliği politikalarınızı bir güvenlik uzmanına onaylatmanız önemle tavsiye edilir.


Yorumlar (0)
Yorum Yaz