BillingResult yanıt kodlarını işleme

Play Faturalandırma Kitaplığı çağrısı bir işlemi tetiklediğinde kitaplık, geliştiricileri sonucu hakkında bilgilendirmek için bir BillingResult yanıtı döndürür. Örneğin, queryProductDetailsAsync kullanıcıya sunulan teklifleri almak için yanıt kodu Tamam kodu ve doğru ProductDetails değerini sağlar ya da hatanın nedenini belirten farklı bir yanıt içeriyorsa ProductDetails nesne sağlanamadı.

Tüm yanıt kodları hata değildir. Bu kılavuzda ele alınan yanıtların her biri BillingResponseCode referans sayfasında ayrıntılı olarak açıklanmaktadır. Hata belirtmeyen yanıt kodu örneklerinden bazıları şunlardır:

Yanıt kodu bir hata belirttiğinde, bunun nedeni bazen geçici koşullar olduğunu ve dolayısıyla iyileşmenin mümkün olduğunu unutmayın. Play Billing Library yöntemine yapılan bir çağrı, kurtarılabilir bir durumu belirten bir BillingResponseCode değeri döndürdüğünde çağrıyı yeniden denemeniz gerekir. Diğer durumlarda, koşullar geçici olarak kabul edilmez ve bu nedenle yeniden deneme önerilmez.

Geçici hatalar, deneme gibi unsurlara bağlı olarak farklı yeniden deneme stratejileri gerektirir. hatanın, kullanıcılar oturumdayken mi (örneğin, kullanıcı oturumundaki devam ederken (veya hata arka planda gerçekleşirse) Örneğin, onResume sırasında kullanıcının mevcut satın alma işlemlerini sorguladığınızda. Aşağıdaki yeniden deneme stratejileri bölümünde, Bu farklı stratejiler ve Retriable BillingResult Yanıtlar bölümü Her yanıt kodu için en uygun stratejinin hangisi olduğunu önerir.

Bazı hata yanıtları, yanıt koduna ek olarak hata ayıklama ve günlük kaydı amacıyla mesajlar içerir.

Yeniden deneme stratejileri

Basit yeniden deneme

Kullanıcının oturumda olduğu durumlarda, basit bir kesintiye uğratmasını sağlamak için yeniden deneme yapmasını sağlar. Bu durumda, çıkış koşulu olarak maksimum deneme sayısı içeren basit bir yeniden deneme stratejisi kullanmanızı öneririz.

Aşağıdaki örnekte, bir hatayı işlemek için basit bir yeniden deneme stratejisi gösterilmektedir BillingClient oluştururken bağlantı:

class BillingClientWrapper(context: Context) : PurchasesUpdatedListener {
  // Initialize the BillingClient.
  private val billingClient = BillingClient.newBuilder(context)
    .setListener(this)
    .enablePendingPurchases()
    .build()

  // Establish a connection to Google Play.
  fun startBillingConnection() {
    billingClient.startConnection(object : BillingClientStateListener {
      override fun onBillingSetupFinished(billingResult: BillingResult) {
        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
          Log.d(TAG, "Billing response OK")
          // The BillingClient is ready. You can now query Products Purchases.
        } else {
          Log.e(TAG, billingResult.debugMessage)
          retryBillingServiceConnection()
        }
      }

      override fun onBillingServiceDisconnected() {
        Log.e(TAG, "GBPL Service disconnected")
        retryBillingServiceConnection()
      }
    })
  }

  // Billing connection retry logic. This is a simple max retry pattern
  private fun retryBillingServiceConnection() {
    val maxTries = 3
    var tries = 1
    var isConnectionEstablished = false
    do {
      try {
        billingClient.startConnection(object : BillingClientStateListener {
          override fun onBillingSetupFinished(billingResult: BillingResult) {
            if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
              isConnectionEstablished = true
              Log.d(TAG, "Billing connection retry succeeded.")
            } else {
              Log.e(
                TAG,
                "Billing connection retry failed: ${billingResult.debugMessage}"
              )
            }
          }
        })
      } catch (e: Exception) {
        e.message?.let { Log.e(TAG, it) }
        tries++
      }
    } while (tries <= maxTries && !isConnectionEstablished)
  }
  ...
}

Üstel geri yüklemeyi yeniden deneme

Şu özelliklere sahip Play Faturalandırma Kitaplığı işlemleri için eksponansiyel geri yükleme kullanmanızı öneririz: arka planda gerçekleştiğinden ve kullanıcı işlem yaparken kullanıcı deneyimini devam ediyor.

Örneğin, yeni müşterileri kabul ederken bunu uygulamak uygun olur. gerçekleşebilir. Bu işlem arka planda gerçekleşebileceği için, bir hata oluşursa onayın gerçek zamanlı olarak gerçekleşmesi gerekmez.

private fun acknowledge(purchaseToken: String): BillingResult {
  val params = AcknowledgePurchaseParams.newBuilder()
    .setPurchaseToken(purchaseToken)
    .build()
  var ackResult = BillingResult()
  billingClient.acknowledgePurchase(params) { billingResult ->
    ackResult = billingResult
  }
  return ackResult
}

suspend fun acknowledgePurchase(purchaseToken: String) {

  val retryDelayMs = 2000L
  val retryFactor = 2
  val maxTries = 3

  withContext(Dispatchers.IO) {
    acknowledge(purchaseToken)
  }

  AcknowledgePurchaseResponseListener { acknowledgePurchaseResult ->
    val playBillingResponseCode =
    PlayBillingResponseCode(acknowledgePurchaseResult.responseCode)
    when (playBillingResponseCode) {
      BillingClient.BillingResponseCode.OK -> {
        Log.i(TAG, "Acknowledgement was successful")
      }
      BillingClient.BillingResponseCode.ITEM_NOT_OWNED -> {
        // This is possibly related to a stale Play cache.
        // Querying purchases again.
        Log.d(TAG, "Acknowledgement failed with ITEM_NOT_OWNED")
        billingClient.queryPurchasesAsync(
          QueryPurchasesParams.newBuilder()
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
        )
        { billingResult, purchaseList ->
          when (billingResult.responseCode) {
            BillingClient.BillingResponseCode.OK -> {
              purchaseList.forEach { purchase ->
                acknowledge(purchase.purchaseToken)
              }
            }
          }
        }
      }
      in setOf(
         BillingClient.BillingResponseCode.ERROR,
         BillingClient.BillingResponseCode.SERVICE_DISCONNECTED,
         BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE,
       ) -> {
        Log.d(
          TAG,
          "Acknowledgement failed, but can be retried --
          Response Code: ${acknowledgePurchaseResult.responseCode} --
          Debug Message: ${acknowledgePurchaseResult.debugMessage}"
        )
        runBlocking {
          exponentialRetry(
            maxTries = maxTries,
            initialDelay = retryDelayMs,
            retryFactor = retryFactor
          ) { acknowledge(purchaseToken) }
        }
      }
      in setOf(
         BillingClient.BillingResponseCode.BILLING_UNAVAILABLE,
         BillingClient.BillingResponseCode.DEVELOPER_ERROR,
         BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED,
       ) -> {
        Log.e(
          TAG,
          "Acknowledgement failed and cannot be retried --
          Response Code: ${acknowledgePurchaseResult.responseCode} --
          Debug Message: ${acknowledgePurchaseResult.debugMessage}"
        )
        throw Exception("Failed to acknowledge the purchase!")
      }
    }
  }
}

private suspend fun <T> exponentialRetry(
  maxTries: Int = Int.MAX_VALUE,
  initialDelay: Long = Long.MAX_VALUE,
  retryFactor: Int = Int.MAX_VALUE,
  block: suspend () -> T
): T? {
  var currentDelay = initialDelay
  var retryAttempt = 1
  do {
    runCatching {
      delay(currentDelay)
      block()
    }
      .onSuccess {
        Log.d(TAG, "Retry succeeded")
        return@onSuccess;
      }
      .onFailure { throwable ->
        Log.e(
          TAG,
          "Retry Failed -- Cause: ${throwable.cause} -- Message: ${throwable.message}"
        )
      }
    currentDelay *= retryFactor
    retryAttempt++
  } while (retryAttempt < maxTries)

  return block() // last attempt
}

Yeniden Kullanılabilir BillingResult yanıtları

NETWORK_ERROR (Hata Kodu 12)

Sorun

Bu hata, ağ bağlantısında bir sorun olduğunu gösterir Google Play sistemleri arasında.

Olası çözüm

Kurtarmak için, hangisinin bağlı olduğuna bağlı olarak basit yeniden deneme veya eksponansiyel geri yükleme yöntemini kullanın. işlemi hatayı tetiklemiştir.

SERVICE_TIMEOUT (Hata Kodu -3)

Sorun

Bu hata, Google Play yanıt vermeden önce isteğin maksimum zaman aşımına ulaştığını gösterir. Bu durum, örneğin bir gecikme nedeniyle .

Olası çözüm

Bu genellikle geçici bir sorundur. Aşağıdakilerden birini kullanarak isteği yeniden deneyin: hangi işlemin sonucu döndürdüğüne bağlı olarak, basit veya eksponansiyel geri yükleme stratejisidir. hatası.

Aşağıdaki SERVICE_DISCONNECTED durumundan farklı olarak, Google Play Faturalandırma hizmetine olan bağlantı kesilmez. Tek yapmanız gereken, denenen Play Faturalandırma Kitaplığı işlemini tekrar denemektir.

SERVICE_DISCONNECTED (Hata Kodu: -1)

Sorun

Bu önemli hata, istemci uygulamasının BillingClient üzerinden Google Play Store hizmetine olan bağlantısının kesildiğini gösterir.

Olası çözüm

Bu hatadan mümkün olduğunca kaçınmak için her zaman Google ile bağlantınızı kontrol edin Şu telefon numarasını arayarak Play Faturalandırma Kitaplığı ile arama yapmadan önce Play Hizmetleri: BillingClient.isReady().

SERVICE_DISCONNECTED hesabından kurtarmayı denemek için istemci uygulamanız BillingClient.startConnection.

Aynı SERVICE_TIMEOUT'de olduğu gibi kullanıyorsanız, hangi işlemin tetiklendiğine bağlı olarak basit yeniden deneme veya üstel geri yükleme yöntemini kullanın. gösterir.

SERVICE_UNAVAILABLE (Hata Kodu 2)

Önemli Not:

Google Play Faturalandırma Kitaplığı 6.0.0 sürümünden itibaren SERVICE_UNAVAILABLE, daha uzun süre döndürüldü. Faturalandırma hizmeti şu olduğunda döndürülür: ve desteği sonlandırılan SERVICE_TIMEOUT senaryo senaryoları.

Sorun

Bu geçici hata, Google Play Faturalandırma hizmetinin şu anda kullanıldığını gösterir kullanılamıyor. Çoğu durumda bu, istemci cihaz ile Google Play Faturalandırma Hizmetleri arasında bir ağ bağlantısı sorunu olduğu anlamına gelir.

Olası çözüm

Bu genellikle geçici bir sorundur. Aşağıdakilerden birini kullanarak isteği yeniden deneyin: hangi işlemin sonucu döndürdüğüne bağlı olarak, basit veya eksponansiyel geri yükleme stratejisidir. hatası.

SERVICE_DISCONNECTED durumundan farklı olarak, Google Play Faturalandırma hizmetine olan bağlantı kesilmez ve denenen işlemi tekrarlamanız gerekir.

BILLING_UNAVAILABLE (Hata Kodu 3)

Sorun

Bu hata, satın alma işlemi sırasında kullanıcı faturalandırması hatası oluştuğunu gösterir. Bu durumun yaşanabileceği durumlara örnek olarak aşağıdakiler verilebilir:

  • Kullanıcının cihazındaki Play Store uygulaması güncel değil.
  • Kullanıcı desteklenmeyen bir ülkede.
  • Kullanıcı, kurumsal bir kullanıcı ve kurumsal yöneticisi bazı kullanıcıları devre dışı bıraktı engeller.
  • Google Play, kullanıcının ödeme yönteminden ödeme alamıyor. Örneğin, kullanıcının kredi kartının süresi dolmuş olabilir.

Olası çözüm

Bu durumda otomatik yeniden denemelerin işe yarama olasılığı düşüktür. Ancak kullanıcı, soruna neden olan durumu giderirse manuel olarak tekrar denemek faydalı olabilir. Örneğin, Kullanıcı Play Store sürümünü desteklenen bir sürüme günceller ve ardından manuel olarak tekrar deneyebilirsiniz.

Bu hata, kullanıcı oturumda değilken oluşursa yeniden denemek başarısız olabilir olması gerekir. Satın alma akışı sonucunda BILLING_UNAVAILABLE hatası aldığınızda, kullanıcının satın alma işlemi sırasında Google Play'den geri bildirim almış olması ve hatanın neyle ilgili olduğunu bilmesi muhtemeldir. Bu durumda, kullanıcı arabirimi için bir hata mesajı ve kullanıcıya deneme veya kontrol ekleme seçeneği sunan bir "Tekrar dene" düğmesi manuel olarak yeniden deneyin.

ERROR (Hata Kodu 6)

Sorun

Bu, Google Play'in kendisiyle ilgili dahili bir sorunu gösteren önemli bir hatadır.

Olası çözüm

Bazen ERROR'e neden olan dahili Google Play sorunları geri yükleme işlemi geçicidir ve eksponansiyel geri yükleme ile yeniden deneme olabilir. Kullanıcılar oturumdayken basit bir yeniden deneme tercih edilir.

ITEM_ALREADY_OWNED

Sorun

Bu yanıt, Google Play kullanıcısının satın almaya çalıştığı aboneliğe veya tek seferlik satın alma işlemine tabi ürüne zaten sahip olduğunu gösterir. Çoğu durumda bu geçici bir hata değildir. Google Play’in önbelleğini kullanır.

Olası çözüm

Nedeni önbellek sorunu olmadığında bu hatanın oluşmasını önlemek için, kullanıcının zaten sahip olduğu bir ürünü satın almak üzere sunmayın. Şunu kontrol ettiğinizden emin olun: satın alınabilecek ürünleri gösterdiğinizde kullanıcının yararlanma hakları ve uygun şekilde filtreleyerek kullanıcının satın alabileceği ürünlere göre filtre uygulayabilirsiniz. İstemci uygulaması, önbellek sorunu nedeniyle bu hatayı aldığında hata, Google Play'in arka ucundaki en son verilerle güncellenmesi için Google Play'in önbelleğini tetikler. Hatadan sonra yeniden deneme, bu geçici örneği şu şekilde çözecektir: dava açın. Kullanıcının ürünü alıp almadığını kontrol etmek için ITEM_ALREADY_OWNED aldıktan sonra BillingClient.queryPurchasesAsync()'i arayın. Kullanıcı ürünü satın almadıysa satın alma işlemini yeniden denemek için basit bir yeniden deneme mantığı uygulayın.

ITEM_NOT_OWNED

Sorun

Bu satın alma yanıtı, Google Play kullanıcısının değiştirmeye, onaylamaya veya kullanmaya çalıştığı aboneliğin ya da tek seferlik satın alma ürününün sahibi olmadığını gösterir. Bu, Google'dan kaynaklanmadığı durumlar dışında çoğu durumda geçici bir hata değildir Play’in önbelleği eski durumuna geçiyor.

Olası çözüm

Hata, önbellek sorunu nedeniyle alındığında Google Play'in önbelleği, Play'in arka ucundaki en son verilerle güncellenir. Hata oluştuktan sonra basit bir yeniden deneme stratejisiyle yeniden denemek, bu geçici durumu çözecektir. ITEM_NOT_OWNED aldıktan sonra BillingClient.queryPurchasesAsync() adlı kişiyi arayarak kullanıcının şu olup olmadığını kontrol edin: kararlaştırdık. Aksi halde, basit yeniden deneme mantığını kullanarak değeri için teklif verirsiniz.

Yeniden Kullanılabilir Olmayan Faturalandırma Sonucu yanıtları

Yeniden deneme mantığını kullanarak bu hataları düzeltemezsiniz.

FEATURE_NOT_SUPPORTED

Sorun

Yeniden alınamayan bu hata, Google Play Faturalandırma özelliğinin kullanıcının cihazında desteklenmediğini gösterir. Bunun nedeni muhtemelen eski bir Play Store sürümü olabilir.

Örneğin bazı kullanıcılarınızın cihaz uygulama içi mesajlaşmayı desteklemiyor.

Olası çözüm

Play Faturalandırma Kitaplığı'na telefon etmeden önce özellik desteğini kontrol etmek için BillingClient.isFeatureSupported() simgesini kullanın.

when {
  billingClient.isReady -> {
    if (billingClient.isFeatureSupported(BillingClient.FeatureType.IN_APP_MESSAGING)) {
       // use feature
    }
  }
}

USER_CANCELED

Sorun

Kullanıcı, faturalandırma akışı kullanıcı arayüzünü tıkladı.

Olası çözüm

Bu yalnızca bilgilendirme amaçlıdır ve sorunsuz bir şekilde başarısız olabilir.

ITEM_UNAVAILABLE

Sorun

Google Play Faturalandırma aboneliği veya tek seferlik satın alma ürünü bu kullanıcı tarafından satın alınamaz.

Olası çözüm

Uygulamanızın, ürün ayrıntılarını önerilen şekilde queryProductDetailsAsync üzerinden yenilediğinden emin olun. Gerekirse ek yenilemeler uygulamak için ürün kataloğunuzun Play Console yapılandırmasında ne sıklıkta değiştiğini göz önünde bulundurun. Google Play Faturalandırma'da yalnızca queryProductDetailsAsync üzerinden doğru bilgileri döndüren ürünleri satmaya çalışın. Tutarsızlık olup olmadığını kontrol etmek için ürün uygunluk yapılandırmasını kontrol edin. Örneğin, yalnızca belirli bir tarihte satılan bir ürünü sorguluyor olabilirsiniz. satın almaya çalıştığı bölgeden farklı bir bölge olabilir. Bir ürünün satın alınabilmesi için etkin olması, uygulamasının yayınlanmış ve uygulamasının kullanıcının ülkesinde kullanılabilir olması gerekir.

Bazen, özellikle de test sırasında üründeki her şey doğru yapılandırmaya devam ediyor, ancak kullanıcılar bu hatayı görmeye devam ediyor. Bu durum, ürün ayrıntılarının Google sunucularına dağıtılmasındaki gecikmeyle ilgili olabilir. Tekrar dene daha sonra.

GELİŞTİRİCİ_HATASI

Sorun

Bu, bir API'yi yanlış kullandığınızı belirten önemli bir hatadır. Örneğin, BillingClient.launchBillingFlow öğesine yanlış parametreler sağlanması, bu hataya neden olur.

Olası çözüm

Farklı Play Faturalandırma Kitaplığı çağrılarını doğru şekilde kullandığınızdan emin olun. Hatayla ilgili daha fazla bilgi için hata ayıklama mesajını da kontrol edin.