จัดการโค้ดตอบกลับ Billingผลลัพธ์

เมื่อการเรียกใช้ Play Billing Library ทริกเกอร์การดำเนินการ ไลบรารีจะแสดงการตอบกลับ BillingResult เพื่อแจ้งให้นักพัฒนาแอปทราบผลลัพธ์ ตัวอย่างเช่น หากคุณใช้ queryProductDetailsAsync เพื่อรับข้อเสนอที่มีให้สำหรับผู้ใช้ โค้ดตอบกลับจะมี รหัส OK และแสดงออบเจ็กต์ ProductDetails ที่ถูกต้อง หรือมีคำตอบอื่นที่ระบุเหตุผลที่แสดงออบเจ็กต์ ProductDetails ไม่ได้

ไม่ใช่ว่ารหัสการตอบกลับทั้งหมดจะเป็นข้อผิดพลาด หน้าอ้างอิง BillingResponseCode จะอธิบายรายละเอียดของการตอบกลับแต่ละรายการที่ กล่าวถึงในคู่มือนี้ ตัวอย่างรหัสการตอบกลับที่ไม่ได้บ่งบอกถึงข้อผิดพลาด ได้แก่

  • BillingClient.BillingResponseCode.OK : การดำเนินการที่ทริกเกอร์โดยการเรียกใช้เสร็จสมบูรณ์
  • BillingClient.BillingResponseCode.USER_CANCELED : สำหรับการดำเนินการที่แสดงขั้นตอน UI ของ Play Store ต่อผู้ใช้ การตอบกลับนี้บ่งบอกว่าผู้ใช้ได้ออกจากขั้นตอน UI เหล่านั้นโดยไม่ได้ทำกระบวนการให้เสร็จสมบูรณ์

เมื่อโค้ดตอบกลับบ่งบอกถึงข้อผิดพลาด สาเหตุอาจเกิดจากสภาวะชั่วคราว จึงสามารถกู้คืนได้ เมื่อการเรียกใช้เมธอด Play Billing Library แสดงค่า BillingResponseCode ที่บ่งบอกถึงสภาวะที่กู้คืนได้ คุณควรลองเรียกใช้อีกครั้ง ในกรณีอื่นๆ ระบบจะไม่ถือว่าสภาวะเป็นแบบชั่วคราว จึงไม่แนะนำให้ลองอีกครั้ง

ข้อผิดพลาดชั่วคราวต้องใช้กลยุทธ์การลองอีกครั้งที่แตกต่างกันไปตามปัจจัยต่างๆ เช่น ข้อผิดพลาดเกิดขึ้นเมื่อผู้ใช้อยู่ในเซสชัน (เช่น เมื่อผู้ใช้ ทำตามขั้นตอนการซื้อ) หรือข้อผิดพลาดเกิดขึ้นในเบื้องหลัง (เช่น เมื่อคุณค้นหาการซื้อที่มีอยู่ของผู้ใช้ระหว่าง onResume) ส่วนกลยุทธ์การลองอีกครั้งด้านล่างมีตัวอย่างกลยุทธ์ต่างๆ เหล่านี้ และส่วนการตอบกลับ BillingResultที่ลองอีกครั้งได้ จะแนะนำกลยุทธ์ที่เหมาะที่สุดสำหรับโค้ดตอบกลับแต่ละรายการ

นอกเหนือจากโค้ดตอบกลับแล้ว การตอบกลับข้อผิดพลาดบางรายการยังมีข้อความสำหรับวัตถุประสงค์ในการแก้ไขข้อบกพร่องและการบันทึก

กลยุทธ์การลองอีกครั้ง

การลองอีกครั้งแบบง่าย

ในสถานการณ์ที่ผู้ใช้อยู่ในเซสชัน การใช้กลยุทธ์การลองอีกครั้งแบบง่ายจะดีกว่า เพื่อให้ข้อผิดพลาดรบกวนประสบการณ์ของผู้ใช้น้อยที่สุด ในกรณีนี้ เราขอแนะนำกลยุทธ์การลองอีกครั้งแบบง่ายโดยกำหนดจำนวนครั้งที่ลองสูงสุดเป็นเงื่อนไขการออก

ตัวอย่างต่อไปนี้แสดงกลยุทธ์การลองอีกครั้งแบบง่ายเพื่อจัดการข้อผิดพลาด เมื่อสร้าง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)
  }
  ...
}

การลองอีกครั้งแบบ Exponential Backoff

เราขอแนะนำให้ใช้ Exponential Backoff สำหรับการดำเนินการ 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

วิธีแก้ปัญหาที่เป็นไปได้

หากต้องการกู้คืน ให้ใช้การลองอีกครั้งแบบง่ายหรือ Exponential Backoff ขึ้นอยู่กับการดำเนินการที่ทริกเกอร์ข้อผิดพลาด

SERVICE_TIMEOUT (รหัสข้อผิดพลาด -3)

ปัญหา

ข้อผิดพลาดนี้บ่งบอกว่าคำขอหมดเวลาสูงสุดก่อนที่ Google Play จะตอบกลับได้ สาเหตุอาจเกิดจากความล่าช้าในการดำเนินการตามคำขอที่เรียกใช้โดย Play Billing Library

วิธีแก้ปัญหาที่เป็นไปได้

โดยปกติแล้วปัญหานี้จะเป็นปัญหาชั่วคราว ลองส่งคำขออีกครั้งโดยใช้กลยุทธ์การลองอีกครั้งแบบง่ายหรือ Exponential Backoff ขึ้นอยู่กับการดำเนินการที่แสดงข้อผิดพลาด

การเชื่อมต่อกับบริการ Google Play Billing จะไม่ถูกตัดขาดเหมือนกับ SERVICE_DISCONNECTED ด้านล่าง และคุณ เพียงแค่ต้องลองดำเนินการ Play Billing Library ที่พยายามดำเนินการอีกครั้ง

SERVICE_DISCONNECTED (รหัสข้อผิดพลาด -1)

ปัญหา

ข้อผิดพลาดร้ายแรงนี้บ่งบอกว่าการเชื่อมต่อของแอปไคลเอ็นต์กับบริการ Google Play Store ผ่าน BillingClient ถูกตัดขาด

วิธีแก้ปัญหาที่เป็นไปได้

Play Billing Library เวอร์ชัน 8.0.0 ได้เปิดตัวฟีเจอร์ enableAutoServiceReconnection() เราขอแนะนำอย่างยิ่งให้คุณเปิดใช้ฟีเจอร์นี้ เมื่อสร้าง BillingClient ซึ่งจะช่วยให้ไลบรารีพยายามสร้างการเชื่อมต่ออีกครั้งโดยอัตโนมัติเมื่อมีการเรียกใช้ Billing API ขณะที่บริการถูกตัดการเชื่อมต่อ ซึ่งจะช่วยลดการเกิดข้อผิดพลาดนี้ลงอย่างมาก

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 เมื่อทำการเรียก API แสดงว่าไลบรารีไม่สามารถเชื่อมต่ออีกครั้งหลังจากพยายามโดยอัตโนมัติ ในสถานการณ์นี้ คุณควรใช้ตรรกะการลองอีกครั้งในแอปดังนี้

  • สำหรับการดำเนินการที่ผู้ใช้เริ่ม (ในเซสชัน): ใช้การลองเรียกใช้ API อีกครั้งแบบง่าย ปัญหาพื้นฐานอาจเป็นปัญหาชั่วคราว
  • สำหรับคำขอเบื้องหลัง: ใช้การลองอีกครั้งแบบ Exponential Backoff เพื่อหลีกเลี่ยงไม่ให้ระบบทำงานหนักเกินไปหากการตัดการเชื่อมต่อเกิดขึ้นเป็นเวลานาน
หากคุณไม่ได้เปิดใช้การเชื่อมต่อบริการอีกครั้งโดยอัตโนมัติ

หากต้องการหลีกเลี่ยงข้อผิดพลาดนี้ให้ได้มากที่สุด ให้ตรวจสอบการเชื่อมต่อกับบริการ Google Play เสมอก่อนที่จะเรียกใช้ Play Billing Library โดยเรียกใช้ BillingClient.isReady()

หากต้องการพยายามกู้คืนจาก SERVICE_DISCONNECTED แอปไคลเอ็นต์ควรพยายามสร้างการเชื่อมต่ออีกครั้งโดยใช้ BillingClient.startConnection

เช่นเดียวกับ SERVICE_TIMEOUT ให้ใช้การลองอีกครั้งแบบง่ายหรือ Exponential Backoff ขึ้นอยู่กับการดำเนินการที่ทริกเกอร์ ข้อผิดพลาด

SERVICE_UNAVAILABLE (รหัสข้อผิดพลาด 2)

หมายเหตุสำคัญ:

ตั้งแต่ Google Play Billing Library 6.0.0 เป็นต้นไป ระบบจะไม่แสดง SERVICE_UNAVAILABLE สำหรับปัญหาเกี่ยวกับเครือข่ายอีกต่อไป แต่จะแสดงเมื่อบริการการเรียกเก็บเงินไม่พร้อมให้บริการและสถานการณ์กรณี SERVICE_TIMEOUT ที่เลิกใช้งานแล้ว

ปัญหา

ข้อผิดพลาดชั่วคราวนี้บ่งบอกว่าบริการ Google Play Billing ไม่พร้อมให้บริการในขณะนี้ ในกรณีส่วนใหญ่ หมายความว่าเกิดปัญหาการเชื่อมต่อเครือข่ายระหว่างอุปกรณ์ไคลเอ็นต์กับบริการ Google Play Billing

วิธีแก้ปัญหาที่เป็นไปได้

โดยปกติแล้วปัญหานี้จะเป็นปัญหาชั่วคราว ลองส่งคำขออีกครั้งโดยใช้กลยุทธ์การลองอีกครั้งแบบง่ายหรือ Exponential Backoff ขึ้นอยู่กับการดำเนินการที่แสดงข้อผิดพลาด

การเชื่อมต่อกับบริการ Google Play Billing จะไม่ถูกตัดขาดเหมือนกับ SERVICE_DISCONNECTED และคุณต้อง ลองดำเนินการที่พยายามดำเนินการอีกครั้ง

BILLING_UNAVAILABLE (รหัสข้อผิดพลาด 3)

ปัญหา

ข้อผิดพลาดนี้บ่งบอกว่าเกิดข้อผิดพลาดในการเรียกเก็บเงินจากผู้ใช้ระหว่างกระบวนการซื้อ ตัวอย่างกรณีที่อาจเกิดข้อผิดพลาดนี้ ได้แก่

  • แอป Play Store ในอุปกรณ์ของผู้ใช้ล้าสมัย
  • ผู้ใช้อยู่ในประเทศที่ไม่รองรับ
  • ผู้ใช้เป็นผู้ใช้ระดับองค์กร และผู้ดูแลระบบขององค์กรได้ปิดใช้การซื้อของผู้ใช้
  • Google Play ไม่สามารถเรียกเก็บเงินจากวิธีการชำระเงินของผู้ใช้ เช่น บัตรเครดิตของผู้ใช้อาจหมดอายุ

วิธีแก้ปัญหาที่เป็นไปได้

การลองอีกครั้งโดยอัตโนมัติไม่น่าจะช่วยได้ในกรณีนี้ อย่างไรก็ตาม การลองอีกครั้งด้วยตนเองอาจช่วยได้หากผู้ใช้แก้ไขเงื่อนไขที่ทำให้เกิดปัญหา ตัวอย่างเช่น หากผู้ใช้อัปเดต Play Store เป็นเวอร์ชันที่รองรับ การลองดำเนินการเริ่มต้นอีกครั้งด้วยตนเองอาจได้ผล

หากข้อผิดพลาดนี้เกิดขึ้นเมื่อผู้ใช้ไม่ได้อยู่ในเซสชัน การลองอีกครั้งอาจไม่สมเหตุสมผล เมื่อคุณได้รับข้อผิดพลาด BILLING_UNAVAILABLE อันเป็นผลมาจากขั้นตอนการซื้อ ผู้ใช้มีแนวโน้มมากที่จะได้รับ ความคิดเห็นจาก Google Play ระหว่างกระบวนการซื้อและอาจทราบถึงสิ่งที่ ผิดพลาด ในกรณีนี้ คุณสามารถแสดงข้อความแสดงข้อผิดพลาดที่ระบุว่าเกิดข้อผิดพลาดขึ้นและเสนอปุ่ม "ลองอีกครั้ง" เพื่อให้ผู้ใช้มีตัวเลือกในการลองอีกครั้งด้วยตนเองหลังจากแก้ไขปัญหาแล้ว

ERROR (รหัสข้อผิดพลาด 6)

ปัญหา

ข้อผิดพลาดร้ายแรงนี้บ่งบอกว่าเกิดปัญหาภายในกับ Google Play เอง

วิธีแก้ปัญหาที่เป็นไปได้

บางครั้งปัญหาภายในของ Google Play ที่ทำให้เกิด ERROR เป็นปัญหาชั่วคราว และคุณสามารถใช้การลองอีกครั้งแบบ Exponential Backoff เพื่อลดผลกระทบได้ เมื่อผู้ใช้อยู่ในเซสชัน การลองอีกครั้งแบบง่ายจะดีกว่า

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 การลองอีกครั้งโดยใช้กลยุทธ์การลองอีกครั้งแบบง่ายหลังจากเกิดข้อผิดพลาดควรแก้ไขอินสแตนซ์ชั่วคราวที่เฉพาะเจาะจงนี้ได้ เรียกใช้ BillingClient.queryPurchasesAsync() หลังจากได้รับ ITEM_NOT_OWNED เพื่อตรวจสอบว่าผู้ใช้ได้รับ ผลิตภัณฑ์แล้วหรือไม่ หากยังไม่ได้รับ ให้ใช้ตรรกะการลองอีกครั้งแบบง่ายเพื่อพยายามซื้ออีกครั้ง

การตอบกลับ BillingResult ที่ลองอีกครั้งไม่ได้

คุณไม่สามารถกู้คืนจากข้อผิดพลาดเหล่านี้ได้โดยใช้ตรรกะการลองอีกครั้ง

FEATURE_NOT_SUPPORTED

ปัญหา

ข้อผิดพลาดที่ลองอีกครั้งไม่ได้นี้บ่งบอกว่าอุปกรณ์ของผู้ใช้ไม่รองรับฟีเจอร์ Google Play Billing ซึ่งอาจเป็นเพราะ Play Store เวอร์ชันเก่า

ตัวอย่างเช่น อุปกรณ์ของผู้ใช้บางรายอาจไม่รองรับการรับส่งข้อความในแอป

วิธีลดผลกระทบที่เป็นไปได้

ใช้ BillingClient.isFeatureSupported() เพื่อตรวจสอบการรองรับฟีเจอร์ก่อนที่จะเรียกใช้ Play Billing Library

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

USER_CANCELED

ปัญหา

ผู้ใช้คลิกออกจาก UI ของขั้นตอนการเรียกเก็บเงิน

วิธีแก้ปัญหาที่เป็นไปได้

ข้อผิดพลาดนี้เป็นเพียงข้อมูลและสามารถล้มเหลวได้อย่างราบรื่น

ITEM_UNAVAILABLE

ปัญหา

การสมัครใช้บริการหรือผลิตภัณฑ์ที่ซื้อครั้งเดียวของ Google Play Billing ไม่พร้อมให้ผู้ใช้รายนี้ซื้อ

วิธีลดผลกระทบที่เป็นไปได้

ตรวจสอบว่าแอปของคุณรีเฟรชรายละเอียดผลิตภัณฑ์ผ่าน queryProductDetailsAsync ตามที่แนะนำ พิจารณาความถี่ที่แคตตาล็อกผลิตภัณฑ์ของคุณเปลี่ยนแปลงในการกำหนดค่า Play Console เพื่อใช้การรีเฟรชเพิ่มเติมหากจำเป็น พยายามขายผลิตภัณฑ์ใน Google Play Billing ที่แสดงข้อมูลที่ถูกต้อง ผ่าน queryProductDetailsAsync เท่านั้น ตรวจสอบการกำหนดค่าการมีสิทธิ์ของผลิตภัณฑ์เพื่อดูความไม่สอดคล้องกัน ตัวอย่างเช่น คุณอาจค้นหาผลิตภัณฑ์ที่พร้อมให้บริการในภูมิภาคอื่นที่ไม่ใช่ภูมิภาคที่ผู้ใช้พยายามซื้อ ผลิตภัณฑ์ต้องใช้งานได้ แอปต้องเผยแพร่ และแอปต้องพร้อมให้บริการในประเทศของผู้ใช้จึงจะพร้อมให้ซื้อ

บางครั้ง โดยเฉพาะอย่างยิ่งระหว่างการทดสอบ การกำหนดค่าผลิตภัณฑ์ถูกต้องทุกอย่าง แต่ผู้ใช้ยังคงเห็นข้อผิดพลาดนี้ ซึ่งอาจเกิดจากความล่าช้าในการเผยแพร่รายละเอียดผลิตภัณฑ์ในเซิร์ฟเวอร์ของ Google โปรดลองอีกครั้งในภายหลัง

DEVELOPER_ERROR

ปัญหา

ข้อผิดพลาดร้ายแรงนี้บ่งบอกว่าคุณใช้ API อย่างไม่ถูกต้อง ตัวอย่างเช่น การระบุพารามิเตอร์ที่ไม่ถูกต้องให้กับ BillingClient.launchBillingFlow อาจทำให้เกิดข้อผิดพลาดนี้

วิธีแก้ปัญหาที่เป็นไปได้

ตรวจสอบว่าคุณใช้การเรียกใช้ Play Billing Library ต่างๆ อย่างถูกต้อง นอกจากนี้ ให้ตรวจสอบข้อความแก้ไขข้อบกพร่องเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับข้อผิดพลาด