购买成功后(onPurchasesUpdated),或者确认成功后(onAcknowledgePurchaseResponse),我们应该解锁应用内商品吗?

时间:2020-07-28 10:50:38

标签: android in-app-billing android-billing

自从计费库2和3开始,购买成功后,我们需要执行额外的确认步骤。


购买成功后,将触发以下回叫。

df <- structure(list(rating = c(0.6, NA, 0.9, NA, 0, NA), playerID = c("a1", 
"b2", "a4", "b5", "a3", "b2")), row.names = c(NA, -6L), class = "data.frame")

确认成功后,将触发以下回叫。

public interface PurchasesUpdatedListener {
    void onPurchasesUpdated(BillingResult billingResult, java.util.List<com.android.billingclient.api.Purchase> list);
}

在成功案例中,当购买成功或确认成功时,我们应该解锁应用内购买项目吗?

2 个答案:

答案 0 :(得分:0)

请查看“授予权利之前验证购买”部分。

https://developer.android.com/google/play/billing/security#verify

只有在通过后端服务器确认购买合法之后,才能解锁内容。

您实施onPurchasesUpdated,以获取有关在应用内或应用外启动的购买更新的通知。

如果您不确认购买,则该购买将自动退款。您实施onAcknowledgePurchaseResponse,以接收有关购买操作确认已完成的通知。

但是要知道它是否合法购买,您必须在授予权利之前确认购买是否合法。

敏感数据和逻辑的特殊情况,应在 后端是购买验证。用户制作完一个 购买,您应该执行以下操作:

  • 将相应的PurchaseToken发送到您的后端。这意味着您应保留所有记录的所有purchaseToken值 购买。
  • 验证当前购买的purchaseToken值与任何先前的purchaseToken值都不匹配。 PurchaseToken在全球范围内 唯一,因此您可以安全地将此值用作您的主键 数据库。
  • 使用Google Play开发者API中的Purchases.products:get或Purchases.subscriptions:get端点与Google进行验证 购买是合法的。
  • 如果购买的商品是合法商品,并且过去从未使用过,则可以安全地授予应用内商品或订阅的权利。
  • 对于订阅,在Purchases.subscriptions:get中设置linkedPurchaseToken时,还应删除 从您的数据库中链接了PurchaseToken,并撤销了 被授予linkedPurchaseToken以确保多个用户 没有资格进行相同的购买。

因此,您仅应在全部三个完成后才能解锁内容。

  • onPurchaseUpdated,最初了解购买已完成。
  • onAcknowledgePurchaseResponse,因此您知道确认已完成,并且购买交易不会自动退款
  • 您需要通过后端服务器验证购买是否合法。

完成这三个步骤后,就可以安全地解锁您的购买了。如果您不选择这三个选项,则存在解锁已退还或非法购买的内容的风险。

答案 1 :(得分:0)

购买后无法购买InApp产品。我们需要在 成功购买,以便我们可以再次购买,它将可供 下次我们购买与之前购买的产品相同的产品。

您必须确认所有非消耗性的购买,即必须确认订阅。这是参考代码,或者您

            /**
             * If you do not acknowledge a purchase, the Google Play Store will provide a refund to the
             * users within a few days of the transaction. Therefore you have to implement
             * [BillingClient.acknowledgePurchaseAsync] inside your app.
             *
             * @param purchase list of Purchase Details returned from the queries.
             */
            private fun acknowledgeNonConsumablePurchasesAsync(purchase: Purchase) {
                val acknowledgePurchaseRunnable = Runnable {
                    val params = AcknowledgePurchaseParams.newBuilder()
                        .setPurchaseToken(purchase.purchaseToken)
                        .build()
                    myBillingClient.acknowledgePurchase(
                        params
                    ) { billingResult: BillingResult ->
                        if (billingResult.responseCode == BillingResponseCode.OK) {
                            LogUtils.d(TAG, "onAcknowledgePurchaseResponse: " + billingResult.responseCode)
                        } else {
                            LogUtils.d(TAG, ("onAcknowledgePurchaseResponse: " + billingResult.debugMessage))
                        }
                    }
                }
            }

对于消耗品,应该这样做

 /**
     * Consumes InApp Product Purchase after successful purchase of InApp Product Purchase. InApp
     * Products cannot be bought after a purchase was made. We need to consume it after a
     * successful purchase, so that we can purchase again and it will become available for the
     * next time we make purchase of the same product that was bought before.
     *
     * @param purchase the purchase result contains Purchase Details.
     */
val onConsumeListener =
            ConsumeResponseListener { billingResult: BillingResult, purchaseToken: String ->
                // If billing service was disconnected, we try to reconnect 1 time
                // (feel free to introduce your retry policy here).
                if (billingResult.responseCode == BillingResponseCode.OK) {
                    LogUtils.d(TAG, "onConsumeResponse, Purchase Token: $purchaseToken")
                } else {
                    LogUtils.d(TAG, "onConsumeResponse: " + billingResult.debugMessage)
                }
            }
        // Creating a runnable from the request to use it inside our connection retry policy below
        val consumeRequest = Runnable {

            // Consume the purchase async
            val consumeParams = ConsumeParams.newBuilder()
                .setPurchaseToken(purchase.purchaseToken)
                .build()
            myBillingClient!!.consumeAsync(consumeParams, onConsumeListener)
        }
相关问题