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

Bu konuda, ü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 sürecinin

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

  1. Kullanıcıya neler satın alabileceğini 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 verin.
  5. İçeriğin yayınlanmasını kabul edin. Tüketilebilir ürünler söz konusu olduğunda, kullanıcının öğeyi tekrar satın alabilmesi için satın alma işlemini gerçekleştirin.

Abonelikler, iptal edilene kadar otomatik olarak yenilenir. Aboneliklerin aşamalarında şunlar bulunabilir:

  • Etkin: Kullanıcı iyi durumda ve aboneliğe erişimi var.
  • İptal edildi: Kullanıcı, üyeliğini iptal etmiştir, ancak son kullanma tarihine kadar erişimi devam etmektedir.
  • Ek süre verildi: Kullanıcı bir ödeme sorunuyla karşılaşmıştır ancak Google, ödeme yöntemini yeniden denerken kullanıcı erişimi sürdürmektedir.
  • Beklemede: Kullanıcı bir ödeme sorunuyla karşılaşmıştır ve Google, ödeme yöntemini yeniden denerken artık erişimi yoktur.
  • Duraklatıldı: Kullanıcı, erişimini duraklatmıştır ve devam edene kadar erişemez.
  • Süresi doldu: Kullanıcı, aboneliğini iptal etmiştir ve aboneliğe erişimini kaybetti. Kullanıcı, geçerlilik süresi sona erdiğinde uygulamayı kullanmayı bırakmış olarak kabul edilir.

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

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

Modern

dependencies {
    def billing_version = "6.1.0"

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

Kotlin

dependencies {
    val billing_version = "6.1.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ş yordamlar 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:

Modern

dependencies {
    def billing_version = "6.1.0"

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

Kotlin

dependencies {
    val billing_version = "6.1.0"

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

Faturalandırma İstemcisini 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şim için ana arayüzdür. BillingClient, yaygın faturalandırma işlemlerinin çoğu için eşzamanlı ve eşzamansız yöntem sunar. Tek bir etkinlik için birden fazla PurchasesUpdatedListener geri çağırmasını önlemek amacıyla aynı anda bir etkin BillingClient bağlantınızın olması önemle tavsiye edilir.

BillingClient oluşturmak için newBuilder() kullanın. newBuilder() işlevine herhangi bir bağlamı iletebilirsiniz. BillingClient, bunu uygulama bağlamı almak için kullanır. Bu sayede bellek sızıntıları konusunda endişelenmenize gerek kalmaz. Satın alma işlemleriyle ilgili güncellemeleri almak için setListener() yöntemini çağırarak PurchasesUpdatedListener referansını iletmeniz gerekir. Bu işleyici, uygulamanızdaki tüm satın alma işlemleri için güncelleme alır.

Kotlin

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

private var billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   .enablePendingPurchases()
   .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)
    .enablePendingPurchases()
    .build();

Google Play'e bağlan

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ı işlemi eşzamansızdır ve istemci kurulumu tamamlandığında ve istemci başka isteklerde bulunmaya hazır olduğunda geri çağırma almak için bir BillingClientStateListener uygulamanız gerekir.

Kayıp Google Play bağlantılarını ele almak için yeniden deneme mantığını da uygulamanız gerekir. Yeniden deneme mantığını uygulamak için onBillingServiceDisconnected() geri çağırma yöntemini geçersiz kılın ve BillingClient uygulamasının başka isteklerde bulunmadan ö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ığı 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österin

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

Ürün ayrıntılarını sorgulamak, yerelleştirilmiş ürün bilgilerini döndürdüğünden ürünlerinizi kullanıcılarınıza göstermeden önce ö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.

Eşzamansız işlemin sonucunu işlemek için ProductDetailsResponseListener arayüzünü uygulayan bir işleyici de belirtmeniz gerekir. Ardından, aşağıdaki örnekte gösterildiği gibi sorgu bittiğinde işleyiciye bildirimde bulunan onProductDetailsResponse() özelliğini 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 ProductType ile birlikte oluşturulan ürün kimliği dizelerinin listesini belirten bir QueryProductDetailsParams örneği iletin. ProductType, tek seferlik ürünler için ProductType.INAPP veya abonelikler için ProductType.SUBS olabilir.

Kotlin uzantılarıyla sorgulama

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

queryProductDetails(), Kotlin eş yordamlarından yararlanır. Böylece ayrı bir işleyici tanımlamanıza gerek kalmaz. Bunun yerine, sorgu tamamlanana kadar işlev askıya alınır. Bunun ardından, sonucu işleyebilirsiniz:

suspend fun processPurchases() {
    val productList = ArrayList<String>()
    productList.add(
              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 ProductDetails ve queryProductDetailsAsync() uygulamalarını destekleyemez. Bu durum genellikle Google Play Hizmetleri'nin eski sürümlerinden kaynaklanır. Bu senaryonun doğru şekilde desteklenebilmesi için geriye dönük uyumluluk özelliklerinin nasıl kullanılacağını Play Faturalandırma Kitaplığı 5 geçiş kılavuzundan öğrenebilirsiniz.

Sonucu işle

Google Play Faturalandırma Kitaplığı, sorgu sonuçlarını List ProductDetails nesnede depolar. Daha sonra, bir uygulama içi ürünle ilgili fiyatı veya açıklaması gibi alakalı bilgileri 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.

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

Abonelik sunmadan önce kullanıcının abone olmadığını doğrulayın. 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 fırsatı satın almaya çalışırsa (örneğin, uygulamada uygun tekliflerin eski bir listesini gösteriyorsa) Play, kullanıcıya uygun olmadığını bildirir ve kullanıcı bunun yerine temel planı satın almayı seçebilir.

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)
        // 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ışını başlatırken herhangi bir hata olmadığından emin olmak için bu sonucu kontrol edin. OK BillingResponseCode değeri, lansmanın başarılı olduğunu gösterir.

launchBillingFlow() numaralı telefona yapılan başarılı bir aramada sistem Google Play satın alma ekranını görüntüler. Şekil 1'de bir abonelik için satın alma ekranı gösterilmektedir:

google play satın alma ekranında, satın alınabilen
            bir abonelik gösterilir.
Şekil 1. Google Play satın alma ekranında, satın alınabilen bir abonelik gösterilir.

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

Olası yanıt kodlarını işlemek için onPurchasesUpdated() öğesini uygulamanız gerekir. Aşağıdaki örnek, onPurchasesUpdated() öğesinin nasıl geçersiz kılınacağını gösterir:

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 başarısı ekranı oluşturur.

google play&#39;de satın alma başarılı ekranı
Şekil 2. Google Play'in satın alma başarısı ekranı.

Başarılı bir satın alma işlemi aynı zamanda kullanıcıyı temsil eden benzersiz bir tanımlayıcı ve satın alınan uygulama içi ürünün ürün kimliği olan bir satın alma jetonu da oluşturur. Uygulamalarınız satın alma jetonunu yerel olarak depolayabilir ancak jetonu güvenli arka uç sunucunuza iletmenizi öneririz. Burada satın alma işlemini doğrulayabilir ve sahtekarlığa karşı koruma sağlayabilirsiniz. Bu süreç aşağıdaki bölümde daha ayrıntılı olarak açıklanmaktadır.

Kullanıcıya, bir Sipariş Kimliği veya işlemin benzersiz bir kimliğini içeren işlem makbuzu da e-postayla gönderilir. Kullanıcılar, her bir tek seferlik ürün satın alma işlemi ve ayrıca ilk abonelik satın alma işlemleri 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ği'ni kullanabilirsiniz.

Kişiselleştirilmiş bir fiyat belirtin

Uygulamanız Avrupa Birliği'ndeki kullanıcılara dağıtılabiliyorsa bir öğenin fiyatının otomatik karar verme yöntemiyle kişiselleştirildiğini kullanıcılara 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ı.

Bu Ek Sözleşme'nin Kullanıcılara sunduğunuz fiyatın kişiselleştirilmiş olup olmadığını belirlemek için Tüketici Hakları Yönergesi'nin (2011/83/EU) 6 (1) (ea) CRD'si.

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

Daha fazla bilgi için Tüketici Yardım Merkezi'ne bakın.

Satın alma işlemleri işleniyor

Kullanıcı bir satın alma işlemini tamamladığında, uygulamanızın bu satın alma işlemini işlemesi gerekir. Çoğu durumda, uygulamanıza PurchasesUpdatedListener aracılığıyla yapılan satın alma işlemleri bildirilir. Bununla birlikte, Satın alma işlemlerini getirme bölümünde açıklandığı gibi uygulamanızda BillingClient.queryPurchasesAsync() çağrısı yapılarak satın alma işlemlerinin gerçekleştirildiği bazı durumlar söz konusudur.

Ayrıca, güvenli arka ucunuzda Gerçek Zamanlı Geliştirici Bildirimleri istemciniz varsa yeni bir satın alma işlemi hakkında sizi uyaran bir subscriptionNotification veya oneTimeProductNotification (yalnızca bekleyen satın alma işlemleri için) 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 bir satın alma işlemini 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 edilmesini onaylayın. İsteğe bağlı olarak, kullanıcının yeniden satın alabilmesi için öğeyi tüketildi olarak işaretleyin.

Bir satın alma işlemini doğrulamak için önce satın alma durumunun PURCHASED olduğundan emin olun. Satın alma işlemi PENDING ise satın alma işlemini Bekleyen işlemleri işleme bölümünde açıklandığı gibi işlemeniz gerekir. onPurchasesUpdated() veya queryPurchasesAsync() üzerinden alınan satın alma işlemlerinde, uygulamanız yararlanma hakkı vermeden önce meşruluğundan emin olmak için satın alma işlemini daha ayrıntılı doğrulamanız gerekir. Bir satın alma işlemini doğru şekilde nasıl doğrulayacağınızı öğrenmek için Yararlanma hakkı vermeden önce satın alma işlemlerini doğrulama bölümüne bakın.

Satın alma işlemini doğrulamanızın ardından uygulamanız kullanıcıya yetki vermeye hazır hale gelir. Satın alma işlemiyle ilişkili kullanıcı hesabı, Purchases.products:get tarafından uygulama içi ürün satın alma işlemleri için iade edilen ProductPurchase.obfuscatedExternalAccountId ve sunucu tarafındaki abonelikler için Purchases.subscriptions:get tarafından iade edilen SubscriptionPurchase.obfuscatedExternalAccountId, obfuscatedAccountId tarafından ise Purchase.getAccountIdentifiers() tarafından Purchase.getAccountIdentifiers() tarafından iade edilen }{/20/} ile tanımlanabilir.setObfuscatedAccountId

Yararlanma hakkı verildikten sonra uygulamanızın satın alma işlemini onaylaması gerekir. Bu onay, satın alma için yetki verdiğinizi Google Play'e bildirir.

Yararlanma hakkı verme ve satın alma işlemini onaylama süreci, satın alma işleminin tüketilebilir mi, tüketilemez mi yoksa abonelik mi olduğuna bağlıdır.

Tüketim Ürünleri

Tüketilebilir ürünler söz konusu olduğunda, uygulamanızın güvenli bir arka ucu varsa satın alma işlemlerini güvenilir bir şekilde tüketmek için Purchases.products:consume kullanmanızı öneririz. Purchases.products:get araması sonucunda bulunan consumptionState değerini kontrol ederek satın alma işleminin daha önce tamamlanmadığından emin olun. Uygulamanız, arka uç olmadan yalnızca istemci kullanıyorsa Google Play Faturalandırma Kitaplığı'ndan consumeAsync() kullanın. Her iki yöntem de onay şartını karşılar ve uygulamanızın kullanıcıya yararlanma hakkı verdiğini belirtir. Bu yöntemler ayrıca uygulamanızın giriş satın alma jetonuna karşılık gelen tek seferlik ürünü yeniden satın alabilmesini sağlar. consumeAsync() ile ConsumeResponseListener arayüzünü uygulayan bir nesneyi 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 kullanılması 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);
}

Tüketilebilir Olmayan Ürünler

Uygulamanızın güvenli bir arka ucu varsa tüketimsiz satın alma işlemlerini onaylamak için Purchases.products:acknowledge kullanarak satın alma işlemlerini güvenilir bir şekilde onaylamanızı öneririz. Purchases.products:get araması sonucunda görülen acknowledgementState değerini kontrol ederek satın alma işleminin daha önce onaylanmadığından emin olun.

Uygulamanız yalnızca istemci sürümüne sahipse uygulamanızdaki Google Play Faturalandırma Kitaplığı'nda bulunan BillingClient.acknowledgePurchase() adresini kullanın. Bir satın alma işlemini onaylamadan önce uygulamanızın halihazırda Google Play Faturalandırma Kitaplığı'ndaki isAcknowledged() yöntemini kullanarak onaylanıp onaylanmadığını kontrol etmesi gerekir.

Aşağıdaki örnekte, bir satın alma işleminin Google Play Faturalandırma Kitaplığı'nı kullanarak nasıl onaylanacağı 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üketilebilir olmayan öğelere benzer şekilde işlenir. Mümkünse satın alma işlemini güvenli arka ucunuzdan güvenilir bir şekilde onaylamak için Google Play Developer API'deki Purchases.subscriptions.acknowledge aracını kullanın. Purchases.subscriptions:get alanındaki satın alma kaynağında acknowledgementState öğesini kontrol ederek satın alma işleminin daha önce onaylanmadığını doğrulayın. Aksi takdirde, isAcknowledged() adresini kontrol ettikten sonra Google Play Faturalandırma Kitaplığı'ndan BillingClient.acknowledgePurchase() adresini kullanarak abonelik 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 alınanlar getiriliyor

Satın alma güncellemelerini PurchasesUpdatedListener kullanarak 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 takibini kaybedebileceği veya satın alma işlemlerinin farkında olmayabileceği bazı senaryolar şunlardır:

  • Satın alma işlemi sırasındaki Ağ Sorunları: Bir kullanıcı başarılı bir satın alma işlemi gerçekleştirir ve Google'dan onay alır, ancak PurchasesUpdatedListener üzerinden satın alma işlemiyle ilgili bildirim almadan önce cihazının ağ bağlantısı kesilir.
  • Birden fazla cihaz: Kullanıcı bir cihazda bir ürün satın alır ve sonra cihaz değiştirdiğinde bu öğeyi görmeyi bekler.
  • Uygulamanızın dışında yapılan satın alma işlemlerini işleme: Promosyon kullanımları gibi bazı satın alma işlemleri, uygulamanızın dışında yapılabilir.

Bu durumların üstesinden gelmek için, uygulamanızın onResume() yönteminizde BillingClient.queryPurchasesAsync() çağrısı yaptığından emin olun. Böylece, tüm satın alma işlemlerinin satın alma işlemlerini işleme bölümünde açıklandığı gibi başarıyla işlendiğinden 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üketilmeyen tek seferlik satın alımlar 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 purchases) {
        // check billingResult
        // process returned purchase list, e.g. display the plans user owns

      }
    }
);

Satın alma geçmişi getiriliyor

queryPurchaseHistoryAsync(), satın alma işleminin süresi dolmuş, iptal edilmiş veya tüketilmiş olsa bile kullanıcının her ürün için yaptığı en son satın alma işlemini döndürür.

Kotlin uzantılarını kullanıyorsanız queryPurchaseHistory() uzantı işlevini kullanabilirsiniz.

Kotlin

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

// uses queryPurchaseHistory Kotlin extension function
val purchaseHistoryResult = billingClient.queryPurchaseHistory(params.build())

// check purchaseHistoryResult.billingResult
// process returned purchaseHistoryResult.purchaseHistoryRecordList, e.g. display purchase

Java

billingClient.queryPurchaseHistoryAsync(
    QueryPurchaseHistoryParams.newBuilder()
        .setProductType(ProductType.SUBS)
        .build(),
    new PurchaseHistoryResponseListener() {
      public void onPurchaseHistoryResponse(
        BillingResult billingResult, List purchasesHistoryList) {
          // check billingResult
          // process returned purchase history list, e.g. display purchase history
        }
    }
);

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

Promosyon kullanımları gibi bazı satın alma işlemleri, uygulamanızın dışında gerçekleşebilir. Bir kullanıcı, uygulamanızın dışında bir satın alma işlemi gerçekleştirdiğinde, uygulamanızın uygulama içi bir mesaj göstermesini bekler veya kullanıcıya uygulamanın satın alma işlemini doğru bir şekilde aldığını ve işlediğini bildirmek için bir tür bildirim mekanizması kullanır. Kabul edilebilir mekanizmalardan bazıları şunlardır:

  • Uygulama içi pop-up göster.
  • Mesajı, uygulama içi mesaj kutusunda yeni bir mesaj olduğunu açıkça belirterek uygulama içi mesaj kutusuna iletin.
  • İşletim sistemi bildirim mesajı kullanılsın.

Satın alma işlemini tanıyan uygulamanız da herhangi bir durumda kalabilir. Hatta uygulamanızın, satın alma işlemi gerçekleştirildiğinde yüklenmemiş olması bile mümkündür. Kullanıcılar, uygulamanın durumundan bağımsız olarak uygulamayı devam ettirdiklerinde satın alma işlemlerini almayı beklerler.

Satın alma işlemlerini, uygulamanın satın alma işleminin yapıldığı durumdan bağımsız olarak tespit etmeniz gerekir. Bununla birlikte, öğenin alındığını kullanıcıya hemen bildirmemenin kabul edilebilir olduğu bazı istisnalar da vardır. Örneğin:

  • Oyunun aksiyon aşamasındaki bölümünde bir mesaj göstermenin kullanıcının dikkatini dağıtabileceği içerikler. Bu durumda, işlem bölümü bittikten sonra kullanıcıyı bilgilendirmeniz gerekir.
  • Ara verme sırasında, mesaj göstermek kullanıcının dikkatini dağıtabilir. Bu durumda, ara sahne sona erdikten sonra kullanıcıyı bilgilendirmeniz gerekir.
  • Oyunun ilk eğitim ve kullanıcı kurulumu bölümleri sırasında. Yeni kullanıcıları oyunu açar açmaz veya ilk kullanıcı kurulumu sırasında bilgilendirmenizi öneririz. Bununla birlikte, kullanıcıyı bilgilendirmek için ana oyun sırasının hazır olması da kabul edilebilir.

Uygulamanızın dışında yapılan satın alma işlemleriyle ilgili olarak kullanıcıları ne zaman ve nasıl bilgilendireceklerine karar verirken her zaman kullanıcıyı aklınızda bulundurun. Bir kullanıcı hemen bildirim almadığında kafası karışabilir ve uygulamanızı kullanmayı bırakabilir, kullanıcı desteğiyle iletişime geçebilir veya sosyal medyada şikayette bulunabilir. Not: PurchasesUpdatedListener, uygulamanızın dışında başlatılan satın alma işlemleri de dahil olmak üzere satın alma güncellemelerini işlemek için uygulama bağlamınıza kaydedilmiştir. Bu, uygulama işleminiz mevcut değilse PurchasesUpdatedListener cihazınıza bildirilmeyeceği anlamına gelir. Bu nedenle uygulamanız, Satın Alma İşlemleri bölümünde belirtildiği gibi onResume() yöntemini kullanarak BillingClient.queryPurchasesAsync() çağrısı yapmalıdır.

Bekleyen işlemleri işleme

Google Play, bekleyen işlemleri veya bir kullanıcının satın alma işlemini başlatması ile ödeme yönteminin işlenmesi arasında bir ya da daha fazla ek adım gerektiren işlemleri destekler. Google, kullanıcının ödeme yönteminden başarılı bir şekilde ödeme alındığını bildirene kadar uygulamanız bu tür satın alma işlemlerine izin vermemelidir.

Örneğin, bir kullanıcı ödeme şekli olarak nakit seçeneğini belirleyerek PENDING satın alma işlemi için uygulama içi öğe oluşturabilir. Kullanıcı daha sonra işlemi tamamlayacağı ve hem bildirim hem de e-posta yoluyla bir kod alacağı fiziksel bir mağaza seçebilir. Kullanıcı fiziksel mağazaya geldiğinde kasiyere kodu kullanıp nakit ödeme yapabiliyor. Google daha sonra hem size hem de kullanıcıya nakit alındığını bildirir. Uygulamanız daha sonra kullanıcıya yararlanma hakkı verebilir.

Uygulamanız, başlatma sırasında enablePendingPurchases() yöntemini çağırarak bekleyen işlemleri desteklemelidir.

Uygulamanız PurchasesUpdatedListener cihazınız üzerinden veya queryPurchasesAsync() çağrısının sonucunda yeni bir satın alma işlemi aldığında satın alma durumunun PURCHASED veya PENDING olduğunu belirlemek için getPurchaseState() yöntemini kullanın.

Kullanıcı satın alma işlemini tamamladığında uygulamanız çalışıyorsa PurchasesUpdatedListener yeniden çağrılır ve PurchaseState artık PURCHASED olur. Bu noktada, uygulamanız tek seferlik satın alma işlemlerini işleme için standart yöntemi kullanarak satın alma işlemini işleyebilir. Uygulamanız, çalışmadığı sırada PURCHASED durumuna geçen satın alma işlemlerini işlemek için uygulamanızın onResume() yönteminde queryPurchasesAsync() yöntemini de çağırmalıdır.

Uygulamanız ayrıca OneTimeProductNotifications dinleyerek bekleyen satın alma işlemleriyle ilgili Gerçek zamanlı geliştirici bildirimlerini kullanabilir. Satın alma işlemi PENDING-PURCHASED arasında geçtiğinde uygulamanız bir ONE_TIME_PRODUCT_PURCHASED bildirimi alır. Satın alma işlemi iptal edilirse uygulamanız bir ONE_TIME_PRODUCT_CANCELED bildirimi alır. Müşteriniz ödemeyi gereken süre içinde tamamlamazsa bu durumla karşılaşılabilir. Bu bildirimleri alırken, Purchases.products için PENDING durumunu içeren Google Play Geliştirici API'sini kullanabilirsiniz.

Bu senaryonun nasıl test edileceğiyle ilgili ayrıntılı adımları, Bekleyen satın alma işlemlerini test etme bölümünde bulabilirsiniz.

Çoklu miktar satın alma işlemlerini yönetme

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

Çoklu miktar satın alma işlemlerinin gerçekleştirilebilmesi için uygulamanızın temel hazırlık mantığının, öğe miktarını kontrol etmesi gerekir. quantity alanına aşağıdaki API'lerin birinden erişebilirsiniz:

Çoklu miktar satın alma işlemlerini işlemek için gereken mantığı ekledikten sonra, Google Play Geliştirici Konsolu'ndaki 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çin 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() çağrısının nasıl yapılacağı açıklanmaktadır. BillingConfigResponseListener öğesini uygulayarak yanıtı ele alın. Bu işleyici, uygulamanızdan başlatılan tüm faturalandırma yapılandırması sorguları için güncelleme alır.

Döndürülen BillingResult hiç hata içermiyorsa kullanıcının Play Country'sini 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
        }
      }
    });