Bu belgede, ürün satmaya başlamak için Google Play Faturalandırma Kitaplığı'nı uygulamanıza nasıl entegre edeceğiniz açıklanmaktadır.
Satın alma süreci
Tek seferlik satın alma veya abonelik için tipik bir satın alma süreci aşağıda verilmiştir.
- Kullanıcıya ne satın alabileceğini gösterin.
- Kullanıcının satın alma işlemini kabul etmesi için satın alma sürecini başlatın.
- Satın alma işlemini sunucunuzda doğrulayın.
- Kullanıcıya içerik verin.
- İçeriğin teslim edildiğini onaylayın. Tüketilebilir ürünler için satın alma işlemini tüketin. Böylece kullanıcı, öğeyi tekrar satın alabilir.
Abonelikler iptal edilene kadar otomatik olarak yenilenir. Abonelikler aşağıdaki durumlardan geçebilir:
- Etkin: Kullanıcı iyi durumda ve aboneliğe erişimi var.
- İptal edildi: Kullanıcı iptal etti ancak geçerlilik süresi dolana kadar erişimi devam ediyor.
- Ek süre içinde: Kullanıcı, ödeme sorunu yaşamasına rağmen Google ödeme yöntemini tekrar denerken erişime devam eder.
- Beklemede: Kullanıcı, ödeme sorunu yaşadı ve Google ödeme yöntemini tekrar denerken artık erişimi yok.
- Duraklatıldı: Kullanıcı erişimini duraklatmıştır ve devam ettirene kadar erişimi yoktur.
- Süresi doldu: Kullanıcı aboneliği iptal etti ve aboneliğe erişimini kaybetti. Kullanıcı, abonelik süresi dolduğunda kaybedilmiş olarak kabul edilir.
Google Play'e bağlantı başlatma
Google Play'in faturalandırma sistemiyle entegrasyonun ilk adımı, Google Play Faturalandırma Kitaplığı'nı uygulamanıza eklemek ve bir bağlantı başlatmaktır.
Google Play Faturalandırma Kitaplığı bağımlılığını ekleme
Google Play Faturalandırma Kitaplığı bağımlılığını, uygulamanızın build.gradle
dosyasına aşağıdaki gibi ekleyin:
Modern
dependencies { def billing_version = "9.1.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "9.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ı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ığı gösterildiği gibi ekleyin:
Modern
dependencies { def billing_version = "9.1.0" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Kotlin
dependencies { val billing_version = "9.1.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
BillingClient'ı başlatma
Google Play Faturalandırma Kitaplığı'na bağımlılık ekledikten sonra bir BillingClient örneği başlatmanız gerekir. BillingClient, Google Play Faturalandırma Kitaplığı ile uygulamanızın geri kalanı arasındaki iletişim için kullanılan ana arayüzdür. BillingClient, birçok yaygın faturalandırma işlemi için hem eşzamanlı hem de eşzamansız kolaylık yöntemleri sağlar. Aşağıdakileri göz önünde bulundurun:
- Tek bir etkinlik için birden fazla
PurchasesUpdatedListenergeri araması yapılmasını önlemek amacıyla, aynı anda yalnızca bir etkinBillingClientbağlantısı açmanız önerilir. - Uygulamanızın satın alma işlemlerini zamanında gerçekleştirmesi için uygulamanız başlatıldığında veya ön plana geldiğinde BillingClient için bir bağlantı başlatmanız önerilir. Bunu yapmak için
registerActivityLifecycleCallbackstarafından kaydedilenActivityLifecycleCallbackskullanın ve bir etkinliğin devam ettirildiğini ilk kez algıladığınızda bağlantı başlatmak için onActivityResumed'i dinleyin. Bu en iyi uygulamanın neden kullanılması gerektiği hakkında daha fazla bilgi için satın alma işlemlerini işleme bölümüne bakın. Ayrıca, uygulamanız kapatıldığında bağlantıyı sonlandırmayı unutmayın.
BillingClient oluşturmak için newBuilder kullanın. newBuilder() işlevine herhangi bir bağlam iletebilirsiniz. BillingClient, uygulama bağlamı almak için bu bağlamı kullanır. Bu sayede bellek sızıntıları konusunda endişelenmenize gerek kalmaz. Satın alma işlemleriyle ilgili güncellemeler almak için setListener işlevini de çağırarak PurchasesUpdatedListener öğesine referans iletmeniz gerekir. Bu dinleyici, uygulamanızdaki tüm satın alma işlemleriyle ilgili güncellemeleri alır.
Kotlin
private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases -> // To be implemented in a later section. } private var billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) // Configure other settings. .build()
Java
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
// To be implemented in a later section.
}
};
private BillingClient billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
// Configure other settings.
.build();
Google Play'e bağlanma
BillingClient oluşturduktan sonra Google Play ile bağlantı kurmanız gerekir.
Google Play'e bağlanmak için startConnection numaralı telefonu arayın. Bağlantı süreci eşzamansızdır ve istemcinin kurulumu tamamlanıp başka istekler göndermeye hazır olduğunda geri arama almak için BillingClientStateListener uygulamanız gerekir.
Otomatik hizmet yeniden bağlantısını etkinleştirmediyseniz Google Play ile bağlantı kaybını yönetmek 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'nin başka istekler göndermeden önce Google Play'e yeniden bağlanmak için startConnection() yöntemini çağırdığından emin olun. Otomatik hizmet yeniden bağlantısını etkinleştirdiyseniz bu yöntemi no-op olarak uygulayabilirsiniz.
Aşağıdaki örnekte, bir bağlantının nasıl başlatılacağı ve kullanıma hazır olup olmadığının nasıl test edileceği gösterilmektedir:
Kotlin
billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } override fun onBillingServiceDisconnected() { // If automatic service reconnection is enabled, this can be left empty (no-op) // because the library handles retries. You can still use this for non-retry // tasks like logging or updating the UI to reflect a disconnected state. // Otherwise, 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. // It's a good practice to query products after the connection is established. queryProductDetails(); } } @Override public void onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. // This is automatically handled by the library when you call a method that requires a connection. } });
Bağlantıyı Otomatik Olarak Yeniden Kurma
8.0.0 sürümünde BillingClient.Builder'e enableAutoServiceReconnection() yöntemi eklendiğinden beri Play Faturalandırma Kitaplığı, hizmet bağlantısı kesilmişken bir API çağrısı yapılması durumunda hizmet bağlantısını otomatik olarak yeniden kurabilir. Yeniden bağlantı, API çağrısı yapılmadan önce dahili olarak işlendiğinden bu durum SERVICE_DISCONNECTED yanıtlarında azalmaya yol açabilir.
Otomatik yeniden bağlanmayı etkinleştirme
Bir BillingClient örneği oluştururken otomatik yeniden bağlanmayı etkinleştirmek için BillingClient.Builder içindeki enableAutoServiceReconnection() yöntemini kullanın.
Kotlin
val billingClient = BillingClient.newBuilder(context) .setListener(listener) .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build()) .enableAutoServiceReconnection() // Add this line to enable reconnection .build()
Java
BillingClient billingClient = BillingClient.newBuilder(context)
.setListener(listener)
.enablePendingPurchases()
.enableAutoServiceReconnection() // Add this line to enable reconnection
.build();
Satın alınabilecek ürünleri gösterme
Google Play ile bağlantı kurduktan sonra mevcut ürünlerinizi sorgulamaya ve kullanıcılarınıza göstermeye hazır olursunuz.
Ürün ayrıntıları için sorgu göndermek, yerelleştirilmiş ürün bilgileri döndürdüğünden ürünlerinizi kullanıcılarınıza göstermeden önce yapılması gereken önemli bir adımdır. Abonelikler için ürün gösteriminizin tüm Google Play politikalarına uyduğundan emin olun.
Tek seferlik ürün ayrıntılarını sorgulamak için queryProductDetailsAsync
yöntemini çağırın. Bu yöntem, tek seferlik ürün yapılandırmanıza bağlı olarak birden fazla fırsat döndürebilir. Daha fazla bilgi için Tek seferlik ürünler için birden fazla satın alma seçeneği ve teklif başlıklı makaleyi inceleyin.
Asenkron işlemin sonucunu işlemek için ProductDetailsResponseListener arayüzünü uygulayan bir dinleyici de belirtmeniz gerekir.
Ardından, aşağıdaki örnekte gösterildiği gibi, sorgu tamamlandığında dinleyiciyi bilgilendiren onProductDetailsResponse yöntemini geçersiz kılabilirsiniz:
Kotlin
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( listOf( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build() ) ) .build() billingClient.queryProductDetailsAsync(queryProductDetailsParams) { billingResult, queryProductDetailsResult -> if (billingResult.responseCode == BillingResponseCode.OK) { for (productDetails in queryProductDetailsResult.productDetailsList) { // Process successfully retrieved product details here. } for (unfetchedProduct in queryProductDetailsResult.unfetchedProductList) { // Handle any unfetched products as appropriate. } } }
Java
QueryProductDetailsParams queryProductDetailsParams =
QueryProductDetailsParams.newBuilder()
.setProductList(
ImmutableList.of(
Product.newBuilder()
.setProductId("product_id_example")
.setProductType(ProductType.SUBS)
.build()))
.build();
billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener() {
public void onProductDetailsResponse(BillingResult billingResult,
QueryProductDetailsResult queryProductDetailsResult) {
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
for (ProductDetails productDetails : queryProductDetailsResult.getProductDetailsList()) {
// Process successfully retrieved product details here.
}
for (UnfetchedProduct unfetchedProduct : queryProductDetailsResult.getUnfetchedProductList()) {
// Handle any unfetched products as appropriate.
}
}
}
}
)
Ürün ayrıntılarını sorgularken Google Play Console'da oluşturulan ürün kimliği dizelerinin listesini ve ProductType değerini 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ını kullanıyorsanız queryProductDetails() uzantı işlevini çağırarak tek seferlik ürün ayrıntılarını sorgulayabilirsiniz.
queryProductDetails(), ayrı bir dinleyici tanımlamanıza gerek kalmaması için Kotlin eşyordamlarından yararlanır. Bunun yerine, sorgulama tamamlanana kadar işlev askıya alınır. Ardından sonucu işleyebilirsiniz:
suspend fun processPurchases() { val productList = listOf( QueryProductDetailsParams.Product.newBuilder() .setProductId("product_id_example") .setProductType(BillingClient.ProductType.SUBS) .build() ) val params = QueryProductDetailsParams.newBuilder() params.setProductList(productList) // leverage queryProductDetails Kotlin extension function val productDetailsResult = withContext(Dispatchers.IO) { billingClient.queryProductDetails(params.build()) } // Process the result. }
Nadir durumlarda, genellikle Google Play Hizmetleri'nin eski sürümleri nedeniyle bazı cihazlar ProductDetails ve queryProductDetailsAsync()'i destekleyemez. Bu senaryoya uygun destek sağlamak için Google Play Faturalandırma Kitaplığı 7 geçiş rehberinde geriye dönük uyumluluk özelliklerini nasıl kullanacağınızı öğrenin.
Sonucu işleme
Google Play Faturalandırma Kitaplığı, sorgu sonuçlarını bir QueryProductDetailsResult nesnesinde depolar. QueryProductDetailsResult
ProductDetails nesnelerinin List öğesini içerir. Ardından, başarıyla getirilen tek seferlik ürünle ilgili fiyat veya açıklama gibi alakalı bilgileri görüntülemek için listedeki her bir ProductDetails nesnesinde çeşitli yöntemleri çağırabilirsiniz. Kullanılabilir ürün ayrıntıları bilgilerini görüntülemek için ProductDetails sınıfındaki yöntemlerin listesine bakın.
QueryProductDetailsResult, List adet UnfetchedProduct nesnesi de içerir. Ardından, her UnfetchedProduct için sorgu göndererek getirme hatasının nedenine karşılık gelen durum kodunu alabilirsiniz.
Mevcut getirilmemiş ürün bilgilerini görüntülemek için UnfetchedProduct sınıfındaki yöntemlerin listesine bakın.
Bir öğeyi satışa sunmadan önce kullanıcının bu öğeye sahip olmadığından emin olun. Kullanıcının öğe kitaplığında hâlâ bir tüketilebilir öğe varsa tekrar satın alabilmesi için önce bu öğeyi tüketmesi gerekir.
Abonelik teklif etmeden önce kullanıcının zaten abone olmadığını doğrulayın. Ayrıca aşağıdakileri de göz önünde bulundurun:
Abonelikler için
queryProductDetailsAsync()yöntemi, abonelik ürünü ayrıntılarını ve abonelik başına en fazla 50 kullanıcıya uygun teklifi döndürür. Kullanıcı uygun olmayan bir teklifi satın almaya çalışırsa (örneğin, uygulama uygun tekliflerin güncel olmayan bir listesini gösteriyorsa) Google Play, kullanıcıyı uygun olmadığı konusunda bilgilendirir ve kullanıcı bunun yerine temel planı satın almayı seçebilir.Tek seferlik ürünler için
queryProductDetailsAsync()yöntemi yalnızca kullanıcıya uygun teklifleri döndürür. Kullanıcı, uygun olmadığı bir teklifi satın almaya çalışırsa (örneğin, kullanıcı satın alma miktar sınırına ulaştıysa) Google Play, kullanıcıyı uygun olmadığı konusunda bilgilendirir ve kullanıcı bunun yerine satın alma seçeneği teklifini satın almayı tercih edebilir.
Satın alma sürecini başlatma
Uygulamanızdan satın alma isteği başlatmak için uygulamanızın ana iş parçacığından launchBillingFlow() yöntemini çağırın. Bu yöntem, queryProductDetailsAsync çağrısından elde edilen ilgili ProductDetails nesnesini içeren bir BillingFlowParams nesnesine referans alır. BillingFlowParams nesnesi oluşturmak için BillingFlowParams.Builder sınıfını kullanın.
Kotlin
// An activity reference from which the billing flow will be launched. val activity : Activity = ... val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() // retrieve a value for productDetails by calling queryProductDetailsAsync() .setProductDetails(productDetails) // Get the offer token: // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList() // for a list of offers that are available to the user. // b. For subscriptions, call ProductDetails.getSubscriptionOfferDetails() // 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<BillingFlowParams.ProductDetailsParams> productDetailsParamsList = ImmutableList.of( BillingFlowParams.ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // Get the offer token: // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList() // for a list of offers that are available to the user. // b. For subscriptions, call ProductDetails.getSubscriptionOfferDetails() // for a list of offers that are available to the user. .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
launchBillingFlow() yöntemi, BillingClient.BillingResponseCode bölümünde listelenen çeşitli yanıt kodlarından birini döndürür. Satın alma sürecini başlatırken hata oluşmadığını doğrulamak için bu sonucu kontrol edin. OK değerindeki BillingResponseCode, başarılı bir lansmanı gösterir.
launchBillingFlow() başarılı bir şekilde çağrıldığında sistem, Google Play satın alma ekranını gösterir. Şekil 1'de bir aboneliğin satın alma ekranı gösterilmektedir:
Google Play, satın alma işleminin sonucunu PurchasesUpdatedListener arayüzünü uygulayan bir dinleyiciye iletmek için onPurchasesUpdated() yöntemini ç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() yöntemini uygulamanız gerekir. Aşağıdaki örnekte onPurchasesUpdated() değerinin nasıl geçersiz kılınacağı gösterilmektedir:
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) { if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { // Process the purchase as described in the next section. } } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user canceling the purchase flow. } else { // Handle any other error codes. } }
Java
@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
// Process the purchase as described in the next section.
}
} else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
// Handle an error caused by a user canceling the purchase flow.
} else {
// Handle any other error codes.
}
}
Başarılı bir satın alma işlemi, Şekil 2'deki Google Play satın alma işlemi başarıyla tamamlandı ekranına benzer bir ekran oluşturur.
Başarılı bir satın alma işlemi, kullanıcının ve satın aldığı tek seferlik ürünün ürün kimliğini temsil eden benzersiz bir tanımlayıcı olan satın alma jetonu da oluşturur. Uygulamalarınız satın alma jetonunu yerel olarak depolayabilir ancak jetonu güvenli arka uç sunucunuza iletmenizi önemle tavsiye ederiz. Bu sunucuda satın alma işlemini doğrulayabilir ve sahtekarlığa karşı koruma sağlayabilirsiniz. Bu işlem, Satın Alma İşlemlerini Algılama ve İşleme bölümünde daha ayrıntılı olarak açıklanmıştır.
Kullanıcıya, işlemle ilgili bir makbuz da e-postayla gönderilir. Bu makbuzda sipariş kimliği veya işlemin benzersiz kimliği yer alır. Kullanıcılar, her tek seferlik ürün satın alma işlemi, ilk abonelik satın alma işlemi ve sonraki yinelenen otomatik yenilemeler için benzersiz bir sipariş kimliği içeren bir e-posta alır. Google Play Console'da geri ödemeleri yönetmek için sipariş kimliğini kullanabilirsiniz.
Kişiselleştirilmiş bir fiyat belirtme
Uygulamanız Avrupa Birliği'ndeki kullanıcılara dağıtılabiliyorsa launchBillingFlow yöntemini çağırırken setIsOfferPersonalized() yöntemini kullanarak kullanıcılara bir öğenin fiyatının otomatik karar alma kullanılarak kişiselleştirildiğini açıklayın.
DSA'nın 21. maddesine bakmanız gerekir. Kullanıcılara sunduğunuz fiyatın kişiselleştirilmiş olup olmadığını belirlemek için lütfen Tüketici Hakları Yönergesi'nin 2011/83/EU 6. (1) (ea) maddesine bakın.
setIsOfferPersonalized(), boole girişi alır. true olduğunda Google Play kullanıcı arayüzünde açıklama gösterilir. false olduğunda kullanıcı arayüzü açıklamayı göstermez. Varsayılan değer: false.
Daha fazla bilgi için Tüketici Yardım Merkezi'ne göz atabilirsiniz.
Kullanıcı kimlikleri ekleme
Satın alma sürecini başlattığınızda uygulamanız, satın alma işlemini yapan kullanıcı için sahip olduğunuz tüm kullanıcı tanımlayıcılarını obfuscatedAccountId veya �obfuscatedProfileId kullanarak ekleyebilir. Örneğin, tanımlayıcı olarak kullanıcının sisteminizdeki girişinin karartılmış bir sürümü kullanılabilir. Bu parametreleri ayarlamak, Google'ın sahtekarlığı tespit etmesine yardımcı olabilir. Ayrıca, kullanıcılara haklar verme bölümünde açıklandığı gibi, satın alma işlemlerinin doğru kullanıcıyla ilişkilendirilmesini sağlamanıza yardımcı olabilir.
Satın alma işlemlerini algılama ve işleme
Bu bölümde açıklanan satın alma işleminin tespiti ve işlenmesi, promosyon kullanımları gibi uygulama dışı satın alma işlemleri de dahil olmak üzere her tür satın alma işlemi için geçerlidir.
Uygulamanız, yeni satın alma işlemlerini ve tamamlanan bekleyen satın alma işlemlerini aşağıdaki yöntemlerden biriyle algılar:
onPurchasesUpdated, uygulamanızınlaunchBillingFlow'ı çağırması sonucunda (önceki bölümde ele alındığı gibi) çağrıldığında veya uygulamanız, uygulama dışında yapılan bir satın alma işlemi olduğunda ya da bekleyen bir satın alma işlemi tamamlandığında etkin bir Faturalandırma Kitaplığı bağlantısıyla çalışıyorsa. Örneğin, bir aile üyesi başka bir cihazda bekleyen bir satın alma işlemini onaylar.- Uygulamanız, kullanıcının satın alma işlemlerini sorgulamak için queryPurchasesAsync yöntemini çağırdığında.
1 numaralı yöntem için uygulamanız çalıştığı ve etkin bir Google Play Faturalandırma Kitaplığı bağlantısı olduğu sürece yeni veya tamamlanmış satın alma işlemleri için onPurchasesUpdated otomatik olarak çağrılır. Uygulamanız çalışmıyorsa veya uygulamanızın etkin bir Google Play Faturalandırma Kitaplığı bağlantısı yoksa onPurchasesUpdated çağrılmaz. Uygulamanızın zamanında satın alma güncellemeleri alabilmesi için uygulamanız ön planda olduğu sürece etkin bir bağlantı sürdürmeye çalışması önerilir.
2. sorun için, uygulamanızın tüm satın alma işlemlerini işlediğinden emin olmak üzere BillingClient.queryPurchasesAsync() işlevini çağırmanız gerekir. Bu işlemi, uygulamanız Google Play Faturalandırma Kitaplığı ile başarılı bir şekilde bağlantı kurduğunda yapmanız önerilir (Bu, uygulamanız başlatıldığında veya BillingClient'ı başlatma bölümünde belirtildiği gibi ön plana geldiğinde önerilir). Bu, onServiceConnected için başarılı bir sonuç alındığında queryPurchasesAsync çağrılarak yapılabilir. Bu öneriyi uygulamak, aşağıdaki gibi etkinlik ve durumları yönetmek için çok önemlidir:
- Satın alma işlemi sırasında ağ sorunları: Kullanıcı başarılı bir satın alma işlemi yapıp Google'dan onay alabilir ancak cihazı ve uygulamanız
PurchasesUpdatedListenerüzerinden satın alma işlemi bildirimi almadan önce cihazının ağ bağlantısı kesilir. - Birden fazla cihaz: Kullanıcı bir cihazda satın aldığı öğeyi başka bir cihaza geçtiğinde de görmek isteyebilir.
- Uygulamanızın dışında yapılan satın alma işlemlerini işleme: Promosyon kullanma gibi bazı satın alma işlemleri uygulamanızın dışında yapılabilir.
- Satın alma durumu geçişlerini işleme: Kullanıcı, uygulamanız çalışmıyorken BEKLEMEDE olan bir satın alma işleminin ödemesini tamamlayabilir ve uygulamanızı açtığında satın alma işlemini tamamladığına dair onay almayı bekleyebilir.
- Askıya alınmış abonelikler: Abonelik, abonelik yaşam döngüsü sırasında askıya alınabilir. BillingClient.queryPurchasesAsync(), askıya alınmış abonelikleri yalnızca
includeSuspendedSubscriptionsparametresiQueryPurchasesParams.Builderüzerinde ayarlanmışsa döndürür. Askıya alınmış aboneliklerPurchasesUpdatedListeneriçinde döndürülmez.
Uygulamanız yeni veya tamamlanmış bir satın alma işlemi algıladığında:
- Satın alma işlemini doğrulayın.
- Tamamlanan satın alma işlemleri için kullanıcıya içerik erişimi verme
- Kullanıcıyı bilgilendirin.
- Google'a, uygulamanızın tamamlanan satın alma işlemlerini işlediğini bildirin.
Bu adımlar aşağıdaki bölümlerde ayrıntılı olarak ele alınmakta ve ardından tüm adımları özetleyen bir bölüm yer almaktadır.
Satın alma işlemini doğrulama
Uygulamanız, kullanıcılara avantajlar sunmadan önce her zaman satın alma işlemlerinin geçerliliğini doğrulamalıdır. Bunu yapmak için Yararlanma hakkı vermeden önce satın alma işlemlerini doğrulama bölümünde açıklanan yönergeleri uygulayabilirsiniz. Uygulamanız, satın alma işlemini yalnızca doğruladıktan sonra işlemeye devam etmeli ve kullanıcıya yetki vermelidir. Bu konu, sonraki bölümde ele alınmıştır. Bir satın alma işlemi doğrulama, uygunluk veya kötüye kullanım kontrollerinizden geçemezse Reddedilen veya yerine getirilmeyen satın alma işlemlerini işleme başlıklı makaleyi inceleyin.
Kullanıcıya yararlanma hakkı verme
Uygulamanız bir satın alma işlemini doğruladıktan sonra kullanıcıya hak vermeye devam edebilir ve kullanıcıyı bilgilendirebilir. Hak vermeden önce uygulamanızın satın alma durumunun PURCHASED olduğunu kontrol ettiğini doğrulayın. Satın alma işlemi BEKLEMEDE durumundaysa uygulamanız, hak verilmeden önce kullanıcının satın alma işlemini tamamlamak için gerekli işlemleri yapması gerektiğini bildirmelidir.
Yalnızca satın alma işlemi BEKLEMEDE durumundan SATIN ALINDI durumuna geçtiğinde yararlanma hakkı verin.
Ek bilgileri Bekleyen işlemleri yönetme başlıklı makalede bulabilirsiniz.
Kullanıcı kimlikleri ekleme bölümünde açıklandığı gibi satın alma işlemine kullanıcı kimlikleri eklediyseniz bunları alabilir ve sisteminizdeki doğru kullanıcıyla ilişkilendirmek için kullanabilirsiniz. Bu teknik, uygulamanızın bir satın alma işleminin hangi kullanıcıya ait olduğuyla ilgili bağlamı kaybettiği durumlarda satın alma işlemlerini uzlaştırmak için yararlıdır. Google Play, kötüye kullanıma karşı korunmak için hak vermeden önce bu tanımlayıcıları güvenli arka ucunuzda doğrulamanızı önerir. Daha fazla bilgi için Hak vermeden önce satın alma işlemlerini doğrulama başlıklı makaleyi inceleyin. Uygulamanızın dışında yapılan satın alma işlemlerinde bu tanımlayıcıların ayarlanmayacağını unutmayın. Bu durumda uygulamanız, oturum açmış kullanıcıya hak verebilir veya kullanıcıdan tercih ettiği hesabı seçmesini isteyebilir.
Ön siparişlerde, satın alma işlemi yayınlanma zamanına ulaşılmadan önce BEKLEMEDE durumundadır. Ön sipariş satın alma işlemi, yayınlanma zamanında tamamlanır ve ek işlem yapılmadan durum SATIN ALINDI olarak değişir.
Kullanıcıyı bilgilendirme
Kullanıcıya yetki verdikten sonra uygulamanız, başarılı satın alma işlemini onaylamak için bir bildirim göstermelidir. Bildirim sayesinde kullanıcı, satın alma işleminin başarıyla tamamlanıp tamamlanmadığı konusunda kafa karışıklığı yaşamaz. Bu kafa karışıklığı, kullanıcının uygulamanızı kullanmayı bırakmasına, kullanıcı desteğiyle iletişime geçmesine veya sosyal medyada bu konuda şikayette bulunmasına neden olabilir. Uygulamanızın, uygulama yaşam döngüsü sırasında herhangi bir zamanda satın alma güncellemelerini algılayabileceğini unutmayın. Örneğin, bir ebeveyn başka bir cihazda bekleyen bir satın alma işlemini onayladığında uygulamanız, kullanıcıyı uygun bir zamanda bilgilendirmek için bildirimi geciktirmek isteyebilir. Gecikmenin uygun olacağı bazı örnekler:
- Oyunun aksiyon bölümünde veya ara sahnelerde mesaj göstermek kullanıcının dikkatini dağıtabilir. Bu durumda, işlem bölümü bittikten sonra kullanıcıyı bilgilendirmeniz gerekir.
- Oyunun ilk öğretici ve kullanıcı kurulumu bölümlerinde. Örneğin, bir kullanıcı uygulamanızı yüklemeden önce uygulamanızın dışında bir satın alma işlemi yapmış olabilir. Yeni kullanıcıları, oyunu açtıktan hemen sonra veya ilk kullanıcı kurulumu sırasında ödül hakkında bilgilendirmenizi öneririz. Uygulamanız, kullanıcıya hak vermeden önce kullanıcının hesap oluşturmasını veya giriş yapmasını gerektiriyorsa kullanıcınıza, satın alma işlemini tamamlamak için hangi adımları tamamlaması gerektiğini bildirmeniz önerilir. Uygulamanız satın alma işlemini işlemediyse satın alma işlemleri 3 gün sonra geri ödendiğinden bu çok önemlidir.
Google Play, kullanıcıyı satın alma işlemi hakkında bilgilendirirken aşağıdaki mekanizmaları kullanmanızı önerir:
- Uygulama içi iletişim kutusu gösterme
- Mesajı uygulama içi mesaj kutusuna teslim etme ve uygulama içi mesaj kutusunda yeni bir mesaj olduğunu açıkça belirtme.
- İşletim sistemi bildirim mesajı kullanın.
Bildirim, kullanıcıyı aldığı avantaj hakkında bilgilendirmelidir. Örneğin, "100 altın para satın aldınız!". Ayrıca, satın alma işlemi Play Pass gibi bir programın avantajı sonucunda gerçekleştiyse uygulamanız bunu kullanıcıya bildirir. Örneğin, "Öğeler alındı! Google Play Pass ile 100 Mücevher kazandınız. Devam et.". Her programda, kullanıcılara avantajları bildirmek için gösterilecek önerilen metinle ilgili yönergeler bulunabilir.
Satın alma işleminin işlendiğini Google'a bildirme
Uygulamanız kullanıcıya yetki verdikten ve başarılı işlem hakkında bildirim gönderdikten sonra, satın alma işleminin başarıyla işlendiğini Google'a bildirmelidir. Bu işlem, satın alma işlemini onaylayarak yapılır ve satın alma işleminin otomatik olarak geri ödenmemesi ve hakların iptal edilmemesi için üç gün içinde tamamlanmalıdır. Farklı satın alma türlerinin onaylanması süreci aşağıdaki bölümlerde açıklanmaktadır.
Sarf malzemesi ürünler
Tüketilebilir ürünler için uygulamanızın güvenli bir arka ucu varsa satın alma işlemlerini güvenilir bir şekilde tüketmek üzere Purchases.products:consume kullanmanızı öneririz. Purchases.products:get çağrısının sonucundaki consumptionState değerini kontrol ederek satın alma işleminin daha önce tüketilmediğinden emin olun. Uygulamanız yalnızca istemci tarafında çalışıyor ve arka ucu yoksa Google Play Faturalandırma Kitaplığı'ndaki consumeAsync() öğesini kullanın. Her iki yöntem de onay şartını karşılar ve uygulamanızın kullanıcıya 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 ConsumeResponseListener arayüzünü uygulayan bir nesne de iletmeniz 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 jetonu kullanılarak Google Play Faturalandırma Kitaplığı ile bir ürünün tüketilmesi gösterilmektedir:
Kotlin
val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build() val consumeResult = withContext(Dispatchers.IO) { client.consumePurchase(consumeParams) }
Java
ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build(); ConsumeResponseListener listener = (billingResult, purchaseToken) -> { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Handle the success of the consume operation. } }; billingClient.consumeAsync(consumeParams, listener);
Tüketilemeyen ürünler
Tüketilemeyen satın alma işlemlerini onaylamak için uygulamanızın güvenli bir arka ucu varsa satın alma işlemlerini güvenilir bir şekilde onaylamak için Purchases.products:acknowledge kullanmanızı öneririz. Purchases.products:get çağrısının sonucundaki acknowledgementState değerini kontrol ederek satın alma işleminin daha önce onaylanmadığından emin olun.
Uygulamanız yalnızca istemci tarafındaysa uygulamanızda Google Play Faturalandırma Kitaplığı'ndaki 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ığı'nı kullanarak satın alma işleminin nasıl onaylanacağı gösterilmektedir:
Kotlin
val client: BillingClient = billingClient val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.purchaseToken) val ackPurchaseResult = withContext(Dispatchers.IO) { client.acknowledgePurchase(acknowledgePurchaseParams.build()) }
Java
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) { if (!purchase.isAcknowledged()) { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); billingClient.acknowledgePurchase(acknowledgePurchaseParams, (billingResult) -> { // Acknowledgment handled. }); } }
Abonelikler
Abonelikler, tüketilmeyen ürünlere benzer şekilde ele alınır. Mümkünse güvenli arka ucunuzdaki satın alma işlemini güvenilir bir şekilde onaylamak için Google Play Developer API'den Purchases.subscriptions.acknowledge kullanın. Purchases.subscriptions:get kaynağından gelen satın alma kaynağındaki acknowledgementState işaretini kontrol ederek satın alma işleminin daha önce onaylanmadığını doğrulayın. Aksi takdirde, isAcknowledged() değerini kontrol ettikten sonra Google Play Faturalandırma Kitaplığı'ndaki BillingClient.acknowledgePurchase() yöntemini 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.
Reddedilen veya tamamlanmamış satın alma işlemlerini yönetme
Bir satın alma işlemi arka uç doğrulamanızdan, kullanıcı uygunluk kontrollerinizden, sahtekarlık ve kötüye kullanım kontrollerinizden geçemezse veya sisteminiz yararlanma hakkını yerine getiremezse yararlanma hakkını vermeyin ve satın alma işlemini onaylamayın veya kullanmayın.
Onaylanmamış satın alma işlemleri, onay süresi sona erdikten sonra tüketici güvenliği için otomatik olarak geri ödenir ve iptal edilir. Ancak satın alma işlemlerini reddetmek için bu sürenin dolmasını beklemeyin. Onay penceresinin süresinin dolmasına izin vermek, siparişi onaylanmamış durumda bırakır ve Google Play için belirsizliğe neden olur. Google Play, geliştiricinin kasıtlı olarak reddetmesi ile arka uç işleme zaman aşımı arasındaki farkı ayırt edemez.
Bunun yerine, Google Play Developer API'yi kullanarak reddedilen satın alma işlemlerini arka ucunuzdan hemen iptal edin ve geri ödeyin:
- Abonelikler:
revocationContextiçinde"fullRefund": {}ilepurchases.subscriptionsv2.revokeyöntemini çağırın. Bu işlem, aboneliği derhal sonlandırır, erişimi iptal eder ve eksiksiz geri ödeme başlatır. - Tek seferlik ürünler: Bir siparişi anında iade etmek ve siparişin haklarını iptal etmek için
orders.refundişlevinirevokeparametresitrueolarak ayarlanmış şekilde çağırın. Bu yöntemi çağırırken satın alma işleminin sipariş kimliğini iletmeniz gerekir. Bu kimlik,Purchase.getOrderId()veyapurchases.productsv2.getproductpurchasev2aracılığıyla alınabilir. Reddedilen satın alma işlemlerinde hiçbir zamanconsumeAsync(),acknowledgePurchase(),Purchases.products:consumeveyaPurchases.products:acknowledgeyöntemlerini çağırmayın. - RTDN ve Voided Purchases API davranışı: Geliştirici tarafından başlatılan iptaller ve geri ödemeler (
revoke,trueolarak ayarlanmışkenpurchases.subscriptionsv2.revokeveorders.refund), gerçek zamanlı geliştirici bildirimlerini tetikler ve Voided Purchases API'ye kaydedilir (geliştirici içinvoidedSourceyanıt alanı1olarak ayarlanmışkenpurchases.voidedpurchases.list):- Abonelikler: Hem
SUBSCRIPTION_REVOKEDbildirimi hem deVoidedPurchaseNotificationgönderir. - Tek seferlik ürünler:
VoidedPurchaseNotification(ve uygulamanız Play Console'da tüm tek seferlik ürün bildirimlerini alacak şekilde yapılandırılmışsaONE_TIME_PRODUCT_CANCELEDbildirimi) gönderir. revoke,trueolarak ayarlanmadanorders.refundişlevinin çağrılması, hak iptal edilmeden siparişi iade eder ve iptal veya geçersiz kılınan satın alma bildirimi tetiklemez. Daha fazla bilgi için Abonelikleri ve tek seferlik satın alma işlemlerini yönetme başlıklı makaleyi inceleyin.
- Abonelikler: Hem
Özet
Aşağıda bu adımların bir özeti verilmiştir.
Yararlanma hakkı vermeden önce satın alma işlemlerini doğrulamak için satın alma işlemini güvenli arka ucunuza gönderin.
Satın alma işlemiyle yararlanma hakkı depolama alanınızı güncelleyin. Satın alma işlemi BEKLEMEDE durumundaysa hak sahipliğinin beklemede olarak işaretlendiğinden ve kullanıcının henüz avantajlardan yararlanmadığından emin olun. Bu adımın güvenli arka ucunuzda yapılması ve 1. adımda arka ucunuza yapılan API çağrısında birleştirilmesi önerilir.
Uygun mesajları kullanarak kullanıcıyı bilgilendirin (gerekirse bildirimi daha önce açıklandığı şekilde geciktirin).
Satın alma işlemlerinin işlenmesi bölümünde açıklanan adımları uygulayarak satın alma işleminin işlendiğini Google'a bildirin.
Uygulamanızın bu adımları doğru şekilde uygulayıp uygulamadığını doğrulamak için test kılavuzunu inceleyebilirsiniz.
Bekleyen işlemleri yönetme
Google Play, bekleyen işlemleri veya kullanıcının satın alma işlemini başlatması ile satın alma işleminin ödeme yönteminin işlenmesi 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ı size bildirene kadar uygulamanız bu tür satın alma işlemlerine hak 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 kod alır. Kullanıcı fiziksel mağazaya geldiğinde kasiyere kodu göstererek kullanabilir ve nakit ödeme yapabilir. Ardından Google, ödemenin alındığını hem size hem de kullanıcıya bildirir. Uygulamanız daha sonra kullanıcıya yararlanma hakkı verebilir.
Uygulamanızda bekleyen işlemleri etkinleştirmek için BillingClient başlatma işleminin bir parçası olarak enablePendingPurchases() yöntemini çağırın. Uygulamanızın, tek seferlik ürünler için bekleyen işlemleri etkinleştirmesi ve desteklemesi gerekir. Destek eklemeden önce, bekleyen işlemler için satın alma yaşam döngüsünü anladığınızdan emin olun.
Uygulamanız PurchasesUpdatedListener aracılığıyla veya queryPurchasesAsync çağrısı sonucunda yeni bir satın alma işlemi aldığında satın alma durumunun PURCHASED veya PENDING olup olmadığını belirlemek için getPurchaseState() yöntemini kullanın. Yetkilendirme işlemini yalnızca durum PURCHASED olduğunda yapmalısınız.
Uygulamanız çalışıyorsa ve kullanıcı satın alma işlemini tamamladığında etkin bir Play Faturalandırma Kitaplığı bağlantınız varsa PurchasesUpdatedListener tekrar çağrılır ve PurchaseState artık PURCHASED olur. Bu noktada uygulamanız, Satın Alma İşlemlerini Algılama ve İşleme için standart yöntemi kullanarak satın alma işlemini gerçekleştirebilir. Uygulamanız çalışmıyorken 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 durumundan PURCHASED durumuna geçtiğinde real_time_developer_notifications istemciniz ONE_TIME_PRODUCT_PURCHASED veya SUBSCRIPTION_PURCHASED bildirimi alır. Satın alma işlemi iptal edilirse ONE_TIME_PRODUCT_CANCELED veya SUBSCRIPTION_PENDING_PURCHASE_CANCELED bildirimi alırsınız. Müşteriniz ödemeyi gerekli zaman aralığında tamamlamazsa bu durum yaşanabilir. Satın alma işleminin mevcut durumunu kontrol etmek için her zaman Google Play Developer API'yi kullanabileceğinizi unutmayın.
Çoklu satın alma işlemlerini yönetme
Google Play Faturalandırma Kitaplığı'nın 4.0 ve sonraki sürümlerinde desteklenen bu özellik sayesinde Google Play, müşterilerin alışveriş sepetinden miktar belirterek tek bir işlemde aynı tek seferlik üründen birden fazla satın almasına olanak tanır. Uygulamanızın çoklu satın alma işlemlerini yönetmesi ve belirtilen satın alma miktarına göre hak vermesi beklenir.
Birden fazla ürünün satın alındığı işlemleri desteklemek için uygulamanızın sağlama mantığının öğe miktarını kontrol etmesi gerekir. Aşağıdaki API'lerden birini kullanarak quantity alanına erişebilirsiniz:
- 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 mantık ekledikten sonra Google Play Console'daki tek seferlik ü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 sağlar.
BillingClient oluşturduktan sonra kullanıcının faturalandırma yapılandırmasını sorgulayabilirsiniz. Aşağıdaki kod snippet'inde getBillingConfigAsync()'ya nasıl çağrı yapılacağı açıklanmaktadır. BillingConfigResponseListener yöntemini uygulayarak yanıtı işleyin. Bu dinleyici, uygulamanızdan başlatılan tüm faturalandırma yapılandırması sorgularıyla ilgili güncellemeleri alır.
Döndürülen BillingResult hata içermiyorsa kullanıcının Play ülkesini öğrenmek 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 { // Handle errors } } } )
Java
GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build(); billingClient.getBillingConfigAsync( getBillingConfigParams, (billingResult, billingConfig) -> { if (billingResult.getResponseCode() == BillingResponseCode.OK && billingConfig != null) { String countryCode = billingConfig.getCountryCode(); } else { // TODO: Handle errors } });