You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Qonversion API校验用户订阅状态遇问题求助

Qonversion订阅状态校验问题:购买成功但回调不触发、checkEntitlements返回null

问题现象

  • 用户完成谷歌订阅后返回应用,调用checkEntitlements无法获取权限(返回null)
  • 实际订阅已成功(再次订阅时谷歌提示已订阅),但purchase方法完全不进入onSuccess回调

相关代码

Fragment定义

class PurchaseFragment : Fragment() {
    private var _binding: FragmentPurchaseBinding? = null
    private val binding get() = _binding!!

    private var product: QProduct? = null

展示产品逻辑

private fun displayProducts() {
            Qonversion.shared.offerings(object : QonversionOfferingsCallback {
                override fun onSuccess(offerings: QOfferings) {
                    val mainOffering = offerings.main
                    if (mainOffering != null && mainOffering.products.isNotEmpty()) {   
                        binding.monthlyPrice.text = mainOffering.products[0].prettyPrice
                        product = mainOffering.products[0]
                    }
                }

                override fun onError(error: QonversionError) {
                    Log.d(TAG, "Error: $error")
                }
            })
        }

发起购买逻辑

private fun makePurchase(product: QProduct) {
            Qonversion.shared.purchase(
                requireActivity(),
                product,
                callback = object : QonversionEntitlementsCallback {
                    override fun onSuccess(entitlements: Map<String, QEntitlement>) {
                        val premiumEntitlement = entitlements["premium_permisson"]
                        if (premiumEntitlement != null && premiumEntitlement.isActive) {
                            Log.d(TAG, "Entitlements: $premiumEntitlement")
                        } else {
                            Log.d(TAG, "Entitlements else: $premiumEntitlement")
                        }
                    }

                    override fun onError(error: QonversionError) {
                        // 处理错误
                        if (error.code === QonversionErrorCode.CanceledPurchase) {
                            Log.d(TAG, "Canceled")
                        }
                    }
                })
        }

订阅状态校验逻辑

private fun isItPremiumUser() {
    Qonversion.shared.checkEntitlements(object : QonversionEntitlementsCallback {
        override fun onSuccess(entitlements: Map<String, QEntitlement>) {
            val premiumEntitlement = entitlements["premium_permisson"]

            Log.d(TAG, "isItPremiumUser $premiumEntitlement") // 返回null
            if (premiumEntitlement != null && premiumEntitlement.isActive) {
                Log.d(TAG, "isItPremiumUser Entitlements: $premiumEntitlement")
                // 处理有效权限

                // 可检查续订状态
                // 例如检查用户是否取消订阅并提供折扣
                when (premiumEntitlement.renewState) {
                    QEntitlementRenewState.NonRenewable -> {
                        Log.d(TAG, "NonRenewable Entitlements: $premiumEntitlement")
                        // NonRenewable是消耗型或非消耗型内购的状态
                    }
                    QEntitlementRenewState.WillRenew -> {
                        Log.d(TAG, "WillRenew Entitlements: $premiumEntitlement")
                        // WillRenew是自动续订订阅的状态
                    }
                    QEntitlementRenewState.BillingIssue -> {
                        Log.d(TAG, "BillingIssue Entitlements: $premiumEntitlement")
                        // 提示用户更新支付方式
                    }
                    QEntitlementRenewState.Canceled -> {
                        Log.d(TAG, "Canceled Entitlements: $premiumEntitlement")
                        // 用户已关闭自动续订,但订阅尚未过期
                        // 提示用户以优惠重新订阅
                    }
                    else -> {
                        Log.d(TAG, "else Entitlements: $premiumEntitlement")
                    }
                }
            }
        }

        override fun onError(error: QonversionError) {
            // 处理错误
           Log.d(TAG, "onError: $error")
        }
    })
}

解决方案

1. 核对权限ID一致性

检查代码中使用的权限ID premium_permisson 是否和Qonversion后台配置的权限ID完全一致,注意大小写、拼写错误(比如多字符、少字符)。后台配置的权限ID必须与代码调用的完全匹配,否则会返回null。

2. 确保Qonversion与谷歌订阅同步正常

Qonversion需要同步谷歌Play Billing的订阅状态,需确认:

  • 已在Qonversion后台正确配置谷歌服务账号密钥(JSON文件),确保订阅状态能从谷歌同步到Qonversion
  • 测试环境下(如使用谷歌测试账号购买),需开启Qonversion后台的测试模式,确保测试订阅被正确同步

3. 修复purchase回调不触发问题

purchase不进入onSuccess通常由以下原因导致:

  • Activity生命周期问题:调用purchase时传入的requireActivity()可能在购买流程中被销毁,导致回调无法触发。建议使用viewLifecycleOwner关联的上下文,或确保Activity在购买过程中保持存活。
  • 未转发Activity结果:若Qonversion版本需要手动处理Activity结果,需在Fragment中重写onActivityResult并转发给Qonversion:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    Qonversion.shared.onActivityResult(requestCode, resultCode, data)
}
  • 错误回调未捕获全部情况:在purchase的onError中打印完整错误信息,排查是否有其他异常:
override fun onError(error: QonversionError) {
    Log.d(TAG, "Purchase error: code=${error.code}, message=${error.message}")
}

4. 正确的订阅状态校验流程

不要仅依赖checkEntitlements,建议结合以下步骤:

  • 购买完成后主动同步:用户从谷歌支付界面返回应用时,先调用Qonversion.shared.syncPurchases()同步本地购买记录到Qonversion,再校验权限:
// 在onResume或购买返回后调用
Qonversion.shared.syncPurchases(object : QonversionSyncCallback {
    override fun onSuccess() {
        isItPremiumUser() // 同步完成后再校验权限
    }

    override fun onError(error: QonversionError) {
        Log.d(TAG, "Sync error: $error")
    }
})
  • 开启自动同步:在Application初始化时开启Qonversion自动同步,让SDK自动处理订阅状态更新:
// Application类中初始化Qonversion
Qonversion.initialize(applicationContext, "YOUR_QONVERSION_KEY", true)
// 第三个参数true表示开启自动同步购买记录

5. 测试环境注意事项

使用谷歌测试账号购买订阅时:

  • 测试订阅有效期通常很短(如5分钟),过期后权限会失效
  • 确保Qonversion后台测试模式已开启,或测试订单被正确识别

内容的提问来源于stack exchange,提问作者burhanyaprak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:30:45