Flutter Uygulama İçi Satın Alma ve Ödeme Duvarları Genel Bakış
0:02:00RevenueCat Flutter SDK Codelab'ına hoş geldiniz!
Hedef: Bu Codelab'da RevenueCat Flutter SDK'yı yeni bir Flutter uygulamasına entegre etmeyi, ürün Offering'lerini almayı ve önceden oluşturulmuş yerel ödeme duvarı UI'ını göstermeyi öğreneceksiniz.
Oluşturulacak içerik:
Yükleme göstergesi gösteren ve RevenueCat'te yapılandırılmış "Offering"i aldıktan sonra PaywallView'ı gösteren basit tek ekranlı bir uygulama.
Ön Koşullar
Başlamadan önce aşağıdakilerin hazır olması gerekir:
- Flutter SDK: Flutter geliştirme ortamınız hazır olmalıdır.
- RevenueCat hesabı: revenuecat.com'da ücretsiz hesap gerekir.
- App Store / Play Store yapılandırması:
- App Store Connect veya Google Play Console'da oluşturulmuş uygulama içi ürünler (abonelik veya tek seferlik satın alma). Google Play yapılandırması hakkında daha fazla bilgi için Codelab1: RevenueCat Google Play Entegrasyonu'nu inceleyin.
- Ürünlerin RevenueCat panelindeki Entitlement ve Offering ile bağlantılı olması gerekir. Bu en önemli adımdır. "Current" Offering yoksa ödeme duvarı görüntülenmez.
- Gerçek cihaz veya yapılandırılmış emülatör: Uygulama içi satın alma testi için gereklidir.
Bu Codelab'ı tamamladığınızda, RevenueCat'in Flutter SDK'sını kullanarak Flutter uygulamanızda uygulama içi satın almaları başarıyla uygulayabilecek ve dinamik ödeme duvarları gösterebileceksiniz.
RevenueCat SDK İçe Aktarma
0:05:00Uygulama içi satın almayı uygulamadan önce, mevcut veya yeni projenize RevenueCat SDK'yı içe aktarmanız gerekir. Başlamak için pubspec.yaml dosyanıza aşağıdaki bağımlılığı ekleyin:
GitHub'da en son sürümü kontrol edebilirsiniz.
dependencies:
purchases_flutter: 9.2.3
purchases_ui_flutter: 9.2.3Aşağıdaki görüntüdeki gibi bu bağımlılığı eklediyseniz "Pub get" buton'e tıklayarak gerekli bağımlılıkları otomatik olarak indirebilirsiniz.
Şimdi RevenueCat SDK'yı başlatalım. Bu işlem main.dart dosyasında gerçekleştirilir.
lib/main.dartdosyasını açın ve tüm içeriği aşağıdaki kodla değiştirin.- API anahtarlarınızı
_androidApiKeyve_iosApiKeysabitine yapıştırın.
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:purchases_flutter/purchases_flutter.dart';
import 'dart:io' show Platform;
// --- burada REVENUECAT anahtarınızı yapıştırın ---
const String _androidApiKey = "goog_YOUR_KEY_HERE";
const String _iosApiKey = "appl_YOUR_KEY_HERE";
void main() async {
// Asenkron eklenti çağrılarından önce Flutter widget'ların başlatıldığından kontrol
WidgetsFlutterBinding.ensureInitialized();
// Uygulamayı çalıştırmadan önce RevenueCat SDK'yı başlat
await _initializeRevenueCat();
runApp(const MyApp());
}
Future<void> _initializeRevenueCat() async {
// Geliştirme için hata ayıklama günlüklerini etkinleştir
await Purchases.setLogLevel(LogLevel.debug);
PurchasesConfiguration? configuration;
if (Platform.isAndroid) {
configuration = PurchasesConfiguration(_androidApiKey);
} else if (Platform.isIOS) {
configuration = PurchasesConfiguration(_iosApiKey);
} else {
print("RevenueCat bu platform için yapılandırılmamış.");
return;
}
try {
await Purchases.configure(configuration);
print("RevenueCat başarıyla yapılandırıldı!");
} catch (e) {
print("RevenueCat yapılandırma hata: $e");
}
}
// ... Geri kalan kod sonraki adımda yazılacak ...async main fonksiyonu oluşturduk. Bu sayede _initializeRevenueCat fonksiyonunu await ederek UI oluşturulmadan önce RevenueCat SDK'nın yapılandırılıp hazır olmasını sağlıyoruz. Bu, başlangıçtan itibaren kullanılabilir olması gereken bir eklentiyi başlatmanın doğru yoludur.
Bununla uygulamanın %50'sini tamamladınız!
Yetkileri Doğrulama
0:03:00Şimdi kullanıcı yetkilerini nasıl doğrulayacağınızı öğrenelim.
Daha önce bahsedildiği gibi, yetkiler kullanıcının satın alma işleminden sonra kilidini açtığı erişim seviyelerini veya özellikleri temsil eder. Bu, reklam bannerı gösterip göstermeyeceğinizi veya premium erişim sağlayıp sağlamayacağınızı belirlemenize olanak tanır.
Aşağıdaki kod parçasını kullanarak kullanıcının aktif bir yetkiye sahip olup olmadığını kolayca kontrol edebilirsiniz:
const ENTITLEMENT_IDENTIFIER = ".."; // RevenueCat panelinden özel yetki tanımlayıcınızı alın
final customerInfo = await Purchases.getCustomerInfo();
final isEntitled = customerInfo.entitlements.active[ENTITLEMENT_IDENTIFIER]?.isActive;Kullanıcının belirli bir yetkiye sahip olup olmadığını doğruladıktan sonra, uygulamanızın iş modeline göre nasıl ilerleyeceğinize karar verebilirsiniz.
Örneğin, uygulamanız reklam destekliyse AdMob bannerını gösterebilir veya gizleyebilirsiniz. Alternatif olarak, kullanıcının premium özelliklerin veya içeriğin kilidini açması için bir ödeme duvarı veya satın alma diyaloğu gösterebilirsiniz.
İşte bu mantığı uygulamanın bir örneği:
if (isEntitled == true) {
// Kullanıcının bu yetkiye erişimi varsa banner göstermeye gerek yok.
} else {
// Burada banner arayüzünü veya ödeme duvarını gösterin
..
}Uygulama İçi Satın Alma Uygulama
0:04:00Şimdi reklamsız bir deneyim sağlamak için uygulama içi satın almayı uygulayalım. Başlamak için önce RevenueCat panelinden ilgili ürün bilgilerini almanız gerekir. Bu ürün verileri, kullanıcılara satın alma seçenekleri sunmak için kullanılacaktır.
Aşağıdaki örnekte gösterildiği gibi Purchases.sharedInstance.awaitGetProducts() çağırarak mevcut ürünleri alabilirsiniz:
// RevenueCat sunucusundan ürün bilgilerini alır
final List<StoreProduct> products = await Purchases.getProducts(['paywall_tester.subs']);
// Uygulama içi satın alma işlemini gerçekleştirir
final purchaseResult = await Purchases.purchaseStoreProduct(products.first);paywall_tester.subs:weekly, paywall_tester.subs:monthly, paywall_tester.subs:yearly gibi birden fazla ürün varyasyonu sunuyorsanız, productIds alanında temel ürün tanımlayıcısı olan paywall_tester.subs'yi kullanarak ürün aramayı basitleştirebilirsiniz. Bu şekilde RevenueCat, tüm ilgili ürün varyasyonlarını bir liste olarak alır ve ödeme duvarı arayüzünde dinamik olarak gösterebilirsiniz.
Ürün verilerini aldıktan sonra, Purchases.sharedInstance.awaitPurchase(product) çağırarak uygulama içi satın alma akışını başlatabilirsiniz. Bu otomatik olarak Google Play ödeme diyaloğunu tetikler ve kullanıcının uygulama içinde işlemi tamamlamasını sağlar.
Bununla sadece birkaç satır kodla tam işlevli bir uygulama içi satın alma akışını entegre ettiniz. Makbuzları, mağaza API'lerini veya satın alma doğrulamasını manuel olarak yönetmenin karmaşıklığıyla uğraşmanıza gerek yok.
Tam örnek kod aşağıdaki gibidir:
import 'package:flutter/services.dart';
import 'package:purchases_flutter/purchases_flutter.dart';
/// ID ile belirli bir ürünü alır ve satın alma akışını başlatır.
///
/// Bu fonksiyon ürün bulunamadığında, kullanıcı satın almayı iptal ettiğinde
/// veya diğer mağaza hataları gibi olası hataları işler.
Future<void> purchaseProduct() async {
// 1. Alınacak ürün tanımlayıcısını tanımlayın
const String productId = 'paywall_tester.subs';
try {
// 2. RevenueCat'de StoreProduct'yı alır
print('ürün alınıyor...');
final List<StoreProduct> products = await Purchases.getProducts([productId]);
// 3. ürün liste boş olmadığını kontrol eder
if (products.isEmpty) {
print('hata: ürün bulunamadı. ID'yi ve RevenueCat kurulumunu kontrol edin.');
// İsteğe bağlı olarak kullanıcıya hata mesajı gösterin
return;
}
final StoreProduct productToPurchase = products.first;
print('Ürün bulundu: ${productToPurchase.title}. Satın alma başlatılıyor...');
// 4. satın alma akışını başlatır
final PurchaseResult purchaseResult = await Purchases.purchaseStoreProduct(productToPurchase);
// 5. Satın almanın başarılı olup olmadığını kontrol etmek için entitlement'ı kontrol edin
// "your_premium_entitlement" kısmını RevenueCat'teki gerçek entitlement tanımlayıcınızla değiştirin
if (purchaseResult.customerInfo.entitlements.all["your_premium_entitlement"]?.isActive ?? false) {
print('Satın alma başarılı! Kullanıcı artık premium erişim yetkisine sahip.');
// premium içeriğe erişim izni verir
} else {
print('Satın alma tamamlandı ancak entitlement aktif edilmedi.');
}
} on PlatformException catch (e) {
// 6. olası hataları işler
final PurchasesErrorCode error = PurchasesErrorHelper.getErrorCode(e);
if (error == PurchasesErrorCode.purchaseCancelledError) {
print('Kullanıcı satın almayı iptal etti.');
} else {
print('satın alma başarısız hata: ${e.message}');
}
} catch (e) {
print('Beklenmeyen hata oluştu: $e');
}
}Ödeme Duvarı Uygulama
0:07:00Artık Dart'te Paywall'ı uygulama zamanı.
1adım: Uygulama Kabuğu Oluşturma
Şimdi varsayılan Flutter uygulama yapısını ekleyelim. Burada MyApp widget'ı ve nihayetinde ödeme duvarını barındıracak stateful MyHomePage widget'ı bulunur.
Aşağıdaki kodu lib/main.dart dosyasına ekleyin:
// lib/main.dart (devam)
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'RevenueCat Paywall Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'RevenueCat Paywall Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
// ... State sınıfı sonraki adımda yazılacak ...2adım: Offering Alma ve Durum Yönetimi
Bu temel mantıktır. _MyHomePageState'te RevenueCat'ten Offering'leri alır ve yükleme ile hata durumunu yönetir.
// ... State sınıfı... yorumu aşağıdaki tam _MyHomePageState sınıfıyla değiştirin:
// lib/main.dart (devam)
class _MyHomePageState extends State<MyHomePage> {
// durum değişken
Offering? _offering;
bool _isLoading = true;
String? _errorMessage;
@override
void initState() {
super.initState();
// Sayfa yüklenir yüklenmez offering'ı alır
_loadOfferings();
}
Future<void> _loadOfferings() async {
// setState çağırmadan önce widget'ın hala monte edilmiş olup olmadığını kontrol etmeniz gerekir
if (!mounted) return;
setState(() {
_isLoading = true;
_errorMessage = null; // Önceki hatayı temizler
});
try {
// RevenueCat'de şu anki offering'ı alır
final offerings = await Purchases.getOfferings();
// Asenkron çağrıdan sonra widget'ın hala monte edilmiş olup olmadığını kontrol edin
if (!mounted) return;
setState(() {
_offering = offerings.current;
_isLoading = false;
if (_offering == null) {
_errorMessage = "şu anki offering bulunamadı. RevenueCat panelini kontrol edin.";
}
});
} catch (e) {
if (!mounted) return;
setState(() {
_isLoading = false;
_errorMessage = "offering yükle başarısız: ${e.toString()}";
});
}
}
// build metodu son adımda yazılacak...
@override
Widget build(BuildContext context) {
// şimdilik yer tutucudur
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: const Center(child: Text("Neredeyse bitti!")),
);
}
}- Yükleme göstergesi için
_isLoading, hata göstermek için_errorMessageve ödeme duvarı verilerini tutmak için_offeringadlı üç durum değişkeni oluşturduk. -
initState'te veri alma işlemini başlatmak için_loadOfferings()'ı çağırdık. -
_loadOfferingsmetoduPurchases.getOfferings()çağrısınıtry...catchbloğu ile sarar. Yükleyiciyi gösterip/gizler ve alınan offering veya hata mesajını kaydetmek için durumu günceller.
3adım: PaywallView gösterme
Son olarak, durum değişkenine göre doğru UI'ı koşullu olarak göstermek için build metodunu güncelleyelim. Offering başarıyla yüklendiğinde PaywallView'ı gösterir.
_MyHomePageState'ın build metodunu bu tam sürümle değiştirin:
// lib/main.dart (_MyHomePageState içinde)
@override
Widget build(BuildContext context) {
Widget content;
// offering'yı alırken yükleme göstergesi gösterir
if (_isLoading) {
content = const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 20),
Text("Ödeme duvarı yükleniyor..."),
],
);
}
// Sorun oluştuğunda hata mesajını gösterir
else if (_errorMessage != null) {
content = Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
_errorMessage!,
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.red, fontSize: 16),
),
);
}
// Offering yüklendiğinde PaywallView'ı gösterir
else if (_offering != null) {
content = PaywallView(
offering: _offering!,
onDismiss: () => Navigator.pop(context),
onPurchaseCompleted: (customerInfo) {
print("Entitlement için satın alma tamamlandı: ${customerInfo.entitlements.active.keys.first}");
// buradan kapatabilir veya başka bir yere gidebiliryapabilirsiniz
},
onPurchaseError: (error) {
print("Satın alma hatası: ${error.message}");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("satın alma başarısız: ${error.message}")),
);
},
onRestoreCompleted: (customerInfo) {
print("Geri yükleme tamamlandı. aktif entitlement: ${customerInfo.entitlements.active.length}");
if (customerInfo.entitlements.active.isNotEmpty) {
Navigator.pop(context);
}
},
);
}
// düşük olasılıklı durum için yedek
else {
content = const Text("Mevcut offering bulunamadı.");
}
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: content,
),
);
}Tamamlandı!
Şimdi uygulamayı cihazda veya emülatörde çalıştırın.
flutter run- Yükleme göstergesiyle "Ödeme duvarı yükleniyor..." mesajı görüntülenir.
- Ardından aşağıdaki görseldeki gibi tam işlevsel yerel ödeme duvarı UI'ı görüntülenir.
Sorun Giderme
Ödeme duvarı görüntülenmiyorsa debug konsolunu kontrol edin ve aşağıdaki yaygın sorunları inceleyin: "şu anki offering bulunamadı": En yaygın hata. RevenueCat panelinde "current" offering olmadığı anlamına gelir. Offerings bölümüne gidin, offering'i seçin ve "current" olarak işaretlenmiş olduğunu kontrol edin. Hatalı API anahtarı: Test ettiğiniz platform için doğru public API anahtarını kopyaladığınızı tekrar kontrol edin. Ürün yapılandırılmamış: Mağaza konsolunda uygulama içi ürünlerin doğru şekilde kurulduğunu ve RevenueCat'te entitlement ve offering'e bağlı olduğunu kontrol edin. Sandbox/Test kullanıcısı sorunları: Sandbox test hesabıyla (iOS) giriş yaptığınızı veya lisans test kullanıcısı olarak eklendiğinizi (Android) kontrol edin.
Kurulum tamamlandı! Artık kullanıcı gerekli yetkiye sahip olmadığında, Ödeme Duvarı Düzenleyicisi'nde yapılandırdığınız tasarımla aynı şekilde ödeme duvarını gösterebilirsiniz.
Codelab: RevenueCat Google Play Entegrasyonu (Ödeme Duvarı Oluşturma)'nda zaten gördüğünüz gibi, ödeme duvarı sistemi sunucu tabanlı kullanıcı arayüzü ile oluşturulmuştur. Bu, uygulama güncellemesi göndermeden veya inceleme sürecinden geçmeden panelden doğrudan ödeme duvarının içeriğini ve tasarımını dinamik olarak güncelleyebileceğiniz anlamına gelir.
Son
Bu Codelab'de RevenueCat Flutter SDK'yı entegre etmeyi, uygulama içi satın almayı uygulamayı ve Flutter'de ödeme duvarı oluşturmayı öğrendiniz. Şimdi uygulamanızı yayınlama ve daha fazla gelir elde etme zamanı!
Aşağıdaki kaynakları kullanarak RevenueCat SDK kullanımı hakkında daha fazla bilgi edinebilirsiniz:
- Ürün Eğitimleri: RevenueCat'i kullanmaya başlamanıza ve en iyi şekilde yararlanmanıza yardımcı olacak video eğitimleri.