Flutter inAppPurchase entegrasyonu [Android]

Flutter uygulamalarında uygulama içi satın alma nasıl entegre edilir anlatacağım bu yazıda yalnızca Android için olan kısmı konu alacağım. Bir sonraki yazımda ise doğal olarak iOS tarafını ele alacağım. 🙂

Yazılan uygulamalarda premium satışı, harcanabilir ürünlerin satışı (uygulama içi kredi, puan vs.) ile geliştiriciler gelir elde edebilir. Ayrıca harcanamayan ürünlerle (reklamları kaldır, premium satın al vs.) ile de gelir elde edilebilir. Apple tarafında dört farklı satın alma tipi olmasına rağmen Android tarafında iki farklı satın alma çeşidi vardır: Tek seferlik satın almalar (INAPP – One time products) ve abonelikler (SUBS – Subscriptions) olarak adlandırılır.

Önemli! Bir uygulama içerisinde satın alma opsiyonunun açılması için Google Play’e yüklenmiş olması gerekiyor. Öncelikle uygulamanızı release edin ve istediğiniz sürüm şeklinde Google Play’e yükleyin.

Google Play’e yüklediğiniz sürüm onaylandıktan sonra menüden Monetise – Products – InApp Purchase kısmına gidin. Bu kısımda ekleyeceğiniz ürüne bir ID, isim, tanım ve fiyat belirleyin. Kendi yaptığım uygulamada, uygulamanın geliştirilmesinin desteklenmesi amacıyla harcanamayan ürün olarak bir ürün ekledim.

Kodlama

Sıra geldi uygulama içi satın almayı kodlamaya! Öncelikle in_app_purchase kütüphanesini uygulamamızın içerisine ekleyelim. Daha sonrasında main içerisinde IAP Connection açalım.

  WidgetsFlutterBinding.ensureInitialized();
  InAppPurchaseConnection.enablePendingPurchases();

Satın alma işlemi yaptıracağımız sayfanın State’i içerisinde bazı tanımlamalar yapalım.

  var productIds = {'support'}; // Eklediğimiz ürünlerin ID'leri
  InAppPurchaseConnection connection = InAppPurchaseConnection.instance; // IAP Instance değişkeni

  StreamSubscription<List<PurchaseDetails>> subscription; // Satın alma detaylarını içeren Stream

  List<ProductDetails> products = []; // Ürünlerimiz

Öncelikle ürünlerimizi çekelim ve products içerisine ekleyelim.

  initStoreInfo() async {
    print(
        'iap available: ${await InAppPurchaseConnection.instance.isAvailable()}');

    ProductDetailsResponse productDetailResponse =
        await connection.queryProductDetails(productIds);

    if (productDetailResponse.error == null) {
      setState(() {
        products = productDetailResponse.productDetails;
      });
    }
    print(productDetailResponse.notFoundIDs);
  }

Daha önce satın alınan ürünleri kullanıcının satın almamasını istiyorsanız veya neyi satın alıp almadığının verisini elde etmek ve kullanmak istiyorsanız bir purchaseUpdate fonksiyonu yazmalısınız.

  listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
    purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
      if (purchaseDetails.status == PurchaseStatus.pending) {
        // Satın alma detayı kontrol ediliyor...
      } else {
        if (purchaseDetails.status == PurchaseStatus.error) {
          // Satın alma verisi bulunamadı (restore purchase yapılamaz mesela)
        } else if (purchaseDetails.status == PurchaseStatus.purchased) {
          // daha önce satın alınan bir ürün veya şu an satın alınan bir ürün
        }
      }
    });
  }

Son olarak da ürün satın alma fonksiyonumuz. Benim yalnızca bir ürünüm olduğu için products[0] diyerek kısa kestim fakat bu fonksiyona parametre olarak kullanıcının hangi ürünü satın almak istediğini göndermelisiniz.

  buyProduct() {
    final PurchaseParam purchaseParam =
        PurchaseParam(productDetails: products[0]);
    connection.buyNonConsumable(purchaseParam: purchaseParam);
  }

initState içerisinde yazdığımız fonksiyonları çağıralım.

  @override
  void initState() {
    Stream purchaseUpdated =
        InAppPurchaseConnection.instance.purchaseUpdatedStream;

    subscription = purchaseUpdated.listen((purchaseDetailsList) {
      listenToPurchaseUpdated(purchaseDetailsList);
    }, onDone: () {
      subscription.cancel();
    }, onError: (error) {
      // hata
    });

    initStoreInfo();

    super.initState();
  }


Bir butonun içerisinde onPressed kısmında da buyProduct fonksiyonumu çağırıyorum. Test aşamasında olduğu için gerçekten satın almaz. Zaten şu an çalışmaması da muhtemel. Çünkü yeniden build alıp bunu yüklemeniz gerekiyor. 🙂 Daha sonrasında da fiziksel test cihazınızda satın alma fonksiyonunu deneyebilirsiniz.

Yazının sonuna geldik. Bir sonraki yazımda uygulama içi satın alma olayının iOS tarafını ele alacağım. O zamana kadar takipte kalın!


Okuyucuya Not

Merhaba okuyucu! Blogum son zamanlarda yüksek trafik almaya başladı ve bu durumdan memnunum fakat aynı zamanda siz ziyaretçileri tatmin edememekten endişeliyim. 🙂 Eğer yazılarım ile ilgili bir tavsiyeniz olursa mail adresimden bana ulaşabilir veya Twitter üzerinden direct message gönderebilirsiniz. Github’ta örnek olarak yaptığım projelere göz atmak isterseniz de bu linki kullanabilirsiniz. Umarım bu ziyaretinizle size bir şeyler katabilmişimdir.

Sağlıcakla kalın!