बिलिंग नतीजे के रिस्पॉन्स कोड मैनेज करना

Play Billing Library को कॉल करने पर, अगर कोई कार्रवाई ट्रिगर होती है, तो लाइब्रेरी BillingResult के तौर पर जवाब देती है. इससे डेवलपर को कार्रवाई के नतीजे के बारे में पता चलता है. उदाहरण के लिए, अगर उपयोगकर्ता के लिए उपलब्ध ऑफ़र पाने के लिए, queryProductDetailsAsync का इस्तेमाल किया जाता है, तो जवाब के कोड में या तो OK कोड होता है और सही ProductDetails ऑब्जेक्ट मिलता है या फिर कोई दूसरा जवाब मिलता है. इससे यह पता चलता है कि ProductDetails ऑब्जेक्ट क्यों नहीं दिया जा सका.

सभी जवाब कोड, गड़बड़ियां नहीं होते. BillingResponseCode रेफ़रंस पेज पर, इस गाइड में बताए गए हर जवाब के बारे में ज़्यादा जानकारी दी गई है. जवाब कोड के कुछ उदाहरण यहां दिए गए हैं, जिनसे गड़बड़ियों का पता नहीं चलता:

  • BillingClient.BillingResponseCode.OK : कॉल से ट्रिगर की गई कार्रवाई, सही तरीके से पूरी हो गई.
  • BillingClient.BillingResponseCode.USER_CANCELED : Play Store के यूज़र इंटरफ़ेस (यूआई) फ़्लो को उपयोगकर्ता को दिखाने वाली कार्रवाइयों के लिए, इस जवाब से पता चलता है कि उपयोगकर्ता ने प्रोसेस पूरी किए बिना ही, उन यूआई फ़्लो से बाहर निकल गया.

जब जवाब कोड से किसी गड़बड़ी का पता चलता है, तो इसकी वजह कभी-कभी अस्थायी स्थितियां होती हैं. इसलिए, इसे ठीक किया जा सकता है. जब Play Billing Library के किसी तरीके को कॉल करने पर, BillingResponseCode की ऐसी वैल्यू मिलती है जिससे ठीक की जा सकने वाली स्थिति का पता चलता है, तो आपको कॉल को फिर से करना चाहिए. अन्य मामलों में, स्थितियों को अस्थायी नहीं माना जाता. इसलिए, कॉल को फिर से करने का सुझाव नहीं दिया जाता.

अस्थायी गड़बड़ियों को ठीक करने के लिए, अलग-अलग रणनीतियां अपनाई जाती हैं. यह इस बात पर निर्भर करता है कि गड़बड़ी कब हुई. जैसे, अगर गड़बड़ी तब हुई, जब उपयोगकर्ता सेशन में था. उदाहरण के लिए, जब कोई उपयोगकर्ता खरीदारी की प्रोसेस में था. इसके अलावा, अगर गड़बड़ी बैकग्राउंड में हुई. उदाहरण के लिए, जब onResume के दौरान, उपयोगकर्ता की मौजूदा खरीदारी के बारे में क्वेरी की जा रही हो. नीचे दिए गए, फिर से कोशिश करने की रणनीतियां सेक्शन में, इन अलग-अलग रणनीतियों के उदाहरण दिए गए हैं. वहीं, Retriable BillingResult Responses section में, हर जवाब कोड के लिए सबसे सही रणनीति के बारे में बताया गया है.

जवाब कोड के अलावा, गड़बड़ी के कुछ जवाबों में डीबग करने और लॉग करने के मकसद से मैसेज शामिल होते हैं.

फिर से कोशिश करने की रणनीतियां

सिर्फ़ फिर से कोशिश करना

अगर उपयोगकर्ता सेशन में है, तो सिर्फ़ फिर से कोशिश करने की रणनीति लागू करना बेहतर है, ताकि गड़बड़ी से उपयोगकर्ता अनुभव पर कम से कम असर पड़े. ऐसे में, हमारा सुझाव है कि सिर्फ़ फिर से कोशिश करने की रणनीति लागू करें. इसमें, कोशिशों की ज़्यादा से ज़्यादा संख्या को एग्ज़िट की शर्त के तौर पर सेट करें.

यहां दिए गए उदाहरण में, गड़बड़ी को ठीक करने के लिए, सिर्फ़ फिर से कोशिश करने की रणनीति के बारे में बताया गया है BillingClient कनेक्शन बनाते समय:

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) }
      } finally {
        tries++
      }
    } while (tries <= maxTries && !isConnectionEstablished)
  }
  ...
}

एक्स्पोनेंशियल बैकऑफ़ के साथ फिर से कोशिश करना

हमारा सुझाव है कि Play Billing Library की उन कार्रवाइयों के लिए एक्स्पोनेंशियल बैकऑफ़ का इस्तेमाल करें जो बैकग्राउंड में होती हैं और जब उपयोगकर्ता सेशन में होता है, तब उसके अनुभव पर असर नहीं डालती हैं.

उदाहरण के लिए, नई खरीदारी की पुष्टि करने के लिए, इस रणनीति को लागू करना सही होगा. ऐसा इसलिए, क्योंकि यह कार्रवाई बैकग्राउंड में हो सकती है. साथ ही, गड़बड़ी होने पर, पुष्टि रीयल टाइम में नहीं की जानी चाहिए.

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
}

BillingResult के ऐसे जवाब जिन्हें ठीक किया जा सकता है

NETWORK_ERROR (गड़बड़ी कोड 12)

समस्या

इस गड़बड़ी से पता चलता है कि डिवाइस और Play सिस्टम के बीच इंटरनेट कनेक्शन में कोई समस्या हुई.

समस्या हल करने का तरीका

गड़बड़ी को ठीक करने के लिए, सिर्फ़ फिर से कोशिश करने की रणनीति या एक्स्पोनेंशियल बैकऑफ़ का इस्तेमाल करें. यह इस बात पर निर्भर करता है कि गड़बड़ी किस कार्रवाई की वजह से हुई.

SERVICE_TIMEOUT (गड़बड़ी कोड -3)

समस्या

इस गड़बड़ी से पता चलता है कि Google Play के जवाब देने से पहले ही, अनुरोध का टाइम आउट हो गया है. उदाहरण के लिए, ऐसा Play Billing Library को कॉल करने पर, अनुरोध की गई कार्रवाई को पूरा करने में देरी होने की वजह से हो सकता है.

समस्या हल करने का तरीका

आम तौर पर, यह अस्थायी समस्या होती है. अनुरोध को फिर से करने के लिए, सिर्फ़ फिर से कोशिश करने की रणनीति या एक्स्पोनेंशियल बैकऑफ़ का इस्तेमाल करें. यह इस बात पर निर्भर करता है कि गड़बड़ी किस कार्रवाई की वजह से हुई.

नीचे दिए गए SERVICE_DISCONNECTED के उलट, Google Play Billing सेवा से कनेक्शन नहीं टूटा है. आपको सिर्फ़ Play Billing Library की उस कार्रवाई को फिर से करना होगा जो पूरी नहीं हो पाई थी.

SERVICE_DISCONNECTED (गड़बड़ी कोड -1)

समस्या

इस गंभीर गड़बड़ी से पता चलता है कि क्लाइंट ऐप्लिकेशन का Google Play Store सेवा से कनेक्शन टूट गया है. यह कनेक्शन, BillingClient के ज़रिए बना था.

समस्या हल करने का तरीका

Play Billing Library के वर्शन 8.0.0 में, enableAutoServiceReconnection() सुविधा जोड़ी गई है. हमारा सुझाव है कि BillingClient बनाते समय, इस सुविधा को चालू करें. इससे, सेवा के डिसकनेक्ट होने पर, बिलिंग एपीआई को कॉल करने पर, लाइब्रेरी अपने-आप कनेक्शन को फिर से जोड़ने की कोशिश करती है. इससे, इस गड़बड़ी के होने की संभावना काफ़ी कम हो जाती है.

Kotlin

val billingClient = BillingClient.newBuilder(context)
    .setListener(listener)
    .enablePendingPurchases()
    .enableAutoServiceReconnection() // Enable automatic service reconnection
    .build()

Java

BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(listener)
    .enablePendingPurchases()
    .enableAutoServiceReconnection() // Enable automatic service reconnection
    .build();
अगर आपने सेवा के अपने-आप फिर से कनेक्ट होने की सुविधा चालू की है

Play Billing Library, अपने-आप फिर से कनेक्ट होने की कोशिश करेगी. अगर एपीआई को कॉल करने पर, आपको अब भी SERVICE_DISCONNECTED जवाब कोड मिलता है, तो इसका मतलब है कि लाइब्रेरी, अपने-आप फिर से कनेक्ट होने की कोशिश करने के बाद भी कनेक्ट नहीं हो पाई. इस स्थिति में, आपको अपने ऐप्लिकेशन में फिर से कोशिश करने का लॉजिक लागू करना चाहिए:

  • उपयोगकर्ता की ओर से शुरू की गई कार्रवाइयों (सेशन के दौरान): एपीआई कॉल को सिर्फ़ फिर से करें. हो सकता है कि समस्या अस्थायी हो.
  • बैकग्राउंड में किए गए अनुरोधों के लिए: अगर डिसकनेक्शन लंबे समय तक बना रहता है, तो सिस्टम पर ज़्यादा लोड पड़ने से बचने के लिए, एक्स्पोनेंशियल बैकऑफ़ के साथ फिर से कोशिश करने की रणनीति लागू करें.
अगर आपने सेवा के अपने-आप फिर से कनेक्ट होने की सुविधा चालू नहीं की है

इस गड़बड़ी से बचने के लिए, Play Billing Library से कॉल करने से पहले, हमेशा Google Play सेवाओं से कनेक्शन की जांच करें. इसके लिए, BillingClient.isReady() को कॉल करें.

SERVICE_DISCONNECTED से ठीक होने के लिए, आपके क्लाइंट ऐप्लिकेशन को BillingClient.startConnection का इस्तेमाल करके, कनेक्शन को फिर से जोड़ने की कोशिश करनी चाहिए.

SERVICE_TIMEOUT की तरह ही, सिर्फ़ फिर से कोशिश करने की रणनीति या एक्स्पोनेंशियल बैकऑफ़ का इस्तेमाल करें. यह इस बात पर निर्भर करता है कि गड़बड़ी किस कार्रवाई की वजह से हुई .

SERVICE_UNAVAILABLE (गड़बड़ी कोड 2)

अहम जानकारी:

Google Play Billing Library के वर्शन 6.0.0 से, नेटवर्क से जुड़ी समस्याओं के लिए SERVICE_UNAVAILABLE जवाब नहीं मिलता. यह जवाब तब मिलता है, जब बिलिंग सेवा उपलब्ध नहीं होती और SERVICE_TIMEOUT के बंद किए गए केस के सिनेरियो में.

समस्या

इस अस्थायी गड़बड़ी से पता चलता है कि फ़िलहाल, Google Play Billing सेवा उपलब्ध नहीं है. ज़्यादातर मामलों में, इसका मतलब है कि क्लाइंट डिवाइस और Google Play Billing सेवाओं के बीच, नेटवर्क कनेक्शन में कोई समस्या है.

समस्या हल करने का तरीका

आम तौर पर, यह अस्थायी समस्या होती है. अनुरोध को फिर से करने के लिए, सिर्फ़ फिर से कोशिश करने की रणनीति या एक्स्पोनेंशियल बैकऑफ़ का इस्तेमाल करें. यह इस बात पर निर्भर करता है कि गड़बड़ी किस कार्रवाई की वजह से हुई.

SERVICE_DISCONNECTED के उलट, Google Play Billing सेवा से कनेक्शन नहीं टूटा है. आपको सिर्फ़ उस कार्रवाई को फिर से करना होगा जो पूरी नहीं हो पाई थी.

BILLING_UNAVAILABLE (गड़बड़ी कोड 3)

समस्या

इस गड़बड़ी से पता चलता है कि खरीदारी की प्रोसेस के दौरान, उपयोगकर्ता की बिलिंग में कोई गड़बड़ी हुई. यहां कुछ उदाहरण दिए गए हैं, जिनमें यह गड़बड़ी हो सकती है:

  • उपयोगकर्ता के डिवाइस पर Play Store ऐप्लिकेशन का वर्शन पुराना है.
  • उपयोगकर्ता, ऐसे देश में है जहां Play Store की सुविधा उपलब्ध नहीं है.
  • उपयोगकर्ता, एंटरप्राइज़ उपयोगकर्ता है और उसके एंटरप्राइज़ एडमिन ने उपयोगकर्ताओं को खरीदारी करने से रोक दिया है.
  • Google Play, उपयोगकर्ता के पेमेंट के तरीके से शुल्क नहीं ले पा रहा है. उदाहरण के लिए, हो सकता है कि उपयोगकर्ता के क्रेडिट कार्ड की समयसीमा खत्म हो गई हो.

समस्या हल करने का तरीका

इस मामले में, अपने-आप फिर से कोशिश करने की सुविधा से मदद मिलने की संभावना कम होती है. हालांकि, अगर उपयोगकर्ता उस स्थिति को ठीक कर लेता है जिसकी वजह से समस्या हुई, तो मैन्युअल तरीके से फिर से कोशिश करने पर मदद मिल सकती है. उदाहरण के लिए, अगर उपयोगकर्ता अपने Play Store के वर्शन को ऐसे वर्शन में अपडेट करता है जो काम करता है, तो शुरुआती कार्रवाई को मैन्युअल तरीके से फिर से करने पर काम बन सकता है.

अगर यह गड़बड़ी तब होती है, जब उपयोगकर्ता सेशन में नहीं है, तो फिर से कोशिश करने का कोई मतलब नहीं है. खरीदारी की प्रोसेस के दौरान, BILLING_UNAVAILABLE गड़बड़ी मिलने पर, इस बात की पूरी संभावना है कि उपयोगकर्ता को Google Play से फ़ीडबैक मिला होगा. साथ ही, उसे यह भी पता होगा कि क्या गड़बड़ी हुई. इस मामले में, गड़बड़ी का मैसेज दिखाया जा सकता है. इसमें बताया जा सकता है कि कोई समस्या हुई है. साथ ही, “फिर से कोशिश करें” बटन दिया जा सकता है, ताकि उपयोगकर्ता समस्या को ठीक करने के बाद, मैन्युअल तरीके से फिर से कोशिश कर सके.

गड़बड़ी (गड़बड़ी कोड 6)

समस्या

यह एक गंभीर गड़बड़ी है. इससे पता चलता है कि Google Play में कोई अंदरूनी समस्या है.

समस्या हल करने का तरीका

कभी-कभी Google Play की अंदरूनी समस्याएं अस्थायी होती हैं. इनकी वजह से ERROR गड़बड़ी होती है. इसे ठीक करने के लिए, एक्स्पोनेंशियल बैकऑफ़ के साथ फिर से कोशिश करने की रणनीति लागू की जा सकती है. जब उपयोगकर्ता सेशन में होते हैं, तो सिर्फ़ फिर से कोशिश करने की रणनीति बेहतर होती है.

ITEM_ALREADY_OWNED

समस्या

इस जवाब से पता चलता है कि Google Play का उपयोगकर्ता, उस सदस्यता या एक बार की खरीदारी वाले प्रॉडक्ट का पहले से मालिक है जिसे वह खरीदने की कोशिश कर रहा है. ज़्यादातर मामलों में, यह अस्थायी गड़बड़ी नहीं होती. हालांकि, ऐसा तब हो सकता है, जब Google Play के पुराने कैश की वजह से यह गड़बड़ी हुई हो.

समस्या हल करने का तरीका

अगर गड़बड़ी की वजह कैश से जुड़ी समस्या नहीं है, तो इस गड़बड़ी से बचने के लिए, ऐसा प्रॉडक्ट न दिखाएं जिसे उपयोगकर्ता पहले से खरीद चुका है. पक्का करें कि खरीदारी के लिए उपलब्ध प्रॉडक्ट दिखाते समय, उपयोगकर्ता के अधिकारों की जांच की जाए. साथ ही, फ़िल्टर करें कि उपयोगकर्ता क्या खरीद सकता है. जब क्लाइंट ऐप्लिकेशन को कैश से जुड़ी समस्या की वजह से यह गड़बड़ी मिलती है, तो गड़बड़ी की वजह से Google Play का कैश, Play के बैकएंड से मिले नए डेटा के साथ अपडेट हो जाता है. इस मामले में, गड़बड़ी के बाद फिर से कोशिश करने पर, इस अस्थायी गड़बड़ी को ठीक किया जा सकता है. BillingClient.queryPurchasesAsync() मिलने के बाद, यह देखने के लिए ITEM_ALREADY_OWNED को कॉल करें कि उपयोगकर्ता ने प्रॉडक्ट खरीदा है या नहीं. अगर ऐसा नहीं है, तो खरीदारी को फिर से करने के लिए, सिर्फ़ फिर से कोशिश करने का लॉजिक लागू करें.

ITEM_NOT_OWNED

समस्या

खरीदारी के इस जवाब से पता चलता है कि Google Play का उपयोगकर्ता, उस सदस्यता या एक बार की खरीदारी वाले प्रॉडक्ट का मालिक नहीं है जिसे वह बदलना, स्वीकार करना या इस्तेमाल करना चाहता है. ज़्यादातर मामलों में, यह अस्थायी गड़बड़ी नहीं होती. हालांकि, ऐसा तब हो सकता है, जब Google Play के पुराने कैश की वजह से यह गड़बड़ी हुई हो.

समस्या हल करने का तरीका

जब कैश से जुड़ी समस्या की वजह से गड़बड़ी मिलती है, तो गड़बड़ी की वजह से Google Play का कैश, Play के बैकएंड से मिले नए डेटा के साथ अपडेट हो जाता है. गड़बड़ी के बाद, सिर्फ़ फिर से कोशिश करने की रणनीति का इस्तेमाल करके, इस अस्थायी गड़बड़ी को ठीक किया जा सकता है. ITEM_NOT_OWNED मिलने के बाद, यह देखने के लिए BillingClient.queryPurchasesAsync() को कॉल करें कि उपयोगकर्ता ने प्रॉडक्ट खरीदा है या नहीं. अगर उपयोगकर्ता ने प्रॉडक्ट नहीं खरीदा है, तो खरीदारी को फिर से करने के लिए, सिर्फ़ फिर से कोशिश करने का लॉजिक लागू करें.

BillingResult के ऐसे जवाब जिन्हें ठीक नहीं किया जा सकता

फिर से कोशिश करने के लॉजिक का इस्तेमाल करके, इन गड़बड़ियों को ठीक नहीं किया जा सकता.

FEATURE_NOT_SUPPORTED

समस्या

इस गड़बड़ी को ठीक नहीं किया जा सकता. इससे पता चलता है कि उपयोगकर्ता के डिवाइस पर, Google Play Billing की सुविधा काम नहीं करती. इसकी वजह, Play Store का पुराना वर्शन हो सकता है.

उदाहरण के लिए, हो सकता है कि आपके कुछ उपयोगकर्ताओं के डिवाइसों पर, इन-ऐप्लिकेशन मैसेजिंग की सुविधा काम न करे.

समस्या को कम करने का तरीका

Play Billing Library को कॉल करने से पहले, यह देखने के लिए BillingClient.isFeatureSupported() का इस्तेमाल करें कि सुविधा काम करती है या नहीं.

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

USER_CANCELED

समस्या

उपयोगकर्ता ने बिलिंग फ़्लो के यूज़र इंटरफ़ेस (यूआई) पर क्लिक किया है.

समस्या हल करने का तरीका

यह सिर्फ़ जानकारी के लिए है और इसे आसानी से ठीक किया जा सकता है.

ITEM_UNAVAILABLE

समस्या

Google Play Billing की सदस्यता या एक बार की खरीदारी वाला प्रॉडक्ट, इस उपयोगकर्ता के लिए उपलब्ध नहीं है.

समस्या को कम करने का तरीका

पक्का करें कि आपका ऐप्लिकेशन, queryProductDetailsAsync के ज़रिए प्रॉडक्ट की जानकारी को रीफ़्रेश करे. हमारा सुझाव है कि ऐसा किया जाए. अगर ज़रूरत हो, तो प्रॉडक्ट कैटलॉग को ज़्यादा बार रीफ़्रेश करने के लिए, Play Console कॉन्फ़िगरेशन में देखें कि आपका प्रॉडक्ट कैटलॉग कितनी बार बदलता है. Google Play Billing पर सिर्फ़ उन प्रॉडक्ट को बेचने की कोशिश करें जिनकी सही जानकारी, queryProductDetailsAsync के ज़रिए मिलती है. प्रॉडक्ट की ज़रूरी शर्तों के कॉन्फ़िगरेशन में, किसी भी तरह की गड़बड़ी की जांच करें. उदाहरण के लिए, हो सकता है कि आप ऐसे प्रॉडक्ट के बारे में क्वेरी कर रहे हों जो सिर्फ़ किसी ऐसे इलाके के लिए उपलब्ध है जहां उपयोगकर्ता खरीदारी करने की कोशिश कर रहा है. खरीदारी के लिए उपलब्ध होने के लिए, प्रॉडक्ट का ऐक्टिव होना, उसके ऐप्लिकेशन का पब्लिश होना, और उसके ऐप्लिकेशन का उपयोगकर्ता के देश में उपलब्ध होना ज़रूरी है.

कभी-कभी, खास तौर पर टेस्ट के दौरान, प्रॉडक्ट के कॉन्फ़िगरेशन में सब कुछ सही होता है. हालांकि, उपयोगकर्ताओं को अब भी यह गड़बड़ी दिखती है. ऐसा Google के सर्वर पर, प्रॉडक्ट की जानकारी को अपडेट होने में लगने वाली देरी की वजह से हो सकता है. कुछ देर बाद कोशिश करें.

DEVELOPER_ERROR

समस्या

यह एक गंभीर गड़बड़ी है. इससे पता चलता है कि आपने किसी एपीआई का गलत तरीके से इस्तेमाल किया है. उदाहरण के लिए, BillingClient.launchBillingFlow को गलत पैरामीटर देने पर, यह गड़बड़ी हो सकती है.

समस्या हल करने का तरीका

पक्का करें कि आपने Play Billing Library के अलग-अलग कॉल का सही तरीके से इस्तेमाल किया हो. साथ ही, गड़बड़ी के बारे में ज़्यादा जानकारी के लिए, डीबग मैसेज देखें.