即使我确认购买,Google仍会在3天内退还所有已购买的订阅

问题描述

我开发了一个项目,该项目集成了应用内订阅方法。 它是非消耗性产品,每月有3.99美元的订阅项目。 我已使用计费客户端方法2.1.0并在Google上配置了订阅项。 当我通过内部测试测试应用程序订阅时,它表明该商品已成功购买。 但是,发行版具有很大的风险。 所有用户订阅将在3天内自动退款。 Google支持小组表示,确认所有购买必须在三天内完成。 如果未正确确认购买,则会导致这些购买被退款。

我集成了确认侦听器,但结果仍然相同。 我将附上几张截图,显示如何退款。

Google issued refund

Payment refunded steps

这是我正在处理的代码。 是否有任何原因由于我的代码问题而将所有物品自动退款? 感谢您的阅读和观看。

//build.gradle
implementation 'com.android.billingclient:billing:2.1.0'
implementation 'com.android.billingclient:billing-ktx:2.1.0'

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

//Subscription Purchase and AckNowledge code

class SubscriptionActivity : AppCompatActivity(),PurchasesUpdatedListener {
    lateinit var billingClient: BillingClient
    lateinit var skuList: MutableList<SkuDetails>

    val ackNowledgePurchaseResponseListener =
        AckNowledgePurchaseResponseListener {
            Toast.makeText(this@SubscriptionActivity,"Purchase ackNowledged",Toast.LENGTH_SHORT).show() }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_subscription)

        setupBillingClient()
        setupInitEvents()

    }

    private fun getAvailableProducts() {
        if (billingClient.isReady)
        {
            val params = SkuDetailsParams.newBuilder()
                .setSkusList(Arrays.asList(SubscriptionID))
                .setType(BillingClient.SkuType.SUBS)
                .build()

            billingClient.querySkuDetailsAsync(params)
            {
                    p0,skuDetailsList ->
                if (p0.responseCode == BillingClient.BillingResponseCode.OK)
                    skuList = skuDetailsList as MutableList<SkuDetails>
                    //displayProduct(skuDetailsList)
                else {
                    //Toast.makeText(this@SubscriptionActivity,"Cannot find product",Toast.LENGTH_SHORT).show()
                }
            }
        }
        else
        {
            //Toast.makeText(this@SubscriptionActivity,"Billing Client not ready",Toast.LENGTH_SHORT).show()
        }
    }

        private fun setupBillingClient() {
        //billingClient = BillingClient.newBuilder(this).setListener(this).build()
        billingClient = BillingClient.newBuilder(this)
            .enablePendingPurchases()
            .setListener(this)
            .build();

        billingClient.startConnection(object:BillingClientStateListener{
            override fun onBillingServicedisconnected() {
                //Toast.makeText(this@SubscriptionActivity,"disconnected",Toast.LENGTH_SHORT).show()
            }

            override fun onBillingSetupFinished(p0: BillingResult) {
                if (p0.responseCode == BillingClient.BillingResponseCode.OK) {
                    getAvailableProducts();
                } else {
                    /*
                    Toast.makeText(
                        this@SubscriptionActivity,"BillingClient connecting err : " + p0.responseCode,Toast.LENGTH_SHORT
                    ).show()
                }
            }
        })
    }

    private fun setupInitEvents() {
        buttonClose.setonClickListener {
            closeActivity()
        }

        buttonContainer.setonClickListener {
            purchase()
        }

        buttonRestorePurchase.setonClickListener {
            restorePurchase()
        }
    }

    private fun closeActivity() {
        setResult(Activity.RESULT_CANCELED,null);
        finish()
    }

    private fun purchase() {
        if (!SpLaunch.getPurchasetoken().isNullOrEmpty())
        {
            val builder = AlertDialog.Builder(this)
                .setTitle(getString(R.string.restore_title))
                .setMessage("Already Purchased")
                .setPositiveButton(R.string.ok) { dialog,id ->
                }
                .create().show()
            return
        }

        if (this::skuList.isInitialized && skuList.size > 0) {
            var billingFlowParams = BillingFlowParams.newBuilder()
                .setSkuDetails(skuList[0])
                .build()

            val responseCode = billingClient.launchBillingFlow(this,billingFlowParams).responseCode

        } else {
            //Toast.makeText(this@SubscriptionActivity,"No Subscription List",Toast.LENGTH_SHORT).show()

        }
    }

    private fun restorePurchase() {
        //Toast.makeText(this@SubscriptionActivity,"restorePurchase",Toast.LENGTH_SHORT).show()

        if (SpLaunch.getPurchasetoken().isNullOrEmpty())
        {
            val builder = AlertDialog.Builder(this)
                .setTitle(getString(R.string.restore_title))
                .setMessage(getString(R.string.restore_message))
                .setPositiveButton(R.string.ok) { dialog,id ->

                }
                .create().show()
        } else {
            val url = "https://www.googleapis.com/androidpublisher/v3/applications/" + packageName + "/purchases/subscriptions/" + SubscriptionID + "/tokens/" + SpLaunch.getPurchasetoken() + ":refund"

            HttpTask({
                if (it == null) {
                    //Toast.makeText(this@SubscriptionActivity,"Connection error",Toast.LENGTH_SHORT).show()
                    return@HttpTask
                }
                //Toast.makeText(this@SubscriptionActivity,"refund Success",Toast.LENGTH_SHORT).show()
                SpLaunch.setPurchasetoken("")
            }).execute("POST",url,"")
        }
    }

    override fun onPurchasesUpdated(p0: BillingResult,p1: MutableList<Purchase>?) {
        if (p0.responseCode == BillingClient.BillingResponseCode.OK && p1 != null) {
            //Toast.makeText(this@SubscriptionActivity,"Purchase Success",Toast.LENGTH_SHORT).show()

            for (_pur in p1) {
                var packageName: String = _pur.packageName
                var purchasetoken: String = _pur.purchasetoken
                var purchaseTime: Long = _pur.purchaseTime
                var purchaseState: Int = _pur.purchaseState

                SpLaunch.setPurchasePackage(packageName)
                SpLaunch.setPurchasetoken(purchasetoken)
                SpLaunch.setPurchaseTime(purchaseTime)
                SpLaunch.setPurchaseState(purchaseState)

                handlePurchase(_pur)
            }

            setResult(Activity.RESULT_OK,null)
            finish()
        } else if (p0.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
            //Toast.makeText(this@SubscriptionActivity,"Purchase canceled by User",Toast.LENGTH_SHORT).show()
            setResult(Activity.RESULT_CANCELED,null)
            finish()
        } else {
            //Toast.makeText(this@SubscriptionActivity,"Purchase canceled by Error: " + p0.responseCode,null)
            finish()
        }

    }

    private fun handlePurchase(purchase : Purchase)
    {
        //in handlePurchase()
        if (purchase.purchaseState === Purchase.PurchaseState.PURCHASED) {
            /*
            val ackNowledgePurchaseParams: AckNowledgePurchaseParams =
                AckNowledgePurchaseParams.newBuilder()
                    .setPurchasetoken(purchase.purchasetoken)
                    .build()

            billingClient.ackNowledgePurchase(
                ackNowledgePurchaseParams,ackNowledgePurchaseResponseListener
            )*/

            val params = AckNowledgePurchaseParams.newBuilder()
                .setPurchasetoken(purchase.purchasetoken)
                .build()
            billingClient.ackNowledgePurchase(params) { billingResult ->
                val responseCode = billingResult.responseCode
                val debugMessage = billingResult.debugMessage
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        billingClient.endConnection()
    }

}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)