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

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

Bir satın alma süreci

Tek seferlik satın alma işlemi veya abonelik için tipik bir satın alma akışı aşağıda verilmiştir.

  1. Kullanıcıya neler satın alabileceklerini 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 sunun.
  5. İçeriğin teslim edildiğini onaylama. Tüketilebilir ürünlerde, kullanıcının ürünü tekrar satın alabilmesi için satın alma işlemini tüketin.

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

  • Etkin: Kullanıcının durumu iyidir ve aboneliğe erişimi vardır.
  • İptal edildi: Kullanıcı aboneliğini iptal etmiş ancak geçerlilik süresi sona erene kadar erişmeye devam edebilir.
  • Ek süre içinde: Kullanıcı ödeme sorunuyla karşılaşmış ancak Google ödeme yöntemini tekrar denemeye devam ederken erişime devam etmektedir.
  • Askıya alındı: Kullanıcı ödeme sorunuyla karşılaştı ve Google ödeme yöntemini tekrar dener. Bu sırada kullanıcının erişimi kaldırılır.
  • Duraklatıldı: Kullanıcı erişimini duraklatmıştır ve erişimi, duraklatma işlemini geri alana kadar devam etmez.
  • Süresi doldu: Kullanıcı, aboneliği iptal etti ve aboneliğe erişimi kaybetti. Kullanıcı, süre sona erdiğinde kullanımdan kaldırılmış olarak kabul edilir.

Google Play bağlantısını ilk kullanıma hazırlayın

Google Play'in faturalandırma sistemiyle entegrasyona ilk adım olarak Google Play Faturalandırma Kitaplığı'nı uygulamanıza eklemeniz ve bir bağlantı başlatmanız gerekir.

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 gösterildiği gibi ekleyin:

Eski

dependencies {
    def billing_version = "7.0.0"

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

Kotlin

dependencies {
    val billing_version = "7.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ıza olanak tanıyan 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ığı ekleyin:

Eski

dependencies {
    def billing_version = "7.0.0"

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

Kotlin

dependencies {
    val billing_version = "7.0.0"

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

BillingClient'ı başlatma

Google Play Faturalandırma Kitaplığı'na bir bağımlılık ekledikten sonra bir BillingClient örneğini başlatmanız gerekir. BillingClient, Google Play Faturalandırma Kitaplığı ile uygulamanızın geri kalanı arasındaki iletişimin ana arayüzüdür. BillingClient, birçok yaygın faturalandırma işlemi için hem senkronize hem de eşzamansız kolaylık yöntemleri sağlar. Tek bir etkinlik için birden fazla PurchasesUpdatedListener geri çağırma işlemini önlemek amacıyla aynı anda bir etkin BillingClient bağlantınızın açık olması önemle tavsiye edilir.

BillingClient oluşturmak için newBuilder() simgesini kullanın. newBuilder()'e herhangi bir bağlam iletebilirsiniz. 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() numaralı telefonu arayıp bir PurchasesUpdatedListener öğesine referans vermeniz 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. İstemci kurulumu tamamlandıktan sonra ve istemci başka istekler yapmaya hazır olduğunda geri çağırma almak için bir BillingClientStateListener uygulamanız gerekir.

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

Aşağıdaki örnekte, bir bağlantının nasıl başlatılacağı ve kullanıma hazır olup olmadığı 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.
    }
});

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

Google Play ile bağlantı kurduktan sonra, mevcut ürünlerinizi sorgulamaya ve kullanıcılarınıza göstermeye hazırsınız demektir.

Ürün ayrıntılarını sorgulamak, yerelleştirilmiş ürün bilgileri döndürdüğü için ürünlerinizi kullanıcılarınıza göstermeden önce atmanız gereken önemli bir adımdır. Aboneliklerde, ürün ekranınızın tüm Play politikalarına uyduğundan emin olun.

Uygulama içi ürün ayrıntılarını sorgulamak için queryProductDetailsAsync() numaralı telefonu arayın.

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,
    productDetailsList ->
      // check billingResult
      // process returned productDetailsList
}

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,
                List<ProductDetails> productDetailsList) {
            // check billingResult
            // process returned productDetailsList
        }
    }
)

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

Kotlin uzantılarıyla sorgu oluşturma

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

queryProductDetails(), ayrı bir dinleyici tanımlamanıza gerek kalmaması için Kotlin coroutine'lerinden yararlanır. Bunun yerine işlev, sorgulama tamamlanıncaya kadar 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.
}

Bazı cihazlar, genellikle Google Play Hizmetleri'nin eski sürümleri nedeniyle nadiren ProductDetails ve queryProductDetailsAsync()'ü destekleyemez. Bu senaryoda uygun destek alabilmeniz için Play Faturalandırma Kitaplığı 5'e 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ı ProductDetails nesnelerinden oluşan bir List içinde saklar. Ardından, uygulama içi bir ürünle ilgili alakalı bilgileri (ör. fiyat veya açıklama) görüntülemek için listedeki her ProductDetails nesnesi üzerinde çeşitli yöntemler çağırabilirsiniz. Mevcut ürün ayrıntısı bilgilerini görüntülemek için ProductDetails sınıfındaki yöntemlerin listesine bakın.

Bir öğeyi satışa sunmadan önce, kullanıcının söz konusu öğeye sahip olup olmadığını kontrol edin. Kullanıcının öğe kitaplığında hâlâ bir tüketim öğesi varsa yeniden satın almadan önce öğeyi tüketmesi gerekir.

Abonelik sunmadan önce kullanıcının abone olmadığından emin olun. Ayrıca aşağıdakileri de unutmayın:

  • queryProductDetailsAsync(), abonelik ürün ayrıntılarını ve abonelik başına en fazla 50 teklif döndürür.
  • queryProductDetailsAsync() yalnızca kullanıcının uygun olduğu teklifleri döndürür. Kullanıcı, uygun olmadığı bir teklifi satın almaya çalışırsa (ör. uygulama, uygun tekliflerin güncel olmayan bir listesini gösteriyorsa) Play kullanıcıyı uygun olmadığını bilgilendirir ve kullanıcı bunun yerine temel planı satın almayı seçebilir.
başlıklı makaleyi inceleyin.

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ığında launchBillingFlow() yöntemini çağırın. Bu yöntem, queryProductDetailsAsync() çağrıldıktan sonra 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)
        // For One-time product, "setOfferToken" method shouldn't be called.
        // For subscriptions, to get an offer token, 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)
            // For one-time products, "setOfferToken" method shouldn't be called.
            // For subscriptions, to get an offer token, 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 içinde listelenen çeşitli yanıt kodlarından birini döndürür. Satın alma akışı başlatılırken hata olmadığından emin olmak için bu sonucu kontrol edin. BillingResponseCode OK, başarılı bir lansmanı gösterir.

launchBillingFlow() çağrısı başarılı olduğunda sistem Google Play satın alma ekranını gösterir. Şekil 1'de bir aboneliğin satın alma ekranı gösterilmektedir:

Google Play satın alma ekranında, satın alınabilecek bir abonelik gösteriliyor
Şekil 1. Google Play satın alma ekranında satın alınabilen bir abonelik gösteriliyor.

Google Play, satın alma işleminin sonucunu PurchasesUpdatedListener arayüzünü uygulayan bir dinleyiciye iletmek için onPurchasesUpdated() 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() 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) {
           handlePurchase(purchase)
       }
   } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
       // Handle an error caused by a user cancelling 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) {
            handlePurchase(purchase);
        }
    } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
        // Handle an error caused by a user cancelling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

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

google play&#39;in satın alma işlemi başarılı ekranı
Şekil 2. Google Play'in satın alma işleminin başarılı olduğu ekranı.

Başarılı satın alma işlemleri, kullanıcıyı ve satın alınan uygulama içi ü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, satın alma işlemini doğrulayıp sahtekarlığa karşı koruma sağlayabileceğiniz güvenli arka uç sunucunuza aktarmanızı öneririz. Bu süreç aşağıdaki bölümde daha ayrıntılı olarak açıklanmıştır.

Kullanıcıya, işlemin sipariş kimliğinin veya benzersiz kimliğinin yer aldığı bir fatura e-postası da gönderilir. Kullanıcılar, her tek seferlik ürün satın alma işleminin yanı sıra 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 kullanıcılara bir öğenin fiyatının otomatik karar verme sistemi kullanılarak kişiselleştirildiğini açıklamak için setIsOfferPersonalized() yöntemini kullanın.

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

Google, DSA Madde 21(2) 2011/83/AB Tüketici Hakları Yönergesi'nin 6. (1) (ea) maddesine bakın.

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

Daha fazla bilgi için Tüketici Yardım Merkezi'ne göz atın.

Satın alma işlemleri

Kullanıcı bir satın alma işlemini tamamladıktan sonra uygulamanızın bu satın alma işlemini işlemesi gerekir. Çoğu durumda, uygulamanız satın alma işlemleriyle ilgili bildirimleri PurchasesUpdatedListener üzerinden alır. Bununla birlikte, Satın alma işlemlerini getirme bölümünde açıklandığı gibi, uygulamanızın BillingClient.queryPurchasesAsync() çağrısı yapılarak satın alma işlemlerinden haberdar edileceği durumlar vardır.

Ayrıca, güvenli arka ucunuzda Gerçek Zamanlı Geliştirici Bildirimleri istemcisi varsa yeni bir satın alma işlemi konusunda sizi uyaran bir subscriptionNotification veya oneTimeProductNotification alarak yeni satın alma işlemleri kaydedebilirsiniz. Bu bildirimleri aldıktan sonra, tam durumu almak ve kendi arka uç durumunuzu güncellemek için Google Play Developer API'yi çağırın.

Uygulamanız, satın alma işlemlerini aşağıdaki şekilde işlemelidir:

  1. Satın alma işlemini doğrulayın.
  2. Kullanıcıya içerik verin ve içeriğin teslim edildiğini onaylayın. İsteğe bağlı olarak, kullanıcının öğeyi tekrar satın alabilmesi için öğeyi kullanılmış olarak işaretleyin.

Bir satın alma işlemini doğrulamak için önce satın alma durumunun PURCHASED olduğunu kontrol edin. Satın alma işlemi PENDING ise satın alma işlemini Bekleyen işlemleri yönetme bölümünde açıklandığı şekilde işlemeniz gerekir. onPurchasesUpdated() veya queryPurchasesAsync()'ten alınan satın alma işlemleri için, uygulamanızın uygunluk izni vermeden önce satın alma işleminin meşru olduğundan emin olmak üzere işlemi daha ayrıntılı bir şekilde doğrulamanız gerekir. Bir satın alma işlemini nasıl doğrulayacağınızı öğrenmek için Haklardan yararlanma hakkı vermeden önce satın alma işlemlerini doğrulama başlıklı makaleyi inceleyin.

Satın alma işlemini doğruladıktan sonra uygulamanız, kullanıcıya erişim izni vermeye hazırdır. Satın alma işlemiyle ilişkili kullanıcı hesabı, sunucu tarafında uygulama içi ürün satın alma işlemleri için Purchases.products:get tarafından döndürülen ProductPurchase.obfuscatedExternalAccountId ve abonelikler için Purchases.subscriptions:get tarafından döndürülen SubscriptionPurchase.obfuscatedExternalAccountId ile veya satın alma işlemi yapılırken setObfuscatedAccountId ile ayarlanmışsa istemci tarafında Purchase.getAccountIdentifiers()'ten gelen obfuscatedAccountId ile tanımlanabilir.

Yetki verdikten sonra uygulamanız satın alma işlemini onaylamalıdır. Bu onay işlemi, satın alma için yetki verdiğinizi Google Play'e bildirir.

Kullanım hakkı verme ve satın alma işlemini onaylama süreci, satın alınan öğenin tüketim amaçlı, tüketim amaçlı olmayan veya abonelik olup olmadığına bağlıdır.

Tüketim Ürünleri

Uygulamanızda güvenli bir arka uç varsa tüketim ürünleri için satın alma işlemlerini güvenilir bir şekilde kullanmak üzere Purchases.products:consume kullanmanızı öneririz. Purchases.products:get çağrısının sonucundaki consumptionState değerini kontrol ederek satın alma işleminin daha önce tüketilmediğinden emin olun. Uygulamanız arka uç olmadan yalnızca istemci ise Google Play Faturalandırma Kitaplığı'ndan consumeAsync() işlevini kullanın. Her iki yöntem de onay şartını karşılar ve uygulamanızın kullanıcıya yararlanma hakkı 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 birlikte ConsumeResponseListener arayüzünü uygulayan bir nesne de göndermeniz gerekir. Bu nesne, tüketim işleminin sonucunu işler. Google Play Faturalandırma Kitaplığı'nın işlem tamamlandığında çağırdığı onConsumeResponse() yöntemini geçersiz kılabilirsiniz.

Aşağıdaki örnekte, ilişkili satın alma jetonunu kullanarak Google Play Faturalandırma Kitaplığı ile bir ürünün nasıl kullanılacağı gösterilmektedir:

Kotlin

suspend fun handlePurchase(purchase: Purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
    val purchase : Purchase = ...;

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

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

Java

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

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

    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);
}

Sarf malzemesi olmayan ürünler

Uygulamanızda güvenli bir arka uç varsa tüketilemeyen satın alma işlemlerini onaylamak için Purchases.products:acknowledge yöntemini kullanarak satın alma işlemlerini güvenilir bir şekilde onaylamanızı öneririz. Purchases.products:get çağrısının sonucundaki acknowledgementState öğesini kontrol ederek satın alma işleminin daha önce onaylanmadığından emin olun.

Uygulamanız yalnızca istemci ise uygulamanızda Google Play Faturalandırma Kitaplığı'ndan BillingClient.acknowledgePurchase() yöntemini kullanın. Uygulamanız, bir 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ığı kullanılarak bir satın alma işleminin nasıl onaylandığı gösterilmektedir:

Kotlin

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

suspend fun handlePurchase() {
    if (purchase.purchaseState === PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged) {
            val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.purchaseToken)
            val ackPurchaseResult = withContext(Dispatchers.IO) {
               client.acknowledgePurchase(acknowledgePurchaseParams.build())
            }
        }
     }
}

Java

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

void handlePurchase(Purchase purchase) {
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged()) {
            AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
            client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
        }
    }
}

Abonelikler

Abonelikler, tüketilmeyen öğelere 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'deki Purchases.subscriptions.acknowledge yöntemini kullanın. Purchases.subscriptions:get kaynağındaki satın alma kaynağında acknowledgementState değerini kontrol ederek satın alma işleminin daha önce kabul edilmediğinden emin olun. Aksi takdirde, isAcknowledged()'i işaretledikten sonra Google Play Faturalandırma Kitaplığı'ndan BillingClient.acknowledgePurchase()'ü kullanarak aboneliği onaylayabilirsiniz. Tüm ilk abonelik satın alma işlemlerinin onaylanması gerekir. Abonelik yenilemelerinin onaylanması gerekmez. Aboneliklerin ne zaman onaylanması gerektiği hakkında daha fazla bilgi için Abonelik satma konusuna bakın.

Satın alma işlemlerini getirme

PurchasesUpdatedListener kullanarak satın alma güncellemelerini dinlemek, uygulamanızın tüm satın alma işlemlerini işlemesini sağlamak için yeterli değildir. Uygulamanız, kullanıcının yaptığı tüm satın alma işlemlerinden haberdar olmayabilir. Uygulamanızın satın alma işlemlerini takip edemeyeceği veya satın alma işlemlerinden haberdar olmayacağı bazı senaryolar aşağıda verilmiştir:

  • Satın alma işlemi sırasında ağ sorunları: Kullanıcı başarılı bir satın alma işlemi gerçekleştirir ve Google'dan onay alır ancak cihazı, PurchasesUpdatedListener üzerinden satın alma işlemiyle ilgili bildirim almadan önce ağ bağlantısını kaybeder.
  • Birden fazla cihaz: Kullanıcı bir cihazda ürün satın alır ve ardından cihaz değiştirdiğinde ürünü görmeyi bekler.
  • Uygulamanız 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.

Bu durumları ele almak için uygulamanızın, tüm satın alma işlemlerinin satın alma işlemlerini işleme bölümünde açıklandığı şekilde başarıyla işlenmesini sağlamak amacıyla onResume() yönteminizde BillingClient.queryPurchasesAsync() çağrısında bulunduğundan emin olun.

Aşağıdaki örnekte, bir kullanıcının abonelik satın alma işlemlerinin nasıl getirileceği gösterilmektedir. queryPurchasesAsync() işlevinin yalnızca etkin abonelikleri ve tüketilmemiş tek seferlik satın alma işlemlerini döndürdüğünü unutmayın.

Kotlin

val params = QueryPurchasesParams.newBuilder()
               .setProductType(ProductType.SUBS)

// uses queryPurchasesAsync Kotlin extension function
val purchasesResult = billingClient.queryPurchasesAsync(params.build())

// check purchasesResult.billingResult
// process returned purchasesResult.purchasesList, e.g. display the plans user owns

Java

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
      .setProductType(ProductType.SUBS)
      .build(),
    new PurchasesResponseListener() {
      public void onQueryPurchasesResponse(BillingResult billingResult, List<Purchase> purchases) {
        // check billingResult
        // process returned purchase list, e.g. display the plans user owns

      }
    }
);

Uygulamanızın dışından yapılan satın alma işlemlerini işleme

Promosyon kullanımları veya Google Play Games uygulama içi satın alma işlemleri (UİSA) için alışveriş sepetini terk etme hatırlatıcıları gibi bazı satın alma işlemleri uygulamanızın dışında gerçekleşebilir. Kullanıcılar uygulamanızın dışında satın alma işlemi yaptığında, uygulamanızın bir uygulama içi mesaj göstermesini veya satın alma işleminin doğru şekilde alındığını ve işlendiğini bildirmek için bir tür bildirim mekanizması kullanmasını bekler. Kabul edilen mekanizmalardan bazıları şunlardır:

  • Uygulama içi pop-up göster.
  • İletiyi bir uygulama içi mesaj kutusuna gönderin ve uygulama içi mesaj kutusunda yeni bir ileti olduğunu açıkça belirtin.
  • OS bildirim mesajı kullanın.

Uygulamanız, satın alma işlemini tanıdığında herhangi bir durumda olabilir. Satın alma işlemi yapıldığında uygulamanızın yüklü olmaması bile mümkündür. Kullanıcılar, uygulamanın durumundan bağımsız olarak uygulamayı devam ettirdiklerinde satın aldıkları ürünü elde etmeyi beklerler.

Uygulamanın satın alma işleminin yapıldığı durumlardan bağımsız olarak satın alma işlemlerini algılamanız gerekir. Ancak, kullanıcıyı ürünün elinize ulaştığı konusunda hemen bilgilendirmemenizin kabul edilebilir olabileceği bazı istisnalar vardır. Örnek:

  • Oyunun işlem bölümünde mesaj göstermek, kullanıcının dikkatini dağıtabilir. Bu durumda, işlem bölümü sona erdikten sonra kullanıcıyı bilgilendirmeniz gerekir.
  • Mesaj göstermenin kullanıcının dikkatini dağıtabileceği ara sahneler sırasında. Bu durumda, ara sahne sona erdikten sonra kullanıcıyı bilgilendirmeniz gerekir.
  • Oyunun ilk eğitim ve kullanıcı kurulumu kısımları sırasında. Yeni kullanıcıları, oyunu açtıktan hemen sonra veya ilk kullanıcı ayarlaması sırasında ödül hakkında bilgilendirmenizi öneririz. Ancak kullanıcıyı bilgilendirmek için ana oyun sekansı hazır olana kadar beklemek kabul edilebilir.

Kullanıcılarınızı uygulamanız dışında yapılan satın alma işlemleri hakkında ne zaman ve nasıl bilgilendireceğinize karar verirken her zaman kullanıcıyı göz önünde bulundurun. Kullanıcılar hemen bildirim almadığında kafaları karışabilir, uygulamanızı kullanmayı bırakabilir, kullanıcı desteğiyle iletişime geçebilir veya sosyal medyada bu konuda şikayette bulunabilir.

Google Play Games ana sayfasında Alışveriş Sepetini Terk Etme Hatırlatıcıları (varsayılan olarak etkindir)

IAP üzerinden para kazanan oyun geliştiricileri, Google Play Console'da etkin olan stok tutma birimlerini (SKU'ları) uygulamalarının dışında satmanın bir yolu olarak alışveriş sepetini terk etme hatırlatıcısı özelliğini kullanabilir. Bu özellik, kullanıcıları Google Play Store'da gezinirken daha önce terk ettikleri satın alma işlemlerini tamamlamaya teşvik eder. Bu satın alma işlemleri, uygulamanızın dışında, Google Play Store'daki Google Play Games ana sayfasından gerçekleşir.

Kullanıcıların kalkıştıkları yerden devam etmelerine ve geliştiricilerin satışları en üst düzeye çıkarmalarına yardımcı olmak için bu özellik varsayılan olarak etkindir. Ancak Alışveriş sepetini terk etme hatırlatıcısı özelliğini devre dışı bırakma formunu göndererek uygulamanızı bu özelliğin kapsamı dışında tutabilirsiniz. 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örünen Alışveriş Sepetini Terk Etme Hatırlatıcısı gösterilmektedir:

Google Play Store ekranında daha önce vazgeçilen bir satın alma işlemiyle ilgili satın alma istemi gösteriliyor
Şekil 2. Google Play Store ekranında, daha önce bırakılan bir satın alma işlemi için satın alma istemi gösteriliyor.

Google Play Store ekranında, daha önce bırakılan bir satın alma işlemi için satın alma istemi gösteriliyor
Şekil 3. Google Play Store ekranında daha önce vazgeçilen bir satın alma işlemi için bir satın alma istemi gösteriliyor.

Beklemedeki işlemleri işleme

Google Play, beklemedeki işlemleri veya kullanıcının satın alma işlemini başlattığı ile satın alma işleminin ödeme yönteminin işlendiği arasında bir veya daha fazla ek adım gerektiren işlemleri destekler. Google, kullanıcının ödeme yönteminden başarıyla ödeme alındığını bildirene kadar uygulamanız bu tür satın alma işlemleri için yararlanma hakkı vermemelidir.

Örneğin, bir kullanıcı daha sonra nakit ödeme yapacağı fiziksel bir mağaza seçerek işlem başlatabilir. Kullanıcıya hem bildirim hem de e-posta yoluyla bir kod gönderilir. Kullanıcı fiziksel mağazaya geldiğinde kodu kasiyerle değiştirip nakit ödeme yapabilir. Daha sonra Google, ödemenin alındığını hem size hem de kullanıcıya bildirir. Ardından uygulamanız kullanıcıya hak verebilir.

Uygulamanız için bekleyen işlemleri etkinleştirmek üzere BillingClient'ı başlatmanın bir parçası olarak enablePendingPurchases()'i ç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ılması sonucunda yeni bir satın alma işlemi aldığında, satın alma durumunun PURCHASED mı yoksa PENDING mi olduğunu belirlemek için getPurchaseState() yöntemini kullanın. Yararlanma hakkını yalnızca durum PURCHASED olduğunda vermeniz gerekir.

Kullanıcı satın alma işlemini tamamladığında uygulamanız çalışıyorsa PurchasesUpdatedListener işlevi tekrar çağrılır ve PurchaseState, PURCHASED olur. Uygulamanız bu noktada satın alma işlemlerini işlemek için standart yöntemi kullanarak satın alma işlemini gerçekleştirebilir. Uygulamanız, uygulamanız çalışırken PURCHASED durumuna geçen satın alma işlemlerini işlemek için uygulamanızın onResume() yönteminde queryPurchasesAsync() işlevini de çağırmalıdır.

Satın alma işlemi PENDING ürününden PURCHASED sürümüne geçtiğinde, Gerçek zamanlı geliştirici bildirimleri müşterinize ONE_TIME_PRODUCT_PURCHASED veya SUBSCRIPTION_PURCHASED bildirimi gönderilir. 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 zaman aralığında tamamlamazsa ortaya çıkabilir. Bir satın alma işleminin mevcut durumunu kontrol etmek için dilediğiniz zaman Google Play Developer API'yi kullanabileceğinizi unutmayın.

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

Google Play, Google Play Faturalandırma Kitaplığı'nın 4.0 ve sonraki sürümlerinde desteklenen bir özellik olarak müşterilerin, alışveriş sepetinden bir miktar belirterek tek bir işlemde aynı uygulama içi üründen birden fazla satın almasına olanak tanır. Uygulamanızın çoklu miktar satın alma işlemlerini gerçekleştirmesi ve belirtilen satın alma miktarına göre yararlanma hakkı vermesi beklenir.

Çok miktarda satın alma işlemlerini kabul etmek için uygulamanızın temel hazırlama mantığının öğe miktarını kontrol etmesi gerekir. quantity alanına aşağıdaki API'lerden birinden erişebilirsiniz:

Birden fazla miktarda satın alma işlemlerini işlemek için mantık ekledikten sonra, Google Play Developer Console'daki uygulama içi ürün yönetimi sayfasında ilgili ürün için çoklu miktar özelliğini etkinleştirmeniz gerekir.

Kullanıcının Faturalandırma Yapılandırmasını Sorgulama

getBillingConfigAsync(), kullanıcının Google Play'i kullandığı ülkeyi belirtir.

BillingClient oluşturduktan sonra kullanıcının faturalandırma yapılandırmasını sorgulayabilirsiniz. Aşağıdaki kod snippet'inde, getBillingConfigAsync() adresine nasıl çağrı yapılacağı açıklanmaktadır. BillingConfigResponseListener özelliğini uygulayarak yanıtı yönetin. Bu dinleyici, uygulamanızdan başlatılan tüm faturalandırma yapılandırması sorguları için güncelleme alır.

Döndürülen BillingResult hatası içermiyorsa kullanıcının Play Ülkesi bilgisini 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
        }
      }
    });