检测已退款的应用程序内管理购买android IAP 2.0.3

检测已退款的应用程序内管理购买android IAP 2.0.3,android,in-app-purchase,Android,In App Purchase,我不知道如何使用com.Android.billingclient:billing:2.0.3检测Android中的托管(不可消费)应用程序内产品何时退款。这个问题似乎相当深,尽管我可能把它弄得比应该的更复杂 首先,我做了一个测试购买,已经确认并退款: 查看我的应用程序日志,我看到以下内容: D/BillingManager: Got a verified purchase: Purchase. Json: {"orderId":"GPA.3362-7185-5389-78416","pack

我不知道如何使用
com.Android.billingclient:billing:2.0.3
检测Android中的托管(不可消费)应用程序内产品何时退款。这个问题似乎相当深,尽管我可能把它弄得比应该的更复杂

首先,我做了一个测试购买,已经确认并退款:

查看我的应用程序日志,我看到以下内容:

D/BillingManager: Got a verified purchase: Purchase. Json: {"orderId":"GPA.3362-7185-5389-78416","packageName":"com.glan.input","productId":"pro","purchaseTime":1567672759460,"purchaseState":0,"purchaseToken":"pbkpcaadklleoecegjfjdpbl.AO-J1OwsR6WVaVZCCYOU6JyYN1r0qJsrwitIPZfhc3jX4yketRUwNzKqwMgYx0TgZ2GebEGbXDL0RlMyogwtSKSPsaHCJ4RA4MPlIGay-aM1-QhmnqwjXjQ","acknowledged":true}
I/BillingManager: purchase pbkpcaadklleoecegjfjdpbl.AO-J1OwsR6WVaVZCCYOU6JyYN1r0qJsrwitIPZfhc3jX4yketRUwNzKqwMgYx0TgZ2GebEGbXDL0RlMyogwtSKSPsaHCJ4RA4MPlIGay-aM1-QhmnqwjXjQ is in 1 state
  public @PurchaseState int getPurchaseState() {
    switch (mParsedJson.optInt("purchaseState", PurchaseState.PURCHASED)) {
      case 4:
        return PurchaseState.PENDING;
      default:
        return PurchaseState.PURCHASED;
    }
  }
这里发生了一些有趣的事情:

  • 我们可以看到订单ID与图像中的内容和检测到的购买匹配
  • 第一行日志是打印带有
    log.d的采购(标记“gotaverifiedpurchase:”+purchase)
    正在打印表示
    购买的基本JSON
  • 请注意
    “purchaseState”:0
  • 第二个日志行发布了log.i(标记“purchase”+purchase.getPurchaseToken()+”处于“+purchase.getPurchaseState()+”状态)
  • 请注意,这里的
    purchase.getPurchaseState()
    产生的值为
    1
  • 如果我在Android Studio中查看
    getPurchaseState
    的实现,我会看到以下内容:

    D/BillingManager: Got a verified purchase: Purchase. Json: {"orderId":"GPA.3362-7185-5389-78416","packageName":"com.glan.input","productId":"pro","purchaseTime":1567672759460,"purchaseState":0,"purchaseToken":"pbkpcaadklleoecegjfjdpbl.AO-J1OwsR6WVaVZCCYOU6JyYN1r0qJsrwitIPZfhc3jX4yketRUwNzKqwMgYx0TgZ2GebEGbXDL0RlMyogwtSKSPsaHCJ4RA4MPlIGay-aM1-QhmnqwjXjQ","acknowledged":true}
    I/BillingManager: purchase pbkpcaadklleoecegjfjdpbl.AO-J1OwsR6WVaVZCCYOU6JyYN1r0qJsrwitIPZfhc3jX4yketRUwNzKqwMgYx0TgZ2GebEGbXDL0RlMyogwtSKSPsaHCJ4RA4MPlIGay-aM1-QhmnqwjXjQ is in 1 state
    
      public @PurchaseState int getPurchaseState() {
        switch (mParsedJson.optInt("purchaseState", PurchaseState.PURCHASED)) {
          case 4:
            return PurchaseState.PENDING;
          default:
            return PurchaseState.PURCHASED;
        }
      }
    
    文件前面的
    PurchaseState
    接口声明为:

      @Retention(SOURCE)
      public @interface PurchaseState {
        // Purchase with unknown state.
        int UNSPECIFIED_STATE = 0;
        // Purchase is completed.
        int PURCHASED = 1;
        // Purchase is waiting for payment completion.
        int PENDING = 2;
      }
    
    似乎
    getPurchaseState
    从不返回
    PurchaseState.UNSPECIFIED_STATE
    ,只返回JSON值为
    4
    PENDING
    。我已经确认,当使用需要一段时间才能批准的付款方式执行购买时,正确返回了
    待定
    状态

    我发现类似这样的帖子表明Play服务正在缓存购买,但我不认为这是导致此问题的原因,因为如果我在应用程序运行之间修改代码以确认/消费购买,那么这些获取状态更改将立即反映在购买的JSON中


    我应该如何检测已退款的托管产品

    您可以检查以下是否仍存在购买

     binding.btnRestore.setOnClickListener(v->{
    
    
                Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
                for ( Purchase purchase : purchasesResult.getPurchasesList()){
                    handlePurchase(purchase);
    
                }
    });
    
    Google Play返回登录到设备的用户帐户所购买的内容。如果请求成功,Play Billing Library将查询结果存储在购买对象列表中

    注意:此列表上仅显示活动订阅。只要应用内产品在此列表中,用户就应该有权访问它。有关更多信息,请参阅“添加订阅特定功能”的“句柄”子选项“保留”部分。 要检索列表,请对PurchasesResult调用getPurchasesList()。然后,您可以调用Purchase对象上的各种方法来查看有关该项目的相关信息,例如其购买状态或时间。要查看可用的产品详细信息类型,请参阅Purchase类中的方法列表

    您应该在代码中至少调用queryPurchases()两次:

    每次应用启动时调用queryPurchases(),以便您可以恢复自应用上次停止以来用户所做的任何购买。 在onResume()方法中调用queryPurchases(),因为用户可以在应用程序处于后台时进行购买(例如,在Google Play Store应用程序中兑换促销代码)。 在启动和恢复时调用queryPurchases()可以确保您的应用程序了解用户在应用程序未运行时可能进行的所有购买和赎回。此外,如果用户在应用程序运行时进行了购买,而您的应用程序由于任何原因错过了购买,那么您的应用程序在下次活动恢复并调用queryPurchases()时仍会发现有关购买的信息

    查询最近购买的商品 queryPurchases()方法使用Google Play Store应用程序的缓存,而无需启动网络请求。如果需要检查用户对每个产品ID的最新购买,可以使用queryPurchaseHistoryAsync(),传递购买类型和PurchaseHistoryResponseListener来处理查询结果

    queryPurchaseHistoryAsync()返回一个PurchaseHistory对象,该对象包含用户对每个产品ID最近购买的信息,即使该购买已过期、取消或已消费。尽可能使用queryPurchases(),因为它使用本地缓存,而不是queryPurchaseHistoryAsync()。如果使用queryPurchaseHistoryAsync(),还可以将其与刷新按钮结合使用,使用户可以更新其购买列表

    以下代码演示了如何重写onPurchaseHistoryResponse()方法:

    我的应用程序中有一次购买(SkuType.INAPP)。我试着购买,然后退款

    问题:

    purchase.getOriginalJson()  // contains "purchaseState":0
    purchase.getPurchaseState() // returns 1
    
    public int getPurchaseState() {
        switch(this.zzc.optInt("purchaseState", 1)) {
        case 4:
            return 2;
        default:
            return 1;
        }
    }
    //...
    public @interface PurchaseState {
        int UNSPECIFIED_STATE = 0;
        int PURCHASED = 1;
        int PENDING = 2;
    }
    
    purchase.getOriginalJson().contains(String.format("\"purchaseState\":%s", Purchase.PurchaseState.PURCHASED))
    
    内置com.android.billingclient.api.Purchase:

    purchase.getOriginalJson()  // contains "purchaseState":0
    purchase.getPurchaseState() // returns 1
    
    public int getPurchaseState() {
        switch(this.zzc.optInt("purchaseState", 1)) {
        case 4:
            return 2;
        default:
            return 1;
        }
    }
    //...
    public @interface PurchaseState {
        int UNSPECIFIED_STATE = 0;
        int PURCHASED = 1;
        int PENDING = 2;
    }
    
    purchase.getOriginalJson().contains(String.format("\"purchaseState\":%s", Purchase.PurchaseState.PURCHASED))
    
    从原始json检查purchaseState的黑客方法:

    purchase.getOriginalJson()  // contains "purchaseState":0
    purchase.getPurchaseState() // returns 1
    
    public int getPurchaseState() {
        switch(this.zzc.optInt("purchaseState", 1)) {
        case 4:
            return 2;
        default:
            return 1;
        }
    }
    //...
    public @interface PurchaseState {
        int UNSPECIFIED_STATE = 0;
        int PURCHASED = 1;
        int PENDING = 2;
    }
    
    purchase.getOriginalJson().contains(String.format("\"purchaseState\":%s", Purchase.PurchaseState.PURCHASED))
    
    不幸的是,这个问题仍然存在


    更多详细信息。

    queryPurchases()的一个注释。我认为“此列表上仅显示活动订阅”目前不正确。我在原始json中看到“purchaseState”已取消订阅:0。看起来就像这里说的那样,这是一个不确定的状态。Google Play应用程序上的订阅中不再存在此订阅,我收到的电子邮件已被取消。我还尝试同步数据并等待,但没有任何更改。好的,这是可行的,但当我在退款后再次尝试购买INAPP时,它会使我
    无法购买商品,错误响应代码:7
    该代码是针对已拥有的商品的。这不可行work@MakinTosH这是真的。这是一个至今仍然存在的已知错误。看看这里有多少评论:你解决这个问题了吗?看起来还是一样。。