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

Google Play内购退款后无法重购的内部测试问题解决求助

Google Play内购退款后无法重新购买的测试解决方案

问题背景

应用已发布至Internal Testing渠道,测试阶段遇到如下问题:

  • 成功购买非消耗型内购项目后,通过Google Play控制台完成退款操作
  • 退款后尝试重新购买该项目,收到「您已拥有该项目」的提示
  • 已知Google Play退款后仍会将该项目标记为Purchase.PurchaseState.PURCHASED,需通过编程方式处理以支持重新购买测试

现有购买处理代码

private fun processPurchases(purchasesResult: Set<Purchase>) {
    val validPurchases = HashSet<Purchase>(purchasesResult.size)
    purchasesResult.forEach { purchase ->
        if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
            if (purchase.skus.contains(purchaseItem)) {  
                if (isSignatureValid(purchase)) {
                    validPurchases.add(purchase)
                }
            }
        } else if (purchase.purchaseState == Purchase.PurchaseState.PENDING) {
            Log.e(LOG_TAG, "Received a pending purchase of SKU: ${purchase.skus}")
            mContext.toast(R.string.msgOrderPending)
        } else {
            mContext.toast(R.string.msgOrderError)
        }
    }

    acknowledgeNonConsumablePurchasesAsync(validPurchases.toList())
}

解决方案

核心逻辑调整

Google Play不会自动将已退款的非消耗型内购状态改为「已退款」,仍保留PURCHASED标记但订单已失效。需在购买处理流程中增加退款判断,跳过已退款订单的确认逻辑,允许用户重新发起购买。

代码修改示例

1. 新增退款状态检查逻辑

private fun processPurchases(purchasesResult: Set<Purchase>) {
    val validPurchases = HashSet<Purchase>(purchasesResult.size)
    purchasesResult.forEach { purchase ->
        if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
            if (purchase.skus.contains(purchaseItem)) {  
                if (isSignatureValid(purchase)) {
                    // 判断当前订单是否已退款
                    val isRefunded = checkPurchaseRefundStatus(purchase.orderId)
                    if (!isRefunded) {
                        validPurchases.add(purchase)
                    } else {
                        Log.d(LOG_TAG, "跳过已退款订单: ${purchase.orderId}")
                    }
                }
            }
        } else if (purchase.purchaseState == Purchase.PurchaseState.PENDING) {
            Log.e(LOG_TAG, "Received a pending purchase of SKU: ${purchase.skus}")
            mContext.toast(R.string.msgOrderPending)
        } else {
            mContext.toast(R.string.msgOrderError)
        }
    }

    acknowledgeNonConsumablePurchasesAsync(validPurchases.toList())
}

// 测试环境可通过订单ID标识或调用Google Play Developer API查询退款状态
private fun checkPurchaseRefundStatus(orderId: String): Boolean {
    // 示例:根据测试退款订单的ID特征判断
    return orderId.startsWith("TEST_REFUNDED_")
}

2. 测试模式临时处理(仅内部测试使用)

如果是内部测试阶段,可添加测试开关快速跳过已退款订单:

// 测试开关,正式发布时需关闭
private const val IN_TEST_MODE = true

private fun processPurchases(purchasesResult: Set<Purchase>) {
    val validPurchases = HashSet<Purchase>(purchasesResult.size)
    purchasesResult.forEach { purchase ->
        if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
            if (purchase.skus.contains(purchaseItem)) {  
                if (isSignatureValid(purchase)) {
                    if (!IN_TEST_MODE || !checkPurchaseRefundStatus(purchase.orderId)) {
                        validPurchases.add(purchase)
                    } else {
                        Log.d(LOG_TAG, "测试模式:跳过已退款订单")
                    }
                }
            }
        }
        // 其余逻辑保持不变
    }

    acknowledgeNonConsumablePurchasesAsync(validPurchases.toList())
}

注意事项

  • 正式环境必须通过Google Play Developer API准确查询订单退款状态,禁止依赖测试开关
  • 已退款的非消耗型订单无需调用acknowledge,否则会导致用户无法重新购买
  • 测试完成后需移除所有测试相关逻辑,避免影响正式用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 18:44:53