25

我已经让 IAB v3 正常工作,并且能够购买托管项目。但是,为了继续开发和测试,我想退还购买的款项,以便再次尝试进行相同的购买。我登录了我的 Google Checkout 商家帐户并成功退款了购买。但是,应用程序仍然认为用户购买了该项目。我退款已经好几个星期了,所以这不是延迟问题。

基本上,在我的QueryInventoryFinishedListener实现中inventory.hasPurchase(SKU_REMOVE_ADS),即使在退款之后(SKU_REMOVE_ADS是我正在销售的商品的 SKU),也总是返回 true。我期待它在退款处理后返回错误。

如果您查看IAB 参考的“处理退款”部分,它表示您的应用需要监听 IN_APP_NOTIFY 消息。但是,IN_APP_NOTIFY 的文档特定于 v2 的应用内计费。它似乎不是 v3 中可用的东西,因为它在 v3 参考中的任何地方都没有提到,我也无法在他们用来演示 IAB v3的示例 TrivialDrive 应用程序中找到任何参考。

那么 IAB v3 是否支持退款/取消购买?有没有人尝试过并让它工作?

4

3 回答 3

37

就 Google Play 而言,消耗品和非消耗品之间确实没有区别;这种区别完全取决于您在应用程序中实现的内容。因此,即使您正在测试的 SKU 旨在为非消耗品(例如,永久高级升级),出于测试目的,您也可以将其视为消耗品并进行消费,以便再次购买。

一种方便的方法是在您的应用程序中设置一个临时测试菜单(例如,通过在测试期间将一个菜单项添加到您的应用程序的主选项菜单中),然后让该项目的处理程序调用您的 IabHelper 实例的 consumeAsync() 方法您想再次测试购买的 SKU。这将消耗该项目,从而使其立即可用于从您的设备回购。

当然,您仍然希望从 Google Checkout 退还购买的款项,这样您就不会花费自己的钱来测试您的应用程序。

我要补充一点,如果您使用此类静态值进行测试,consumeAsync() 似乎也可以很好地重置测试 SKU android.test.purchased。

关于更新购买状态以反映退款,我亲身经历过(其他开发人员发布了许多类似的报告),通过 Checkout 手动发起退款(例如,从 TrivialDrive 应用程序进行测试购买)需要几天才能得到结果更改产品的购买状态(更改为 INAPP_PURCHASE_STATE_REFUNDED)。

(知道苦难爱陪伴,一些额外的报告可以在这个讨论线程中找到:https: //plus.google.com/+AndroidDevelopers/posts/R8DKwZDsz5m

至少部分原因是由于 Google Play 在设备上缓存了购买数据。

根据我的经验,重新启动设备有时会导致 Google Play 从 GP 服务器刷新其缓存。因此,重新启动后也可能会检测到由于通过 Checkout 取消或退款订单而导致的更改。

这么长的周转期似乎对您没有好处,因为您不知道用户何时会重新启动。但是话又说回来,您知道每台设备最终都会重新启动,因此,如果您担心收到退款的用户最终应该被阻止使用退款的 IAB 产品,那么延迟几天可能无关紧要,只要它最终发生。

当然,请记住,缓存将在重新启动时刷新的概念是未记录的并且是轶事(到目前为止,就像相当多的 IAB3 和 TrivialDrive 行为一样)。民间传说,他们称之为。

触发更新的另一件事是用户尝试购买产品时。一旦启动购买,系统必须确保该产品尚未拥有,因此它会更新 Google Play 缓存。以我个人的经验,这种情况一直存在。但同样,这不是一个非常实用的检查退款的方法,因为这将涉及显示未出价的购买对话框,并且还会显示一条错误消息,告诉用户“您已经拥有它”(如果他们确实拥有它)。

这在哪里派上用场的情况是,当用户在她的一台设备上为 IAB 商品付款,然后尝试在另一台设备上访问该商品时,该设备与用于购买该商品的帐户相同。这种情况下的购买信息通常还没有被缓存。但是您可以在购买对话框中添加一点说明,如果该项目已被购买,尝试重新购买应该可以在当前设备上免费使用它。有时需要两次(用户发起的)购买尝试才能最终获得 IabHelper.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED 响应。是的,有点笨拙,但我认为从人的角度来看,它可以适当地突出显示消息和确认对话框的道歉措辞,告诉他们他们拥有该项目等 :-) )。

实际上,您可以看到 Google 可能不希望世界上每个 IAB 应用程序的每个实例在每次访问应用程序的购买数据时都访问其服务器特别是考虑到他们正在建议开发人员检查有哪些内容每次启动应用程序时购买。这也是您的应用程序的性能问题 - 这就是缓存的全部内容。所以你需要知道更新缓存的触发器,我还没有找到一个正式记录的地方(除了,我们假设,在代码中)。所以准备好把手伸到你面前,开始在黑暗中摸索吧。

有关 Google Play 缓冲的更多信息,请参阅此页面:

在什么情况下可以在客户端设备上使用应用内计费版本 3 服务器更改?

我会注意到,在您帖子的代码片段中,您调用的是 inventory.hasPurchase(SKU_REMOVE_ADS),但这只会告诉您购买是否在库存对象中返回的购买列表中;它不会告诉您该SKU 的购买状态。我知道这是 TrivialDrive 应用程序使用的方法,但该应用程序不处理退款和取消。要检测退款和取消的订单,您需要以下内容:

Purchase removeAdsPurchase = inventory.getPurchase(SKU_REMOVE_ADS);
if(removeAdsPurchase != null) {
  int purchaseStateForRemoveAds = removeAdsPurchase.getPurchaseState();
  if(purchaseStateForRemoveAds == 1) {
    //Do cancelled purchase stuff here
  }
  else if(purchaseStateForRemoveAds == 2) {
    //Do refunded purchase stuff here
  }
}

关于退款和取消订单的好消息是,AFAIK 两者都完全由开发商选择。因此,如果您发现获得这些的用户能够在此后很长一段时间内继续使用您的应用程序,并且如果您发现很多用户都在利用这一点,那么您可以决定是否要继续提供退款所有情况。我最好的猜测是这不会有问题。即使某些获得退款的用户在那之后可以使用您的应用程序一段时间,这看起来也没什么大不了的。

为了测试,您需要能够非常快速地重新尝试购买,并且使用 consumeAsync() 绝对适用于该目的。

于 2013-04-04T20:42:55.903 回答
0

我建议您在应用处于开发阶段时使用静态产品 ID。

现在确保您正在使用相同的 Gmail ID 测试应用程序并获得退款?为了测试退款方案,我认为您可以将android.test.refunded其用作产品 ID。

如果这不起作用,那么您可以在首次启动您的应用程序时首先在 google play 中检查购买的总商品可用商品,如果您在两个调用中获得相同的产品 ID(不应该是这种情况如果是这种情况,请将此错误报告给谷歌)然后进行 api 调用以制作与消费相同的项目。

于 2013-04-03T12:47:42.687 回答
0

自从发布这个问题以来,我注意到我需要打电话getPurchase(...).getPurchaseState()检查它的价值。可能的值为 0(已购买)、1(已取消)或 2(已退款)。</p>

但是,在我的情况下,即使该项目已退款,它仍然会重新调整 0(已购买)。我在此处发布此信息以防对其他人有所帮助。

于 2013-04-05T00:34:24.110 回答