17

我正在尝试在我的应用程序中实施应用程序内计费,除了退款之外,一切都很好。在过去的几天里,我一直在反对这一点,如果用户要求退款,似乎无法从应用程序方面知道。我希望能够在用户获得退款后撤销对一次性托管产品(删除广告)的访问权限。我没有使用后端,所以我依赖 Google Play API。

我尝试的是查询 Google Play API,queryPurchaseHistoryAsync它会返回用户最近购买的列表。这似乎不起作用,因为在要求退款后购买仍然存在(在写这篇文章之前已经等待了一天)。

这是我所做的:

  1. 在真实设备上安装应用程序
  2. 购买应用内内容
  3. 验证应用是否解锁了内容
  4. 转到我的 Google Play 订单历史记录并为应用内商品申请退款
  5. 10 分钟后,交易被退回(完全没有我作为开发人员参与)
  6. 应用仍然提供付费内容
  7. 清理 Play 商店应用数据和缓存
  8. 应用仍然提供付费内容

所以任何用户都可以购买我的应用内产品,然后立即转到他的 Google Play 页面并要求退款?是我遗漏了一些明显的东西还是这个 API 是一场噩梦?

PurchaseState枚举是

  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;
  }

我在这里没有看到任何与退款相关的内容,在我看来这是一个非常正常的用例,所以我仍然认为我缺少一些关键信息,我该怎么做?

谢谢你的帮助

4

1 回答 1

7

问题

即使用户进行了退款并实际获得了退款,任何进行的购买仍将被记录。当您(开发者/应用所有者)为应用内产品发出退款/撤销请求时也是如此。

唯一的区别是购买的"purchaseState"。Google 的计费库的问题在于,它们将 purchase.getPurchaseState() 调用中的“purchaseState”值屏蔽为PENDNGPURCHASED状态。见反编译代码:

public int getPurchaseState() {
    switch(this.zzc.optInt("purchaseState", 1)) {
    case 4:
        return 2; // PENDING
    default:
        return 1; // PURCHASED
    }
}

当您有一个具有退款状态的应用内产品时,它的状态相当 UNSPECIFIED_STATE,如上面的代码中一样,它被屏蔽为 PURCHASED 。

简单的解决方案

要克服这个问题,只需忽略库的 purchase.getPurchaseState() 方法,而是使用您自己的未屏蔽自定义:

int getUnmaskedPurchaseState(Purchase purchase) {
    int purchaseState = purchase.getPurchaseState();
    try {
        purchaseState = new JSONObject(purchase.getOriginalJson()).optInt("purchaseState", 0);
    } catch (JSONException e) {
        e.printStackTrace();
    }

    return purchaseState;
}

硬解

谷歌似乎刚刚做了这件事,以推动您执行此解决方案。使用 Voided Purchases API提供与用户已作废的购买相关的订单列表。根据他们的文件...

可以通过以下方式取消购买:

  • 用户要求为他们的订单退款。用户取消他们的订单。
  • 订单被退回。
  • 开发商取消或退款订单。注意:只有撤销的订单才会显示在 Voided Purchases API 中。
  • 如果开发者在未设置撤销选项的情况下退款,订单将不会显示在 API 中。
  • Google 取消或退款订单。

但是,此解决方案目前不能作为 Java android 库提供,您必须改为发出服务器请求,并使用 Google Play 开发人员 API。

于 2020-08-17T13:11:05.047 回答