android billing querySkuDetailsAsync 总是返回 0 skuDetails

问题描述

我正在尝试启用应用内购买,但不知道为什么我的 skuDetails 查询总是返回 0 个项目。

我已将该应用程序发布到我的内部测试中,并将我的邮件地址添加到许可证测试中(尝试了我的开发人员邮件和 2. 邮件地址),然后我在手机上下载了该应用程序,等了几个小时,并试图进行购买。它接受我的连接,但在我查询 SKU 详细信息时总是在我的 skuDetailsList 中返回 0 个元素。请帮忙?

清单:

<uses-permission android:name="com.android.vending.BILLING" />

build.gradle:

 def billing_version = "3.0.0"
     implementation "com.android.billingclient:billing-ktx:$billing_version"

querySkuDetails 方法

suspend fun querySkuDetails() {
    val skuList = ArrayList<String>()
    skuList.add(PREMIUM_UPGRADE_ID)
    val params = SkuDetailsParams.newBuilder()
    params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP)
    withContext(dispatchers.IO) {
        billingClient.querySkuDetailsAsync(params.build()) { billingResult,skuDetailsList ->
            // Process the result.
            if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                Log.v(TAG,"queryInventoryAsync - skuDetailsList:")
                if (!skuDetailsList.isNullOrEmpty()) {
                    for (item in skuDetailsList) {
                        Log.v(TAG,item.toString())
                        skuDetails = item
                    }
                } else {
                    Log.v(TAG,"skuDetailsList - is empty")
                }
                return@querySkuDetailsAsync
            }

Google Play 控制台:

enter image description here

全班:

import android.util.Log
import android.widget.Toast
import com.alexco.habitrack.activities.main.MainActivity
import com.alexco.habitrack.utilities.Persistence
import com.android.billingclient.api.*
import kotlinx.coroutines.dispatchers
import kotlinx.coroutines.withContext


class BillingCli(private val activity: MainActivity,private val database: Persistence) {

    companion object {
        private const val TAG = "InAppBilling"
        private const val PREMIUM_UPGRADE_ID = "noaddsplease"
    }


    private var purchases: Purchase.PurchasesResult? = null
    private var skuDetails: SkuDetails? = null
    private val purchasesUpdateListener =
        PurchasesUpdatedListener { billingResult,purchases ->
            if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
                for (purchase in purchases) {
                    handlePurchase(purchase)
                }
            } else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
                // Handle an error caused by a user cancelling the purchase flow.
            } else {
                // Handle any other error codes.
            }
        }

    private var billingClient: BillingClient = BillingClient.newBuilder(activity)
        .setListener(purchasesUpdateListener)
        .enablePendingPurchases()
        .build()

    init {
        connect()
    }

    private fun handlePurchase(purchase: Purchase) {

        if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
            Log.v(TAG,"purchase approved")
            database.setPremium(activity,true)
            activity.newHabitHandler.openAddHabitactivity(activity.tutorial.enabled)
            Toast.makeText(activity,"welcome to premium",Toast.LENGTH_LONG).show()

            if (!purchase.isAckNowledged) {
                val ackNowledgePurchaseParams = AckNowledgePurchaseParams.newBuilder()
                    .setPurchasetoken(purchase.purchasetoken)
                suspend {
                    val ackPurchaseResult = withContext(dispatchers.IO) {
                        billingClient.ackNowledgePurchase(
                            ackNowledgePurchaseParams.build()
                        ) {
                            Log.v(TAG,"purchase ackNowledged")
                        }
                    }
                }
            }
        }
        if (purchase.purchaseState == Purchase.PurchaseState.PENDING) {//pending
            Log.v(TAG,"purchased pending")
            return
        }
        if (purchase.purchaseState == Purchase.PurchaseState.UNSPECIFIED_STATE) {//pending
            Log.v(TAG,"purchase unspecified state")
            return
        }
    }

    private fun connect() {
        billingClient.startConnection(object : BillingClientStateListener {
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                    Log.v(TAG,"service connected")
                    // The BillingClient is ready. You can query purchases here.
                    suspend {
                        querySkuDetails()
                    }
                    suspend {
                        purchases = billingClient.queryPurchases(BillingClient.SkuType.INAPP)
                        Log.v(TAG,"onBillingSetUpFinished,purchases: ${purchases.toString()}")
                    }
                } else {
                    Log.v(TAG,"service did not connect")
                }
            }

            override fun onBillingServicedisconnected() {
                Log.v(TAG,"service disconnected")
            }
        })
    }

    suspend fun querySkuDetails() {
        val skuList = ArrayList<String>()
        skuList.add(PREMIUM_UPGRADE_ID)
        val params = SkuDetailsParams.newBuilder()
        params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP)
        withContext(dispatchers.IO) {
            billingClient.querySkuDetailsAsync(params.build()) { billingResult,skuDetailsList ->
                // Process the result.
                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                    Log.v(TAG,"queryInventoryAsync - skuDetailsList:")
                    if (!skuDetailsList.isNullOrEmpty()) {
                        for (item in skuDetailsList) {
                            Log.v(TAG,item.toString())
                            skuDetails = item
                        }
                    } else {
                        Log.v(TAG,"skuDetailsList - is empty")
                    }
                    return@querySkuDetailsAsync
                }

                if (billingResult.responseCode == 1) {
                    //user cancel
                    return@querySkuDetailsAsync
                }
                if (billingResult.responseCode == 2) {
                    Toast.makeText(activity,"Internet required for purchase",Toast.LENGTH_LONG)
                        .show()
                    return@querySkuDetailsAsync
                }
                if (billingResult.responseCode == 3) {
                    Toast.makeText(
                        activity,"Incompatible Google Play Billing Version",Toast.LENGTH_LONG
                    ).show()
                    return@querySkuDetailsAsync
                }
                if (billingResult.responseCode == 7) {
                    Toast.makeText(activity,"you already own Premium",Toast.LENGTH_LONG)
                        .show()
                    return@querySkuDetailsAsync
                }
                Toast.makeText(
                    activity,"no skuDetails sorry",Toast.LENGTH_LONG
                )
                    .show()
                Log.v(TAG,"responseCode: ${billingResult.responseCode}")
                Log.v(TAG,"debug: ${billingResult.debugMessage}")
            }
        }
    }

    fun makePurchase() {

        if (purchases != null) {
            if (purchases!!.purchasesList != null) {
                if (purchases!!.purchasesList!!.size > 0) {
                    Toast.makeText(
                        activity,"you already owns premium\n-premium activated-",Toast.LENGTH_LONG
                    ).show()
                    database.setPremium(activity,true)
                    activity.newHabitHandler.openAddHabitactivity(activity.tutorial.enabled)
                }
            }
        }

        // Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
        if (skuDetails != null) {
            val flowParams = BillingFlowParams.newBuilder()
                .setSkuDetails(skuDetails!!)
                .build()
            val responseCode = billingClient.launchBillingFlow(activity,flowParams).responseCode

            Log.v(TAG,"makePurchase - responseCode:$responseCode")
        } else {
            Log.v(TAG,"makePurchase - no skuDetails")
            Toast.makeText(activity,"Google didn't accept the purchase attempt",Toast.LENGTH_LONG)
                .show()
        }
    }

解决方法

我在 google play 控制台中删除了该项目并获得了一个具有新 ID 的新项目,并且它工作正常¯_(ツ)_/¯