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.
- Kullanıcıya neler satın alabileceğini gösterin.
- Kullanıcının satın alma işlemini kabul etmesi için satın alma akışını başlatın.
- Satın alma işlemini sunucunuzda doğrulayın.
- Kullanıcıya içerik verin.
- İç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 = "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ı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 = "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") }
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) // 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ğ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 = 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 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.](https://developer.android.com/static/images/google/play/billing/purchase-screen.png?authuser=5&hl=tr)
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'de satın alma başarılı ekranı](https://developer.android.com/static/images/google/play/billing/purchase-success.png?authuser=5&hl=tr)
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ı.](https://developer.android.com/static/images/google/play/billing/personalized-pricing.png?authuser=5&hl=tr)
Bu Ek Sözleşme'nin Kullanıcılara sunduğunuz fiyatın kişiselleştirilmiş olup olmadığının belirlenmesi için 2011/83/EU Tüketici Hakları Yönergesi'nin 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şlemiyle ilgili olarak 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 bir satın alma işlemini aşağıdaki şekilde işlemelidir:
- Satın alma işlemini doğrulayın.
- 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<Purchase> purchases) { // check billingResult // process returned purchase list, e.g. display the plans user owns } } );
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. Örnek:
- 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, kullanıcı daha sonra nakit ödeme yapacağı fiziksel bir mağaza 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 kasiyerle kodu kullanıp nakit ödeme yapabilir. Google daha sonra hem size hem de kullanıcıya ödemenin alındığını bildirir. Uygulamanız daha sonra kullanıcıya yararlanma hakkı verebilir.
Uygulamanızın bekleyen işlemleri etkinleştirmek için BillingClient
uygulamasını başlatma işleminin bir parçası olarak enablePendingPurchases()
numaralı telefonu arayın. Uygulamanızın tek seferlik ürünler için bekleyen işlemleri etkinleştirmesi ve desteklemesi gerekir. Destek eklemeden önce beklemedeki işlemlerin satın alma yaşam döngüsünü anladığınızdan emin olun.
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. Yararlanma hakkı yalnızca durum PURCHASED
olduğunda vermelisiniz.
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. Uygulamanız bu noktada 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.
Satın alma işlemi PENDING
tarihinden PURCHASED
aboneliğine geçtiğinde, Gerçek zamanlı geliştirici bildirimleri istemciniz bir
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. Müşteriniz ödemeyi gereken süre içinde tamamlamazsa bu durumla karşılaşılabilir. Bir satın alma işleminin mevcut durumunu kontrol etmek için her zaman Google Play Developer API'yi kullanabileceğinizi unutmayın.
Ç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:
- Google Play Faturalandırma Kitaplığı'ndan
getQuantity()
. - Google Play Developer API'den
Purchases.products.quantity
.
Ç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
}
}
});