BillingResult yanıt kodlarını işleme

Play Faturalandırma Kitaplığı çağrısı bir işlemi tetiklediğinde kitaplık, BillingResult veya geliştiricilerinizi sonuç konusunda bilgilendirmek için bir e-posta gönderin. Ö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. BillingResponseCode referans sayfası, her yanıtın ayrıntılı açıklamasını sağlar. ele alacağız. 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'e çağrı geldiğinde Faturalandırma Kitaplığı yöntemi bir BillingResponseCode döndürüyor değeri gösteriyorsa aramayı yeniden denemelisiniz. İçinde durumlarda, koşullar geçici olarak kabul edilmez. Bu nedenle, ö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üğe kaydetme amaçlı işlemlerdir.

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, en fazla teklifi içeren basit bir yeniden deneme deneme sayısını belirtir.

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, isteğin Google Play yanıt verebilir. 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ı.

SERVICE_DISCONNECTED listesini beğenmeyin aşağıdaki adımları uygulayarak Google Play Faturalandırma hizmetiyle bağlantı koparılmamış: yalnızca denenen Play Faturalandırma Kitaplığı işlemini yeniden deneyebilirsiniz.

SERVICE_DISCONNECTED (Hata Kodu -1)

Sorun

Bu önemli hata, istemci uygulamasının Google Play ile bağlantısının olduğunu gösterir. Hizmeti BillingClient aracılığıyla depolayın uzaklaştırıldı.

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, bir ağ bağlantısı sorunu olduğu anlamına gelir istemci cihazı ve Google Play Faturalandırma hizmetleri arasındaki herhangi bir yerde

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 listesini beğenmeyin , Google Play Faturalandırma hizmetiyle bağlantı kopmaz ve tıklayın.

BILLING_UNAVAILABLE (Hata Kodu 3)

Sorun

Bu hata, takip eder. Bu durumun yaşanabileceği durumlara örnekler:

  • 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 geçerlilik süresi dolmuş olabilir.

Olası çözüm

Bu durumda otomatik yeniden denemelerin işe yarama olasılığı düşüktür. Ancak, manuel yeniden deneme, kullanıcı, soruna neden olan durumla ilgiliyse yardımcı 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. BILLING_UNAVAILABLE aldığınızda bir hata olduğunu fark ederseniz, kullanıcı büyük olasılıkla satın alma işlemi satın alma sürecinde Google Play'den geri bildirim alır ve bu geri bildirimler doğrultusunda emin olun. 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'de dahili bir sorun olduğunu gösteren önemli bir hatadır kendisi.

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ıkları ürün veya abonelik gibi Çoğu durumda bu geçici bir hata değildir. Google Play’in önbelleğini kullanır.

Olası çözüm

Neden bir önbellek sorunu olmadığında bu hatanın oluşmasını önlemek için önbellek sorunu kullanıcıya zaten sahip olduğu durumlarda satın alınacak üründür. Ş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ı bir önbellek sorunu nedeniyle bu hatayı aldığında hata tetiklenir Play'in arka ucundan alınan en son verilerle güncellenmesi için Google Play'in önbelleği. Hatadan sonra yeniden deneme, bu geçici örneği şu şekilde çözecektir: dava açın. BillingClient.queryPurchasesAsync() numaralı telefonu arayın ITEM_ALREADY_OWNED aldıktan sonra kullanıcının ürünü edinip edindiğini ve edinip edinmediğini kontrol etmek 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ına ait öğenin sahibi olmadığını belirtir kullanıcının değiştirmeye çalıştığı abonelik veya tek seferlik satın alım ürünü, kabullenmek ya da tüketmektir. 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 arka ucundan alınan en son verilerle güncellenmesi için Play'in önbelleği. Yeniden deneniyor hatadan sonra basit bir yeniden deneme stratejisiyle oluşturarak geçici bir örneğidir. 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ı kurtaramazsınız.

FEATURE_NOT_SUPPORTED

Sorun

Bu geri alınamaz hata, Google Play Faturalandırma özelliğinin Kullanıcının cihazında destekleniyor olması olabilir. Bunun nedeni, muhtemelen eski bir Play Store sürümü olmasıdır.

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

Olası çözüm

Play Faturalandırma'yı aramadan önce özellik desteğini kontrol etmek için BillingClient.isFeatureSupported() uygulamasını kullanın Kitaplık'a dokunun.

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ıklayarak çıktı.

Olası çözüm

Bu yalnızca bilgilendirme amaçlıdır ve önemli ölçüde başarısız olabilir.

ÖĞE_YOK

Sorun

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

Olası çözüm

Uygulamanızın, ürün ayrıntılarını queryProductDetailsAsync aracılığıyla önerildiği şekilde yenilediğinden emin olun. Hangi sıklıkta ürün kataloğundaki değişikliklerinizi Play Console yapılandırmasında gerekirse yenileme yapabilirsiniz. Yalnızca doğru ürünü Google Play Faturalandırma üzerinden satmaya çalışın queryProductDetailsAsync aracılığıyla bilgi edinebilirsiniz. Ürün uygunluğu yapılandırmasını kontrol ederek tutarsızlık olup olmadığını kontrol edin. Örneğin, yalnızca bir pazar için sunulan 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. Bunun nedeni, Ürün ayrıntılarının Google'ın sunucuları genelinde yayılma gecikmesi. Tekrar dene daha sonra.

GELİŞTİRİCİ_HATASI

Sorun

Bu, API'yi uygunsuz şekilde kullandığınızı gösteren ö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ığı'nı doğru şekilde kullandığınızdan emin olun çağrısının en iyi yolu. Ayrıca, hata hakkında daha fazla bilgi için hata ayıklama mesajını kontrol edin.