Google Play Faturalandırma Kitaplığı'nı uygulamanıza entegre etme

Bu belgede, ürün satmaya başlamak için Google Play Faturalandırma Kitaplığı'nı uygulamanıza nasıl entegre edeceğiniz açıklanmaktadır.

Satın alma ömrü

Tek seferlik satın alma veya abonelik için tipik bir satın alma akışını burada görebilirsiniz.

  1. Kullanıcıya satın alabileceği ürünleri gösterin.
  2. Kullanıcının satın alma işlemini kabul etmesi için satın alma akışını başlatın.
  3. Satın alma işlemini sunucunuzda doğrulayın.
  4. Kullanıcıya içerik verme
  5. İçeriğin teslim edildiğini onaylayın. Tüketilebilir ürünlerde, kullanıcının öğeyi tekrar satın alabilmesi için satın alma işlemini tüketin.

Abonelikler iptal edilene kadar otomatik olarak yenilenir. Abonelik aşağıdaki durumlardan geçebilir:

  • Etkin: Kullanıcı, aboneliğe erişebilir ve abonelikle ilgili herhangi bir sorun yoktur.
  • İptal edildi: Kullanıcı iptal etti ancak son kullanma tarihine kadar erişimi devam ediyor.
  • Ek süre içinde: Kullanıcı, ödeme sorunu yaşamasına rağmen Google ödeme yöntemini tekrar denerken erişime devam edebilir.
  • Beklemede: Kullanıcı, ödeme sorunu yaşadı ve Google ödeme yöntemini tekrar denerken erişimi kaybetti.
  • Duraklatıldı: Kullanıcı, erişimini duraklattı ve devam ettirene kadar erişimi yok.
  • Süresi doldu: Kullanıcı, aboneliği iptal etti ve aboneliğe erişimini kaybetti. Kullanıcının aboneliği sona erdiğinde müşteri kaybı olarak kabul edilir.

Google Play ile bağlantı başlatma

Google Play'in faturalandırma sistemiyle entegrasyonun ilk adımı, uygulamanıza Google Play Faturalandırma Kitaplığı'nı eklemek ve bağlantıyı başlatmaktır.

Google Play Faturalandırma Kitaplığı bağımlılığını ekleme

Google Play Faturalandırma Kitaplığı bağımlılığını, uygulamanızın build.gradle dosyasına aşağıdaki gibi ekleyin:

Groovy

dependencies {
    def billing_version = "8.0.0"

    implementation "com.android.billingclient:billing:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "8.0.0"

    implementation("com.android.billingclient:billing:$billing_version")
}

Kotlin kullanıyorsanız Google Play Faturalandırma Kitaplığı KTX modülü, Google Play Faturalandırma Kitaplığı'nı kullanırken deyimsel Kotlin yazmanızı sağlayan Kotlin uzantıları ve eş yordam desteği içerir. Bu uzantıları projenize dahil etmek için uygulamanızın build.gradle dosyasına aşağıdaki bağımlılığı gösterildiği gibi ekleyin:

Groovy

dependencies {
    def billing_version = "8.0.0"

    implementation "com.android.billingclient:billing-ktx:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "8.0.0"

    implementation("com.android.billingclient:billing-ktx:$billing_version")
}

BillingClient'ı başlatma

Google Play Faturalandırma Kitaplığı'na bağımlılık ekledikten sonra BillingClient örneğini başlatmanız gerekir. BillingClient, Google Play Faturalandırma Kitaplığı ile uygulamanızın geri kalanı arasındaki iletişim için kullanılan ana arayüzdür. BillingClient, birçok yaygın faturalandırma işlemi için hem senkron hem de asenkron kolaylık yöntemleri sağlar. Aşağıdakileri not edin:

  • Tek bir etkinlik için birden fazla PurchasesUpdatedListener geri çağırma işlemi olmasını önlemek amacıyla aynı anda yalnızca bir etkin BillingClient bağlantısı açmanız önerilir.
  • Uygulamanızın satın alma işlemlerini zamanında işlemesini sağlamak için uygulamanız başlatıldığında veya ön plana geldiğinde BillingClient için bağlantı başlatmanız önerilir. Bu, ActivityLifecycleCallbacks tarafından kaydedilen registerActivityLifecycleCallbacks kullanılarak ve bir etkinliğin devam ettirildiğini ilk kez algıladığınızda bağlantıyı başlatmak için onActivityResumed dinlenerek yapılabilir. Bu en iyi uygulamanın neden izlenmesi gerektiği hakkında daha fazla bilgi için satın alma işlemlerini işleme bölümüne bakın. Ayrıca, uygulamanız kapatıldığında bağlantıyı sonlandırmayı unutmayın.

BillingClient oluşturmak için newBuilder kullanın. newBuilder() işlevine herhangi bir bağlam iletebilirsiniz ve BillingClient, uygulama bağlamı almak için bu bağlamı kullanır. Bu nedenle, bellek sızıntıları konusunda endişelenmenize gerek yoktur. Satın alma işlemleriyle ilgili güncellemeleri almak için setListener'ı da aramanız ve PurchasesUpdatedListener'a referans iletmeniz gerekir. Bu dinleyici, uygulamanızdaki tüm satın alma işlemleriyle ilgili güncellemeleri alır.

Kotlin

private val purchasesUpdatedListener =
   PurchasesUpdatedListener { billingResult, purchases ->
       // To be implemented in a later section.
   }

private var billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   // Configure other settings.
   .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // To be implemented in a later section.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    // Configure other settings.
    .build();

Google Play'e bağlanma

BillingClient oluşturduktan sonra Google Play ile bağlantı kurmanız gerekir.

Google Play'e bağlanmak için startConnection numaralı telefonu arayın. Bağlantı süreci eşzamansızdır ve istemcinin kurulumu tamamlanıp başka istekler göndermeye hazır olduğunda geri arama almak için BillingClientStateListener uygulamanız gerekir.

Google Play ile bağlantı kaybını yönetmek için yeniden deneme mantığı da uygulamanız gerekir. Yeniden deneme mantığını uygulamak için onBillingServiceDisconnected() geri çağırma yöntemini geçersiz kılın ve BillingClient'ın, başka istekte bulunmadan önce Google Play'e yeniden bağlanmak için startConnection() yöntemini çağırdığından emin olun.

Aşağıdaki örnekte, bağlantının nasıl başlatılacağı ve kullanıma hazır olup olmadığının nasıl test edileceği gösterilmektedir:

Kotlin

billingClient.startConnection(object : BillingClientStateListener {
    override fun onBillingSetupFinished(billingResult: BillingResult) {
        if (billingResult.responseCode ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    override fun onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
})

Java

billingClient.startConnection(new BillingClientStateListener() {
    @Override
    public void onBillingSetupFinished(BillingResult billingResult) {
        if (billingResult.getResponseCode() ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    @Override
    public void onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
});

Bağlantıyı Otomatik Olarak Yeniden Kurma

8.0.0 sürümünde BillingClient.Builder'e enableAutoServiceReconnection() yöntemi eklendiğinden Play Faturalandırma Kitaplığı, hizmet bağlantısı kesilmişken bir API çağrısı yapılması durumunda artık hizmet bağlantısını otomatik olarak yeniden kurabilir. Yeniden bağlantı, API çağrısı yapılmadan önce dahili olarak işlendiğinden bu durum, SERVICE_DISCONNECTED yanıtlarında azalmaya neden olabilir.

Otomatik yeniden bağlanmayı etkinleştirme

BillingClient örneği oluştururken otomatik yeniden bağlanmayı etkinleştirmek için BillingClient.Builder içinde enableAutoServiceReconnection() yöntemini kullanın.

Kotlin

val billingClient = BillingClient.newBuilder(context)
    .setListener(listener)
    .enablePendingPurchases()
    .enableAutoServiceReconnection() // Add this line to enable reconnection
    .build()

Java

BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(listener)
    .enablePendingPurchases()
    .enableAutoServiceReconnection() // Add this line to enable reconnection
    .build();

Satın alınabilecek ürünleri gösterme

Google Play ile bağlantı kurduktan sonra, mevcut ürünlerinizle ilgili sorgu göndermeye ve bunları kullanıcılarınıza göstermeye hazırsınız.

Ürün ayrıntıları için sorgu göndermek, ürünlerinizi kullanıcılarınıza göstermeden önce önemli bir adımdır. Bu adım, yerelleştirilmiş ürün bilgilerini döndürür. Abonelikler için ürün gösteriminizin tüm Play politikalarına uygun olduğunu doğrulayın.

Tek seferlik ürün ayrıntılarını sorgulamak için queryProductDetailsAsync yöntemini çağırın. Bu yöntem, tek seferlik ürün yapılandırmanıza bağlı olarak birden fazla fırsat döndürebilir. Daha fazla bilgi için Tek seferlik ürünler için birden fazla satın alma seçeneği ve teklif başlıklı makaleyi inceleyin.

Asenkron işlemin sonucunu işlemek için ProductDetailsResponseListener arayüzünü uygulayan bir dinleyici de belirtmeniz gerekir. Ardından, aşağıdaki örnekte gösterildiği gibi, sorgu tamamlandığında dinleyiciyi bilgilendiren onProductDetailsResponse işlevini geçersiz kılabilirsiniz:

Kotlin

val queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build()

billingClient.queryProductDetailsAsync(queryProductDetailsParams) {
    billingResult,
    queryProductDetailsResult ->
      if (billingResult.getResponseCode() == BillingResponseCode.OK) {
               for (ProductDetails productDetails : queryProductDetailsResult.getProductDetailsList()) {
                 // Process successfully retrieved product details here.
               }

               for (UnfetchedProduct unfetchedProduct : queryproductDetailsResult.getUnfetchedProductList()) {
                 // Handle any unfetched products as appropriate.
               }
            }
}

Java

QueryProductDetailsParams queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build();

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
        public void onProductDetailsResponse(BillingResult billingResult,
                QueryProductDetailsResult queryProductDetailsResult) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
               for (ProductDetails productDetails : queryProductDetailsResult().getProductDetailsList()) {
                 // Process success retrieved product details here.
               }

               for (UnfetchedProduct unfetchedProduct : queryproductDetailsResult.getUnfetchedProductList()) {
                 // Handle any unfetched products as appropriate.
               }
            }
        }
    }
)

Ürün ayrıntılarını sorgularken Google Play Console'da oluşturulan ürün kimliği dizelerinin listesini belirten bir QueryProductDetailsParams örneğini ProductType ile birlikte iletin. ProductType, tek seferlik ürünler için ProductType.INAPP, abonelikler için ise ProductType.SUBS olabilir.

Kotlin uzantılarıyla sorgulama

Kotlin uzantılarını kullanıyorsanız queryProductDetails() uzantı işlevini çağırarak tek seferlik ürün ayrıntılarını sorgulayabilirsiniz.

queryProductDetails(), ayrı bir dinleyici tanımlamanıza gerek kalmaması için Kotlin eşyordamlarından yararlanır. Bunun yerine, sorgulama tamamlanana kadar işlev askıya alınır. Ardından sonucu işleyebilirsiniz:

suspend fun processPurchases() {
    val productList = listOf(
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId("product_id_example")
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    )
    val params = QueryProductDetailsParams.newBuilder()
    params.setProductList(productList)

    // leverage queryProductDetails Kotlin extension function
    val productDetailsResult = withContext(Dispatchers.IO) {
        billingClient.queryProductDetails(params.build())
    }

    // Process the result.
}

Nadiren de olsa bazı cihazlar, genellikle Google Play Hizmetleri'nin eski sürümlerinden dolayı ProductDetails ve queryProductDetailsAsync()'yi destekleyemez. Bu senaryoyu düzgün şekilde desteklemek için Play Faturalandırma Kitaplığı 7'ye geçiş kılavuzundaki geriye dönük uyumluluk özelliklerini nasıl kullanacağınızı öğrenin.

Sonucu işleme

Google Play Faturalandırma Kitaplığı, sorgu sonuçlarını QueryProductDetailsResult nesnesinde saklar. QueryProductDetailsResult ProductDetails nesnelerinin List öğesini içeriyor. Ardından, başarıyla getirilen tek seferlik bir ürünle ilgili alakalı bilgileri (ör. fiyatı veya açıklaması) görüntülemek için listedeki her ProductDetails nesnesinde çeşitli yöntemleri çağırabilirsiniz. Kullanılabilir ürün ayrıntıları bilgilerini görüntülemek için ProductDetails sınıfındaki yöntemlerin listesine bakın.

QueryProductDetailsResult, UnfetchedProduct nesnelerinin List öğesini de içerir. Ardından, getirme hatası nedenine karşılık gelen bir durum kodu almak için her bir UnfetchedProduct'a sorgu gönderebilirsiniz. Kullanılabilir ancak getirilmemiş ürün bilgilerini görüntülemek için UnfetchedProduct sınıfındaki yöntemlerin listesine bakın.

Bir öğeyi satışa sunmadan önce kullanıcının bu öğeye sahip olup olmadığını kontrol edin. Kullanıcının öğe kitaplığında hâlâ bulunan bir tüketilebilir öğe varsa bu öğeyi tekrar satın alabilmesi için tüketmesi gerekir.

Abonelik teklif etmeden önce kullanıcının zaten abone olmadığını doğrulayın. Ayrıca aşağıdakileri de göz önünde bulundurun:

  • Abonelikler için queryProductDetailsAsync() yöntemi, abonelik ürünü ayrıntılarını ve abonelik başına en fazla 50 kullanıcıya uygun teklifi döndürür. Kullanıcı uygun olmayan bir teklifi satın almaya çalışırsa (örneğin, uygulama uygun tekliflerin güncel olmayan bir listesini gösteriyorsa) Play, kullanıcının uygun olmadığını bildirir ve kullanıcı bunun yerine temel planı satın almayı seçebilir.

  • Tek seferlik ürünler için queryProductDetailsAsync() yöntemi yalnızca kullanıcıya uygun teklifleri döndürür. Kullanıcı, uygun olmadığı bir teklifi satın almaya çalışırsa (örneğin, satın alma miktarı sınırına ulaşmışsa) Play, kullanıcıya uygun olmadığını bildirir ve kullanıcı bunun yerine satın alma seçeneği teklifini satın almayı tercih edebilir.

Satın alma akışını başlatma

Uygulamanızdan satın alma isteği başlatmak için uygulamanızın ana iş parçacığından launchBillingFlow() yöntemini çağırın. Bu yöntem, queryProductDetailsAsync çağrısından elde edilen ilgili ProductDetails nesnesini içeren bir BillingFlowParams nesnesine referans alır. BillingFlowParams nesnesi oluşturmak için BillingFlowParams.Builder sınıfını kullanın.

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...;

val productDetailsParamsList = listOf(
    BillingFlowParams.ProductDetailsParams.newBuilder()
        // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
        .setProductDetails(productDetails)
        // Get the offer token:
        // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList()
        // for a list of offers that are available to the user.
        // b. For subscriptions, call ProductDetails.subscriptionOfferDetails()
        // for a list of offers that are available to the user.
        .setOfferToken(selectedOfferToken)
        .build()
)

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build()

// Launch the billing flow
val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Java

// An activity reference from which the billing flow will be launched.
Activity activity = ...;

ImmutableList<ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // Get the offer token:
            // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList()
            // for a list of offers that are available to the user.
            // b. For subscriptions, call ProductDetails.subscriptionOfferDetails()
            // for a list of offers that are available to the user.
            .setOfferToken(selectedOfferToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

launchBillingFlow() yöntemi, BillingClient.BillingResponseCode bölümünde listelenen çeşitli yanıt kodlarından birini döndürür. Satın alma akışının başlatılmasında hata olmadığını doğrulamak için bu sonucu kontrol ettiğinizden emin olun. BillingResponseCode OK, başarılı bir lansmanı gösterir.

launchBillingFlow() başarılı bir şekilde çağrıldığında sistem, Google Play satın alma ekranını gösterir. Şekil 1'de bir abonelik için satın alma ekranı gösterilmektedir:

Google Play satın alma ekranında, satın alınabilir bir abonelik gösteriliyorsa
1. şekil. Google Play satın alma ekranında, satın alınabilecek bir abonelik gösteriliyor.

Google Play, satın alma işleminin sonucunu onPurchasesUpdated() arayüzünü uygulayan bir dinleyiciye iletmek için PurchasesUpdatedListener işlevini çağırır. Dinleyici, istemcinizi başlattığınızda setListener() yöntemi kullanılarak belirtilir.

Olası yanıt kodlarını işlemek için onPurchasesUpdated() kodunu uygulamanız gerekir. Aşağıdaki örnekte onPurchasesUpdated() değerinin nasıl geçersiz kılınacağı gösterilmektedir:

Kotlin

override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
   if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) {
       for (purchase in purchases) {
           // Process the purchase as described in the next section.
       }
   } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
       // Handle an error caused by a user canceling the purchase flow.
   } else {
       // Handle any other error codes.
   }
}

Java

@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
    if (billingResult.getResponseCode() == BillingResponseCode.OK
        && purchases != null) {
        for (Purchase purchase : purchases) {
            // Process the purchase as described in the next section.
        }
    } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
        // Handle an error caused by a user canceling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

Başarılı bir satın alma işlemi, Şekil 2'deki gibi bir Google Play satın alma işlemi başarı ekranı oluşturur.

Google Play&#39;in satın alma işlemi başarıyla tamamlandı ekranı
Şekil 2. Google Play'in satın alma işlemi başarılı ekranı.

Başarılı bir satın alma işlemi, kullanıcıyı ve satın alınan tek seferlik ürünün ürün kimliğini temsil eden benzersiz bir tanımlayıcı olan satın alma jetonu da oluşturur. Uygulamalarınız satın alma jetonunu yerel olarak depolayabilir. Ancak, jetonu güvenli arka uç sunucunuza aktarmanızı önemle tavsiye ederiz. Bu sayede satın alma işlemini doğrulayabilir ve sahtekarlığa karşı koruma sağlayabilirsiniz. Bu süreç, Satın Alma İşlemlerini Algılama ve İşleme başlıklı makalede daha ayrıntılı olarak açıklanmaktadır.

Kullanıcıya, sipariş kimliği veya işlemin benzersiz kimliğini içeren bir işlem makbuzu da e-postayla gönderilir. Kullanıcılar, her tek seferlik ürün satın alma işlemi, ilk abonelik satın alma işlemi ve sonraki yinelenen otomatik yenilemeler için benzersiz bir sipariş kimliği içeren bir e-posta alır. Google Play Console'da geri ödemeleri yönetmek için sipariş kimliğini kullanabilirsiniz.

Kişiselleştirilmiş bir fiyat belirtme

Uygulamanız Avrupa Birliği'ndeki kullanıcılara dağıtılabiliyorsa launchBillingFlow yöntemini çağırırken setIsOfferPersonalized() yöntemini kullanarak kullanıcılara bir öğenin fiyatının otomatik karar verme kullanılarak kişiselleştirildiğini bildirin.

Fiyatın kullanıcı için özelleştirildiğini belirten Google Play satın alma ekranı.
3.şekil Fiyatın kullanıcıya göre özelleştirildiğini belirten Google Play satın alma ekranı.

DSA Madde 21(2) Kullanıcılara sunduğunuz fiyatın kişiselleştirilmiş olup olmadığını belirlemek için lütfen Tüketici Hakları Yönergesi'nin 2011/83/EU 6. (1) (ea) maddesine bakın.

setIsOfferPersonalized(), Boole girişi alır. true olduğunda Play kullanıcı arayüzünde açıklama yer alır. false olduğunda kullanıcı arayüzünde açıklama atlanır. Varsayılan değer false'dir.

Daha fazla bilgi için Tüketici Yardım Merkezi'ni ziyaret edin.

Kullanıcı tanımlayıcıları ekleme

Satın alma akışını başlattığınızda uygulamanız, satın alma işlemini yapan kullanıcı için sahip olduğunuz tüm kullanıcı tanımlayıcılarını obfuscatedAccountId veya obfuscatedProfileId kullanarak ekleyebilir. Örnek bir tanımlayıcı, sisteminizdeki kullanıcının girişinin karartılmış bir sürümü olabilir. Bu parametreleri ayarlamak Google'ın sahtekarlığı tespit etmesine yardımcı olabilir. Ayrıca, kullanıcılara hak verme bölümünde bahsedildiği gibi satın alma işlemlerinin doğru kullanıcıya atfedilmesini sağlamanıza yardımcı olabilir.

Satın alma işlemlerini algılama ve işleme

Bu bölümde açıklanan satın alma işleminin algılanması ve işlenmesi, promosyon kullanımları gibi uygulama dışı satın alma işlemleri de dahil olmak üzere tüm satın alma türleri için geçerlidir.

Uygulamanız, yeni satın alma işlemlerini ve tamamlanan beklemedeki satın alma işlemlerini aşağıdaki yöntemlerden biriyle algılar:

  1. Uygulamanızın onPurchasesUpdated'ı çağırması sonucu launchBillingFlow çağrıldığında (önceki bölümde ele alındığı gibi) veya uygulamanız, uygulama dışında yapılan bir satın alma işlemi olduğunda ya da bekleyen bir satın alma işlemi tamamlandığında etkin bir Faturalandırma Kitaplığı bağlantısıyla çalışıyorsa. Örneğin, bir aile üyesi başka bir cihazda bekleyen bir satın alma işlemini onayladığında.
  2. Uygulamanız, kullanıcının satın alma işlemlerini sorgulamak için queryPurchasesAsync'i çağırdığında.

1 numaralı durumda, uygulamanız çalıştığı ve etkin bir Google Play Faturalandırma Kitaplığı bağlantısı olduğu sürece yeni veya tamamlanmış satın alma işlemleri için onPurchasesUpdated otomatik olarak çağrılır. Uygulamanız çalışmıyorsa veya uygulamanızda etkin bir Google Play Faturalandırma Kitaplığı bağlantısı yoksa onPurchasesUpdated çağrılmaz. Uygulamanızın zamanında satın alma güncellemeleri alabilmesi için uygulama ön planda olduğu sürece etkin bir bağlantı sürdürmeye çalışması önerilir.

2. adımda, uygulamanızın tüm satın alma işlemlerini işlediğinden emin olmak için BillingClient.queryPurchasesAsync() işlevini çağırmanız gerekir. Bunu, uygulamanız Google Play Faturalandırma Kitaplığı ile başarılı bir şekilde bağlantı kurduğunda yapmanız önerilir (Bu, uygulamanız başlatıldığında veya BillingClient'ı başlatma bölümünde bahsedildiği gibi ön plana geldiğinde önerilir). Bu, onServiceConnected için başarılı bir sonuç alındığında queryPurchasesAsync çağrılarak yapılabilir. Bu öneriye uymak, aşağıdaki gibi etkinlikleri ve durumları ele almak için çok önemlidir:

  • Satın alma işlemi sırasında ağ sorunları: Kullanıcı başarılı bir satın alma işlemi yapıp Google'dan onay alabilir ancak cihazı ve uygulamanız PurchasesUpdatedListener üzerinden satın alma işlemi bildirimi almadan önce cihazının ağ bağlantısı kesilir.
  • Birden fazla cihaz: Kullanıcılar bir cihazda satın aldıkları öğeyi cihaz değiştirdiklerinde görmeyi bekleyebilir.
  • Uygulamanızın dışında yapılan satın alma işlemlerini yönetme: Promosyon kullanımları gibi bazı satın alma işlemleri uygulamanızın dışında yapılabilir.
  • Satın alma durumu geçişlerini işleme: Kullanıcı, uygulamanız çalışmıyorken BEKLEMEDE olan bir satın alma işleminin ödemesini tamamlayabilir ve uygulamanızı açtığında satın alma işlemini tamamladığına dair onay almayı bekleyebilir.

Uygulamanız yeni veya tamamlanmış bir satın alma işlemi algıladığında:

  • Satın alma işlemini doğrulayın.
  • Tamamlanan satın alma işlemleri için kullanıcıya içerik erişimi verme
  • Kullanıcıyı bilgilendirin.
  • Uygulamanızın tamamlanan satın alma işlemlerini işlediğini Google'a bildirin.

Bu adımlar, aşağıdaki bölümlerde ayrıntılı olarak açıklanmıştır. Ardından, tüm adımların özetlendiği bir bölüm yer almaktadır.

Satın alma işlemini doğrulama

Uygulamanız, kullanıcılara avantajlar sunmadan önce her zaman satın alma işlemlerinin geçerliliğini doğrulamalıdır. Bu işlem, Hak vermeden önce satın alma işlemlerini doğrulama başlıklı makalede açıklanan yönergeler izlenerek yapılabilir. Uygulamanız, satın alma işlemini yalnızca doğruladıktan sonra işlemeye devam etmeli ve kullanıcıya yetki vermelidir. Bu konu, sonraki bölümde ele alınmaktadır.

Kullanıcıya yararlanma hakkı verme

Uygulamanız bir satın alma işlemini doğruladıktan sonra kullanıcıya hak vermeye devam edebilir ve kullanıcıyı bilgilendirebilir. Hak vermeden önce uygulamanızın satın alma durumunun PURCHASED olduğunu kontrol ettiğini doğrulayın. Satın alma işlemi BEKLEMEDE durumundaysa uygulamanız, hak verilmeden önce kullanıcının satın alma işlemini tamamlamak için yapması gereken işlemler olduğunu bildirmelidir. Yalnızca satın alma işlemi PENDING durumundan SUCCESS durumuna geçtiğinde hak verin. Ek bilgilere Bekleyen işlemleri ele alma başlıklı makaleden ulaşabilirsiniz.

Kullanıcı tanımlayıcılarını ekleme bölümünde açıklandığı gibi, satın alma işlemine kullanıcı tanımlayıcıları eklediyseniz bunları alabilir ve sisteminizdeki doğru kullanıcıya atamak için kullanabilirsiniz. Bu teknik, uygulamanızın bir satın alma işleminin hangi kullanıcıya ait olduğuyla ilgili bağlamı kaybettiği durumlarda satın alma işlemlerini uzlaştırmak için yararlıdır. Uygulamanızın dışında yapılan satın alma işlemlerinde bu tanımlayıcıların ayarlanmayacağını unutmayın. Bu durumda, uygulamanız oturum açmış kullanıcıya hak verebilir veya kullanıcıdan tercih ettiği hesabı seçmesini isteyebilir.

Ön siparişlerde, yayınlanma saatine ulaşılmadan önce satın alma işlemi BEKLEMEDE durumundadır. Ön sipariş satın alma işlemi yayınlanma tarihinde tamamlanır ve ek işlem yapılmasına gerek kalmadan durum SATIN ALINDI olarak değişir.

Kullanıcıyı bilgilendirme

Kullanıcıya yetki verdikten sonra uygulamanız, başarılı satın alma işlemini onaylayan bir bildirim göstermelidir. Bildirim sayesinde kullanıcı, satın alma işleminin başarıyla tamamlanıp tamamlanmadığı konusunda karışıklık yaşamaz. Bu durum, kullanıcının uygulamanızı kullanmayı bırakmasına, kullanıcı desteğiyle iletişime geçmesine veya sosyal medyada bu konuda şikayette bulunmasına neden olabilir. Uygulamanızın, uygulama yaşam döngünüzün herhangi bir anında satın alma güncellemelerini algılayabileceğini unutmayın. Örneğin, bir ebeveyn başka bir cihazda bekleyen bir satın alma işlemini onayladığında uygulamanız, kullanıcıyı uygun bir zamanda bilgilendirmek için bildirim göndermeyi geciktirmek isteyebilir. Gecikmenin uygun olacağı bazı örnekler:

  • Oyunun aksiyon bölümünde veya ara sahnelerde mesaj göstermek kullanıcının dikkatini dağıtabilir. Bu durumda, işlem bölümü bittikten sonra kullanıcıyı bilgilendirmeniz gerekir.
  • Oyunun ilk eğitici ve kullanıcı kurulumu bölümlerinde. Örneğin, bir kullanıcı uygulamanızı yüklemeden önce uygulamanızın dışında bir satın alma işlemi yapmış olabilir. Yeni kullanıcıları, oyunu açtıktan hemen sonra veya ilk kullanıcı kurulumu sırasında ödül hakkında bilgilendirmenizi öneririz. Uygulamanız, kullanıcının hak kazanmadan önce hesap oluşturmasını veya giriş yapmasını gerektiriyorsa kullanıcınıza satın alma işlemini talep etmek için hangi adımları tamamlaması gerektiğini bildirmeniz önerilir. Uygulamanız satın alma işlemini işlemediyse satın alma işlemlerinin 3 gün sonra geri ödenmesi nedeniyle bu durum çok önemlidir.

Google Play, kullanıcıyı satın alma işlemi hakkında bilgilendirirken aşağıdaki mekanizmaları kullanmanızı önerir:

  • Uygulama içi iletişim kutusu gösterin.
  • Mesajı uygulama içi mesaj kutusuna teslim edin ve uygulama içi mesaj kutusunda yeni bir mesaj olduğunu net bir şekilde belirtin.
  • İşletim sistemi bildirim mesajı kullanın.

Bildirim, kullanıcıyı aldığı avantaj hakkında bilgilendirmelidir. Örneğin, "100 altın para satın aldınız!". Ayrıca, satın alma işlemi Play Pass gibi bir programın avantajı sayesinde yapıldıysa uygulamanız bunu kullanıcıya bildirir. Örneğin, "Öğeler alındı! Play Pass ile 100 mücevher kazandınız. Devam et."i tıklayın. Her program, kullanıcılara avantajları bildirmek için gösterilmesi önerilen metinle ilgili yönergeler içerebilir.

Satın alma işleminin tamamlandığını Google'a bildirin.

Uygulamanız, kullanıcıya yetki verdikten ve başarılı işlem hakkında bildirim gönderdikten sonra satın alma işleminin başarıyla işlendiğini Google'a bildirmelidir. Bu işlem, satın alma işlemini onaylayarak yapılır ve satın alma işleminin otomatik olarak geri ödenmemesi ve hakların iptal edilmemesi için üç gün içinde tamamlanmalıdır. Farklı satın alma türlerini onaylama süreci aşağıdaki bölümlerde açıklanmaktadır.

Sarf malzemesi ürünleri

Tüketilebilir ürünler için uygulamanızın güvenli bir arka ucu varsa satın alma işlemlerini güvenilir bir şekilde tüketmek üzere Purchases.products:consume kullanmanızı öneririz. Purchases.products:get çağrısının sonucundan consumptionState işaretini kontrol ederek satın alma işleminin daha önce kullanılmadığından emin olun. Uygulamanız yalnızca istemci tarafında çalışıyor ve arka ucu yoksa Google Play Faturalandırma Kitaplığı'ndaki consumeAsync() öğesini kullanın. Her iki yöntem de onay şartını karşılar ve uygulamanızın kullanıcıya hak verdiğini gösterir. Bu yöntemler, uygulamanızın giriş satın alma jetonuna karşılık gelen tek seferlik ürünü yeniden satın alınabilir hale getirmesini de sağlar. consumeAsync() ile ConsumeResponseListener arayüzünü uygulayan bir nesne de iletmeniz gerekir. Bu nesne, tüketim işleminin sonucunu işler. İşlem tamamlandığında Google Play Faturalandırma Kitaplığı'nın çağırdığı onConsumeResponse() yöntemini geçersiz kılabilirsiniz.

Aşağıdaki örnekte, ilişkili satın alma jetonu kullanılarak Google Play Faturalandırma Kitaplığı ile bir ürünün nasıl tüketileceği gösterilmektedir:

Kotlin

    val consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build()
    val consumeResult = withContext(Dispatchers.IO) {
        client.consumePurchase(consumeParams)
    }

Java

    ConsumeParams consumeParams =
            ConsumeParams.newBuilder()
                .setPurchaseToken(purchase.getPurchaseToken())
                .build();

    ConsumeResponseListener listener = new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Handle the success of the consume operation.
            }
        }
    };

    billingClient.consumeAsync(consumeParams, listener);

Tüketilebilir olmayan ürünler

Uygulamanızın güvenli bir arka ucu varsa tüketilmeyen satın alma işlemlerini onaylamak için satın alma işlemlerini güvenilir bir şekilde onaylamak üzere Purchases.products:acknowledge kullanmanızı öneririz. Purchases.products:get çağrısının sonucundan acknowledgementState değerini kontrol ederek satın alma işleminin daha önce kabul edilmediğinden emin olun.

Uygulamanız yalnızca istemci tarafında çalışıyorsa uygulamanızda Google Play Faturalandırma Kitaplığı'ndaki BillingClient.acknowledgePurchase() öğesini kullanın. Uygulamanız, satın alma işlemini onaylamadan önce Google Play Faturalandırma Kitaplığı'ndaki isAcknowledged() yöntemini kullanarak işlemin daha önce onaylanıp onaylanmadığını kontrol etmelidir.

Aşağıdaki örnekte, Google Play Faturalandırma Kitaplığı'nı kullanarak satın alma işleminin nasıl onaylanacağı gösterilmektedir:

Kotlin

val client: BillingClient = ...
val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ...

val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
    .setPurchaseToken(purchase.purchaseToken)
val ackPurchaseResult = withContext(Dispatchers.IO) {
     client.acknowledgePurchase(acknowledgePurchaseParams.build())
}

Java

BillingClient client = ...
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...

AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
 client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);

Abonelikler

Abonelikler, tüketilmeyen ürünlere benzer şekilde işlenir. Mümkünse güvenli arka uçtan satın alma işlemini güvenilir bir şekilde onaylamak için Google Play Developer API'den Purchases.subscriptions.acknowledge kullanın. Purchases.subscriptions:get kaynağından satın alma kaynağındaki acknowledgementState değerini kontrol ederek satın alma işleminin daha önce kabul edilmediğini doğrulayın. Aksi takdirde, isAcknowledged() kontrol edildikten sonra Google Play Faturalandırma Kitaplığı'ndan BillingClient.acknowledgePurchase() kullanarak aboneliği onaylayabilirsiniz. Tüm ilk abonelik satın alma işlemlerinin kabul edilmesi gerekir. Abonelik yenilemelerinin onaylanması gerekmez. Aboneliklerin ne zaman onaylanması gerektiği hakkında daha fazla bilgi edinmek için Abonelik satma konusuna bakın.

Özet

Aşağıdaki kod snippet'inde bu adımların özeti gösterilmektedir.

Kotlin

fun handlePurchase(Purchase purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your
    // onPurchasesUpdated.
    Purchase purchase = ...;

    // Step 1: Send the purchase to your secure backend to verify the purchase
    // following
    // https://developer.android.com/google/play/billing/security#verify
.
    // Step 2: Update your entitlement storage with the purchase. If purchase is
    // in PENDING state then ensure the entitlement is marked as pending and the
    // user does not receive benefits yet. It is recommended that this step is
    // done on your secure backend and can combine in the API call to your
    // backend in step 1.

    // Step 3: Notify the user using appropriate messaging (delaying
    // notification if needed as discussed above).

    // Step 4: Notify Google the purchase was processed using the steps
    // discussed in the processing purchases section.
}

Java

void handlePurchase(Purchase purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your
    // onPurchasesUpdated.
    Purchase purchase = ...;

    // Step 1: Send the purchase to your secure backend to verify the purchase
    // following
    // https://developer.android.com/google/play/billing/security#verify

    // Step 2: Update your entitlement storage with the purchase. If purchase is
    // in PENDING state then ensure the entitlement is marked as pending and the
    // user does not receive benefits yet. It is recommended that this step is
    // done on your secure backend and can combine in the API call to your
    // backend in step 1.

    // Step 3: Notify the user using appropriate messaging (delaying
    // notification if needed as discussed above).

    // Step 4: Notify Google the purchase was processed using the steps
    // discussed in the processing purchases section.
}

Uygulamanızın bu adımları doğru şekilde uyguladığını doğrulamak için test kılavuzunu inceleyebilirsiniz.

Beklemedeki işlemleri yönetme

Google Play, beklemede olan işlemleri (kullanıcının satın alma işlemini başlattığı an ile satın alma işleminin ödeme yönteminin işlendiği an arasında bir veya daha fazla ek adım gerektiren işlemler) destekler. Google, kullanıcının ödeme yönteminden başarılı bir şekilde ödeme alındığını size bildirene kadar uygulamanız bu tür satın alma işlemlerine hak vermemelidir.

Örneğin, kullanıcılar daha sonra nakit ödeme yapacakları fiziksel bir mağazayı seçerek işlem başlatabilir. Kullanıcı hem bildirim hem de e-posta yoluyla bir kod alır. Kullanıcı fiziksel mağazaya geldiğinde kodu kasiyere göstererek kullanabilir ve nakit ödeme yapabilir. Google, ödemenin alındığını hem size hem de kullanıcıya bildirir. Uygulamanız daha sonra kullanıcıya hak verebilir.

Uygulamanızda bekleyen işlemleri etkinleştirmek için enablePendingPurchases() işlevini BillingClient başlatma işleminin bir parçası olarak çağırın. Uygulamanız, tek seferlik ürünler için bekleyen işlemleri etkinleştirmeli ve desteklemelidir. Destek eklemeden önce, bekleyen işlemler için satın alma yaşam döngüsünü anladığınızdan emin olun.

Uygulamanız PurchasesUpdatedListener aracılığıyla veya queryPurchasesAsync çağrısı sonucunda yeni bir satın alma işlemi aldığında, satın alma durumunun PURCHASED veya PENDING olup olmadığını belirlemek için getPurchaseState() yöntemini kullanın. Yararlanma hakkını yalnızca durum PURCHASED olduğunda vermelisiniz.

Uygulamanız çalışıyorsa ve kullanıcı satın alma işlemini tamamladığında etkin bir Play Billing Library bağlantınız varsa PurchasesUpdatedListener tekrar çağrılır ve PurchaseState artık PURCHASED olur. Bu noktada uygulamanız, Satın Alma İşlemlerini Algılama ve İşleme için standart yöntemi kullanarak satın alma işlemini işleyebilir. Uygulamanız çalışmıyorken PURCHASED durumuna geçen satın alma işlemlerini işlemek için uygulamanızın queryPurchasesAsync() yönteminde onResume() yöntemini de çağırması gerekir.

Satın alma işlemi PENDING durumundan PURCHASED durumuna geçtiğinde real_time_developer_notifications istemciniz ONE_TIME_PRODUCT_PURCHASED veya SUBSCRIPTION_PURCHASED bildirimi alır. Satın alma işlemi iptal edilirse ONE_TIME_PRODUCT_CANCELED veya SUBSCRIPTION_PENDING_PURCHASE_CANCELED bildirimi alırsınız. Bu durum, müşteriniz ödemeyi gerekli süre içinde tamamlamadığında ortaya çıkabilir. Satın alma işleminin mevcut durumunu kontrol etmek için her zaman Google Play Geliştirici API'sini kullanabileceğinizi unutmayın.

Çoklu satın alma işlemlerini işleme

Google Play Faturalandırma Kitaplığı'nın 4.0 ve sonraki sürümlerinde desteklenen Google Play, müşterilerin satın alma sepetinden bir miktar belirterek tek bir işlemde aynı tek seferlik üründen birden fazla satın almasına olanak tanır. Uygulamanızın, çoklu satın alma işlemlerini yönetmesi ve belirtilen satın alma miktarına göre hak vermesi beklenir.

Birden fazla ürün satın alma işlemlerini desteklemek için uygulamanızın sağlama mantığının öğe miktarını kontrol etmesi gerekir. Aşağıdaki API'lerden birini kullanarak quantity alanına erişebilirsiniz:

Çoklu satın alma işlemlerini işleyecek mantığı ekledikten sonra, Google Play Console'daki tek seferlik ürün yönetimi sayfasında ilgili ürün için çoklu satın alma özelliğini etkinleştirmeniz gerekir.

Kullanıcının faturalandırma yapılandırmasını sorgulama

getBillingConfigAsync(), kullanıcının Google Play için kullandığı ülkeyi sağlar.

BillingClient oluşturduktan sonra kullanıcının faturalandırma yapılandırmasını sorgulayabilirsiniz. Aşağıdaki kod snippet'inde getBillingConfigAsync()'ya nasıl çağrı yapılacağı açıklanmaktadır. BillingConfigResponseListener uygulayarak yanıtı ele alın. Bu dinleyici, uygulamanızdan başlatılan tüm faturalandırma yapılandırması sorgularıyla ilgili güncellemeleri alır.

Döndürülen BillingResult hata içermiyorsa kullanıcının Play ülkesini almak için BillingConfig nesnesindeki countryCode alanını kontrol edebilirsiniz.

Kotlin

// Use the default GetBillingConfigParams.
val getBillingConfigParams = GetBillingConfigParams.newBuilder().build()
billingClient.getBillingConfigAsync(getBillingConfigParams,
    object : BillingConfigResponseListener {
        override fun onBillingConfigResponse(
            billingResult: BillingResult,
            billingConfig: BillingConfig?
        ) {
            if (billingResult.responseCode == BillingResponseCode.OK
                && billingConfig != null) {
                val countryCode = billingConfig.countryCode
                ...
            } else {
                // TODO: Handle errors
            }
        }
    })

Java

// Use the default GetBillingConfigParams.
GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(getBillingConfigParams,
    new BillingConfigResponseListener() {
      public void onBillingConfigResponse(
          BillingResult billingResult, BillingConfig billingConfig) {
        if (billingResult.getResponseCode() == BillingResponseCode.OK
            && billingConfig != null) {
            String countryCode = billingConfig.getCountryCode();
            ...
         } else {
            // TODO: Handle errors
        }
      }
    });

Google Play Games ana sayfasında alışveriş sepetini terk etme hatırlatıcıları (varsayılan olarak etkindir)

Tek seferlik ürünlerle para kazanan oyun geliştiriciler için, Google Play Console'da etkin olan stok tutma birimlerinin (SKU'lar) uygulamanızın dışında satılabileceği bir yöntem, kullanıcıları Google Play Store'a göz atarken daha önce tamamlanmamış satın alma işlemlerini tamamlamaya teşvik eden alışveriş sepetini terk etme hatırlatıcısı özelliğidir. Bu satın alma işlemleri, uygulamanızın dışında, Google Play Store'daki Google Play Games ana sayfasından yapılır.

Bu özellik, kullanıcıların kaldıkları yerden devam etmelerine ve geliştiricilerin satışlarını en üst düzeye çıkarmalarına yardımcı olmak için varsayılan olarak etkindir. Ancak Alışveriş sepetini terk etme hatırlatıcısı özelliğini devre dışı bırakma formunu göndererek uygulamanızda bu özelliği devre dışı bırakabilirsiniz. Google Play Console'da SKU'ları yönetmeyle ilgili en iyi uygulamalar için Uygulama içi ürün oluşturma başlıklı makaleyi inceleyin.

Aşağıdaki resimlerde, Google Play Store'da gösterilen alışveriş sepetini terk etme hatırlatıcısı gösterilmektedir:

Google Play Store ekranında, daha önce tamamlanmamış bir satın alma işlemi için satın alma istemi gösteriliyorsa
Şekil 2. Google Play Store ekranında, daha önce tamamlanmamış bir satın alma işlemi için satın alma istemi gösteriliyor.

Google Play Store ekranında, daha önce tamamlanmamış bir satın alma işlemi için satın alma istemi gösteriliyorsa
3.şekil Google Play Store ekranında, daha önce tamamlanmamış bir satın alma işlemi için satın alma istemi gösteriliyor.