Yönetici Özeti
Ne Yapıyoruz?
Muzibu mobil uygulaması, mevcut web altyapısını kullanarak işletmelere kesintisiz müzik deneyimi sunacak. Backend'de 50+ API endpoint hazır durumda. Ek olarak 5 yeni modül geliştirilmesi gerekiyor.
Backend Mevcut Durum Analizi
YENİBasit Anlatım
Muzibu.com backend'i incelendi. Mobil uygulama için gerekli özelliklerin hangilerinin hazır, hangilerinin eksik olduğu belirlendi.
| Özellik | Durum | Detay |
|---|---|---|
| API Endpoints | ✓ HAZIR | 50+ endpoint: auth, songs, playlists, queue, favorites, ratings |
| Premium/Subscription API | ✓ HAZIR | isPremium(), subscription_expires_at, active/trial status |
| Device Registry | ✓ HAZIR | Fingerprint, device profiling, eski cihaz tespiti mevcut |
| Analytics | ⚠ KISMÎ | GTM + Pixel var, debug-log endpoint var, mobile events eksik |
| HLS/MP3 Streaming | ✓ HAZIR | HLS adaptive (32k-320k), MP3 fallback, signed URLs |
| Push Notification | ✗ YOK | Firebase/FCM entegrasyonu yok, modül gerekli |
| Social Login | ✗ YOK | Google/Facebook/Apple OAuth yok, modül gerekli |
| Download API | ✗ YOK | Şarkı indirme endpoint'i yok, modül gerekli |
| Payment Webhooks | ✗ YOK | Google Play/App Store webhook'ları yok |
| Offline Cache Sync | ✗ YOK | Offline veri senkronizasyon API'si yok |
Hazır Olanlar (Mobil Kullanabilir)
- •
/api/auth/*- Login, register, me - •
/api/muzibu/songs/*- Stream, serve - •
/api/muzibu/playlists/*- CRUD - •
/api/muzibu/queue/*- Initial, refill - •
/api/favorites/*- Toggle, list - •
/api/muzibu/device-profile- Kayıt
Geliştirilmesi Gereken
- •
/api/auth/social- OAuth login - •
/api/songs/{id}/download- İndirme - •
/api/push/register- FCM token - •
/api/webhooks/*- IAP webhooks - •
/api/sync/*- Offline sync - •
/api/app/version- Force update
Oluşturulacak Backend Modüller
YENİBasit Anlatım
Mobil uygulama için backend'e 5 yeni Laravel modülü eklenmesi gerekiyor. Bu modüller Modules/ klasörü altında oluşturulacak.
1. MobileAuth Modülü KRİTİK
Social login + mobil token yönetimi
Modules/MobileAuth/ ├── Config/config.php ├── Database/Migrations/ │ └── create_social_accounts_table.php ├── App/ │ ├── Http/Controllers/ │ │ ├── SocialLoginController.php │ │ └── MobileTokenController.php │ ├── Models/SocialAccount.php │ └── Services/ │ ├── GoogleAuthService.php │ ├── FacebookAuthService.php │ └── AppleAuthService.php └── routes/api.php
Endpoints:
POST/api/auth/social/googlePOST/api/auth/social/facebookPOST/api/auth/social/appleGET/api/auth/social/accountsDELETE/api/auth/social/{id}
Gerekli Paketler:
- •
laravel/socialite - •
socialiteproviders/apple
2. PushNotification Modülü KRİTİK
Firebase Cloud Messaging entegrasyonu
Modules/PushNotification/ ├── Config/ │ └── firebase.php ├── Database/Migrations/ │ └── create_device_tokens_table.php ├── App/ │ ├── Http/Controllers/ │ │ └── PushController.php │ ├── Models/DeviceToken.php │ ├── Services/ │ │ └── FirebaseService.php │ ├── Jobs/ │ │ └── SendPushNotification.php │ └── Notifications/ │ ├── NewSongNotification.php │ ├── SubscriptionExpiringNotification.php │ └── PlaylistUpdateNotification.php └── routes/api.php
Endpoints:
POST/api/push/registerPOST/api/push/unregisterGET/api/push/settingsPUT/api/push/settings
Notification Types:
- • Yeni şarkı eklendi
- • Abonelik 3 gün kaldı
- • Playlist güncellendi
- • Premium aktif oldu
3. MobileDownload Modülü KRİTİK
Şifreli şarkı indirme + DRM sistemi
Modules/MobileDownload/ ├── Config/config.php ├── Database/Migrations/ │ ├── create_user_downloads_table.php │ └── create_download_limits_table.php ├── App/ │ ├── Http/Controllers/ │ │ ├── DownloadController.php │ │ └── DownloadLimitController.php │ ├── Models/ │ │ ├── UserDownload.php │ │ └── DownloadLimit.php │ ├── Services/ │ │ ├── EncryptionService.php # AES-256 │ │ └── MzbFileService.php # .mzb format │ └── Middleware/ │ └── CheckDownloadLimit.php └── routes/api.php
Endpoints:
POST/api/songs/{id}/download-tokenGET/api/songs/{id}/downloadGET/api/downloads/myDELETE/api/downloads/{id}GET/api/downloads/limits
Özellikler:
- • AES-256-CBC şifreleme
- • User-specific key
- • .mzb custom format
- • Download limit (100 şarkı)
- • Expiry date embed
4. MobileSync Modülü ÖNEMLİ
Offline cache senkronizasyonu + delta sync
Modules/MobileSync/ ├── Config/config.php ├── Database/Migrations/ │ └── create_sync_logs_table.php ├── App/ │ ├── Http/Controllers/ │ │ └── SyncController.php │ ├── Models/SyncLog.php │ ├── Services/ │ │ ├── DeltaSyncService.php │ │ └── CachePackageService.php │ └── Resources/ │ ├── PlaylistSyncResource.php │ ├── SongSyncResource.php │ └── UserSyncResource.php └── routes/api.php
Endpoints:
GET/api/sync/fullGET/api/sync/delta?since=timestampGET/api/sync/playlistsGET/api/sync/favoritesPOST/api/sync/played
Senkronize Edilen:
- • Playlist listesi + şarkılar
- • Favori şarkılar
- • Kullanıcı profili
- • Subscription durumu
- • Son çalınan şarkılar
5. MobileWebhook Modülü ÖNEMLİ
Google Play & App Store webhook handlers
Modules/MobileWebhook/ ├── Config/config.php ├── Database/Migrations/ │ ├── create_iap_transactions_table.php │ └── create_webhook_logs_table.php ├── App/ │ ├── Http/Controllers/ │ │ ├── GooglePlayWebhookController.php │ │ └── AppStoreWebhookController.php │ ├── Models/ │ │ ├── IapTransaction.php │ │ └── WebhookLog.php │ ├── Services/ │ │ ├── GooglePlayVerificationService.php │ │ └── AppStoreVerificationService.php │ └── Jobs/ │ ├── ProcessGooglePlayNotification.php │ └── ProcessAppStoreNotification.php └── routes/api.php
Endpoints:
POST/api/webhooks/google-playPOST/api/webhooks/app-storePOST/api/iap/verifyGET/api/iap/transactions
İşlenen Events:
- • SUBSCRIPTION_PURCHASED
- • SUBSCRIPTION_RENEWED
- • SUBSCRIPTION_CANCELED
- • SUBSCRIPTION_EXPIRED
- • REFUND
Offline UI Cache Stratejisi
YENİProblem
Kullanıcı internetsizken şarkı dinleyebilir (indirdiklerini). Ama sayfaları nasıl gezecek? Playlist listesi, şarkı detayları, kapak resimleri... Bunlar olmadan uygulama kullanılamaz!
Çözüm: 3 Katmanlı Cache
1. SQLite
Yapısal veri: Playlist, şarkı metadata, kullanıcı bilgisi
2. Dosya Cache
Görseller: Album kapakları, artist resimleri (cached_network_image)
3. Audio Cache
İndirilen şarkılar: .mzb şifreli dosyalar
Veri Akışı
┌─────────────────────────────────────────────────────────────────────────┐
│ UYGULAMA AÇILIŞ │
└────────────────────────────────┬────────────────────────────────────────┘
│
┌────────────▼────────────┐
│ İnternet var mı? │
└────────────┬────────────┘
│ │
YES NO
│ │
┌───────────▼───────┐ ┌──▼─────────────────────┐
│ API'den çek │ │ SQLite'dan yükle │
│ → Playlists │ │ → cached_playlists │
│ → Songs │ │ → cached_songs │
│ → User Profile │ │ → cached_user │
└───────────┬───────┘ └──┬─────────────────────┘
│ │
┌───────────▼───────┐ │
│ SQLite'a kaydet │ │
│ (background) │ │
└───────────┬───────┘ │
│ │
└──────┬───────┘
│
┌──────────────────▼───────────────────┐
│ UI RENDER │
│ • Playlist listesi görünür │
│ • Şarkı detayları görünür │
│ • Kapak resimleri (cache'den) │
└──────────────────────────────────────┘
SQLite Şeması (Flutter)
// lib/database/app_database.dart // Playlists CREATE TABLE cached_playlists ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, description TEXT, cover_url TEXT, song_count INTEGER, updated_at INTEGER, synced_at INTEGER DEFAULT (strftime('%s','now')) ); // Songs (metadata only) CREATE TABLE cached_songs ( id INTEGER PRIMARY KEY, title TEXT NOT NULL, artist TEXT, album TEXT, duration INTEGER, cover_url TEXT, is_downloaded INTEGER DEFAULT 0, local_path TEXT, download_expires_at INTEGER, synced_at INTEGER DEFAULT (strftime('%s','now')) ); // Playlist-Song ilişkisi CREATE TABLE cached_playlist_songs ( playlist_id INTEGER, song_id INTEGER, position INTEGER, PRIMARY KEY (playlist_id, song_id) ); // Favorites CREATE TABLE cached_favorites ( song_id INTEGER PRIMARY KEY, added_at INTEGER ); // User profile cache CREATE TABLE cached_user ( id INTEGER PRIMARY KEY, name TEXT, email TEXT, avatar_url TEXT, is_premium INTEGER, subscription_expires_at INTEGER, synced_at INTEGER ); // Sync metadata CREATE TABLE sync_state ( key TEXT PRIMARY KEY, value TEXT, updated_at INTEGER );
Senkronizasyon Stratejisi
Full Sync (İlk açılış)
- •
GET /api/sync/full - • Tüm playlist, favoriler, profil
- • ~500KB - 2MB veri
- • WiFi'de background'da
Delta Sync (Her açılış)
- •
GET /api/sync/delta?since=1710xxx - • Sadece değişenler
- • ~5-50KB veri
- • Hızlı, düşük bant genişliği
Offline Modda Ekranlar
| Ekran | Online | Offline | Kaynak |
|---|---|---|---|
| Ana Sayfa | ✓ | ✓ | cached_playlists + cached_songs |
| Playlist Detay | ✓ | ✓ | cached_playlist_songs JOIN cached_songs |
| İndirilenler | ✓ | ✓ | cached_songs WHERE is_downloaded=1 |
| Favoriler | ✓ | ✓ | cached_favorites JOIN cached_songs |
| Now Playing | ✓ | ⚠ | Sadece indirilen şarkılar çalar |
| Arama | ✓ | ⚠ | Sadece cache'deki içerikte arama |
| Profil | ✓ | ✓ | cached_user |
| Abonelik Satın Al | ✓ | ✗ | İnternet gerekli |
API Request/Response Detayları
YENİPOST /api/auth/login
REQUEST
{
"email": "user@example.com",
"password": "secret123",
"device_id": "abc123xyz"
}
RESPONSE 200
{
"access_token": "eyJhbG...",
"token_type": "Bearer",
"expires_in": 86400,
"user": {
"id": 123,
"name": "Ahmet",
"email": "user@example.com",
"is_premium": true,
"subscription_expires_at": "2026-04-17T00:00:00Z"
}
}
POST /api/auth/social/google YENİ
REQUEST
{
"id_token": "eyJhbGciOiJSUzI1...",
"device_id": "abc123xyz",
"device_name": "iPhone 14"
}
RESPONSE 200
{
"access_token": "eyJhbG...",
"is_new_user": false,
"user": { ... }
}
POST /api/songs/{id}/download-token YENİ
REQUEST
Headers:
Authorization: Bearer {token}
Body: (empty)
RESPONSE 200
{
"status": "ready",
"download_url": "/api/songs/123/download?token=xyz",
"encryption_key": "a1b2c3d4e5f6...",
"expires_at": "2026-04-17T00:00:00Z",
"file_size": 4521984
}
ERROR RESPONSES
402- subscription_required (Premium değil)429- download_limit_exceeded (100 şarkı limiti)404- song_not_found
GET /api/sync/delta YENİ
REQUEST
GET /api/sync/delta?since=1710672000
Headers:
Authorization: Bearer {token}
RESPONSE 200
{
"server_time": 1710758400,
"changes": {
"playlists": {
"updated": [...],
"deleted": [45, 67]
},
"favorites": {
"added": [101, 102],
"removed": [55]
},
"user": {
"is_premium": true,
"subscription_expires_at": "..."
}
}
}
GET /api/user/subscription-status
REQUEST
Headers:
Authorization: Bearer {token}
RESPONSE 200
{
"is_premium": true,
"status": "active",
"plan": "monthly",
"expires_at": "2026-04-17T00:00:00Z",
"auto_renew": true,
"server_time": "2026-03-17T12:00:00Z"
}
Push Notification Sistemi
YENİBasit Anlatım
Kullanıcıya bildirim göndermek için Firebase Cloud Messaging (FCM) kullanılacak. Hem Android hem iOS için tek sistem.
Backend Kurulum
# .env FIREBASE_CREDENTIALS=storage/app/firebase-adminsdk.json FIREBASE_PROJECT_ID=muzibu-app # composer composer require kreait/laravel-firebase
Flutter Kurulum
# pubspec.yaml firebase_core: ^2.24.2 firebase_messaging: ^14.7.10 # Android android/app/google-services.json # iOS ios/Runner/GoogleService-Info.plist
Notification Payload Yapısı
{
"notification": {
"title": "Yeni Şarkılar Eklendi! 🎵",
"body": "Bu hafta 50 yeni şarkı eklendi. Keşfetmek için tıkla!"
},
"data": {
"type": "new_songs", // new_songs | subscription | playlist
"action": "open_discover", // Hangi sayfayı açacak
"playlist_id": null,
"deep_link": "muzibu://discover"
},
"android": {
"priority": "high",
"notification": {
"channel_id": "default",
"icon": "ic_notification"
}
},
"apns": {
"payload": {
"aps": {
"sound": "default",
"badge": 1
}
}
}
}
Bildirim Türleri
Haftada 1, yeni eklenen şarkılar
3 gün kala, 1 gün kala
Ödeme başarılı olduğunda
Favori playlist'e şarkı eklendiğinde
Test Stratejisi
YENİUnit Tests
Bağımsız fonksiyonlar
- • EncryptionService
- • CacheRepository
- • AudioUrlResolver
- • SubscriptionChecker
flutter testWidget Tests
UI bileşenleri
- • PlayerControls
- • PlaylistCard
- • SongListItem
- • DownloadButton
flutter test --tags widgetIntegration Tests
E2E senaryolar
- • Login → Play flow
- • Download → Offline play
- • Premium expiry
- • 15 saat çalışma
flutter drive15 Saat Dayanıklılık Testi (EN KRİTİK)
Uygulama 15 saat açık kaldığında memory leak olmamalı!
// integration_test/endurance_test.dart test('15 hour endurance test', () async { final startMemory = await getMemoryUsage(); for (int hour = 0; hour < 15; hour++) { // Simulate 1 hour of usage await playRandomSongs(count: 20); await switchPlaylists(count: 5); await toggleFavorites(count: 10); final currentMemory = await getMemoryUsage(); expect(currentMemory, lessThan(startMemory * 1.5)); } });
Erişilebilirlik (Accessibility)
YENİGörsel
- •
Semanticswidget kullanımı - • Minimum 4.5:1 contrast ratio
- • Büyük font desteği (textScaleFactor)
- • Dark/Light mode
Sesli
- • TalkBack (Android) desteği
- • VoiceOver (iOS) desteği
- • Tüm butonlara label
- • Slider değer okuma
CI/CD Pipeline
YENİÖnerilen: Codemagic
Flutter için optimize edilmiş CI/CD. Hem Android hem iOS build'i tek yerden.
# codemagic.yaml
workflows:
production:
triggering:
events: [push]
branch_patterns: [main]
scripts:
- flutter test
- flutter build appbundle --release
- flutter build ipa --release
publishing:
google_play:
credentials: $GPLAY_CREDENTIALS
track: production
app_store_connect:
api_key: $APP_STORE_KEY
submit_to_testflight: true
Store Yayın Gereksinimleri
YENİGoogle Play
- ☐ Privacy Policy URL
- ☐ App Icon (512x512)
- ☐ Feature Graphic (1024x500)
- ☐ Screenshots (min 2)
- ☐ Short description (80 char)
- ☐ Full description (4000 char)
- ☐ Content rating questionnaire
- ☐ Target audience declaration
- ☐ Data safety form
App Store
- ☐ Privacy Policy URL
- ☐ App Icon (1024x1024)
- ☐ Screenshots (6.5", 5.5" iPhone)
- ☐ iPad screenshots (if supporting)
- ☐ Description
- ☐ Keywords (100 char)
- ☐ Support URL
- ☐ Age rating
- ☐ App Privacy details
- ☐ Apple Sign-In (zorunlu!)
Güncellenmiş Yol Haritası (8 Faz)
Riskler & Çözümler
Memory Leak (15 saat)
Çözüm: Playlist limiti, buffer cleanup, isolate, memory profiling
Zayıf İnternet
Çözüm: HLS adaptive, 30sn buffer, fallback chain, offline cache
SQLite Büyümesi
Çözüm: Max 1000 şarkı cache, LRU eviction, vacuum
Dosya Kopyalama
Çözüm: AES-256 + user key + device binding + .mzb format
Özet
Backend'de 50+ API hazır. 5 yeni modül geliştirilecek. Offline-first mimari ile internetsiz kullanım sağlanacak.