React-native-iap: 在具有DEFERRED模式的Android上升级/降级订阅时出错

创建于 2019-12-28  ·  31评论  ·  资料来源: dooboolab/react-native-iap

版本的react-native-iap

4.3.3

本机版本

0.59.10

您遇到错误的平台(IOS或Android还是两者兼有?)

安卓系统

预期行为

在使用DEFERRED模式升级/降级订阅时,应使用新的交易收据来调用购买更新侦听器。

实际行为

购买错误侦听器被调用,并显示以下错误:

{消息:“购买为空。”,
代码:“确定”,
debugMessage:“,
responseCode:0}

经过测试的环境(仿真器?真实设备?)

真实设备-沙箱

重现行为的步骤

1.使用RNIap.requestSubscription(sku)购买订阅,此订阅可以正常运行。

2.使用RNIap.requestSubscription(newSku,false,sku,4)升级或降级订阅。 (4为延期按比例分配模式)Google Play结算对话框将显示订阅计划已成功更改,并且您将收到来自Google Play的通知电子邮件。 但是,将使用上述错误调用错误侦听器。

3.如果再次调用RNIap.requestSubscription(newSku,false,sku,4),则Google Play结算对话框会说他们无法更改订阅计划,并且错误监听器被调用,并显示以下错误:

{消息:“ Google表示我们在付款方面存在问题。”,
代码:“ E_DEVELOPER_ERROR”,
debugMessage:“,
responseCode:5}

但是有时Google Play的“结算”对话框会说您的订单正在处理中,您的产品应尽快交付,并且错误监听器会被调用,并显示以下错误:

{消息:“您已经拥有此项目。”,
代码:“ E_ALREADY_OWNED”,
debugMessage:“,
responseCode:7}

我猜这是由于第2步的事务正在等待确认。 但是,由于第2步未返回收据,因此我们无法对其进行确认。

🕵️‍♂️ need more investigation 🙏 help wanted 🤖 android

最有用的评论

有解决此问题的计划吗?

所有31条评论

升级/降级订阅后,尝试致电getAvailablePurchases
请参阅doc The list of Purchase objects in onPurchasesUpdated() does not contain paused subscriptions.

我不太确定希望有帮助。 请随时离开其他任何尝试和讨论。

在升级/降级订阅后,我尝试了getAvailablePurchases(),但是不幸的是,只有原始购买的交易收据才在返回的数组中。

RNIap v2.3.19和v2.5.5正常工作,在升级/降级订阅时,buySubscription()将返回新的收据。 但是我想升级到v3或v4,如果可能的话,它具有更好的基于事件的模型。

这是一份参考文档,解释了Android订阅升级/降级的工作方式以及为什么在升级/降级后我们需要新的收据。

@ howg0924感谢您确认。 我想比较与v2和当前版本的差异,并查看如何解决此问题。

我在周末为您在#893中查找了代码
新的更新将在4.4.0

您能测试一下[email protected]版本吗?

@hyochan我刚刚尝试了4.4.0-rc.1,但情况仍然相同。

调用RNIap.requestSubscription(oldSku,false,newSku 4)并完成升级/降级后,将调用错误侦听器,并显示以下错误:

{消息:“购买为空。”,
代码:“确定”,
debugMessage:“,
responseCode:0}

而且getAvailablePurchases()仅包含旧收据。

@ howg0924如果你知道如何调试android ,我希望你能够测试出把一些Log.d ,看看它是否通过if的条件buyItemByType 。 那对你有可能吗? 我想看看它们是如何执行的。

@ howg0924哦,等等〜! 我想我发现了问题,让我尽快与您联系!

@ howg0924您可以尝试4.4.0-rc.2吗? 我认为这次可以。

@hyochan 4.4.0-rc.2构建失败于:

RNIapModule.java:436: error: incompatible types: SkuDetails cannot be converted to String:
   builder.setOldSku(selectedOldSku);
                     ^

@hyochan我监视了4.4.0-rc.1。的buyItemByType()。 升级/降级时,它确实执行:

builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.DEFERRED);

并执行:

BillingResult billingResult = billingClient.launchBillingFlow(activity, flowParams);

您要我监视/转储任何流/数据吗?

(由于误会而删除)

@ howg0924对不起,我犯错了,因为我没有很好的调试env 。 我已经在4.4.0-rc.3恢复了它。 看起来您的代码未运行builder.setOldSku(oldSku) ,这是最重要的。

与2.5.5比较之后,我发现2.5.5没有调用

builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.DEFERRED);

使用DEFERRED模式时。

因此,我尝试在4.4.0-rc.1上删除此行,并且可以正常工作! 但是,我不知道:

1.目前正在使用哪种按比例分配模式。
2.为什么在通过setReplaceSkusProrationMode()设置为DEFERRED模式时不起作用

        if (prorationMode != null && prorationMode != -1) {
          if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE) {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE);
            if (type.equals(BillingClient.SkuType.SUBS) == false) {
              String debugMessage = "IMMEDIATE_AND_CHARGE_PRORATED_PRICE for proration mode only works in subscription purchase.";
              WritableMap error = Arguments.createMap();
              error.putString("debugMessage", debugMessage);
              error.putString("code", PROMISE_BUY_ITEM);
              error.putString("message", debugMessage);
              sendEvent(reactContext, "purchase-error", error);
              promise.reject(PROMISE_BUY_ITEM, debugMessage);
              return;
            }
          } else if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION) {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION);
          } else if (prorationMode == BillingFlowParams.ProrationMode.DEFERRED) {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.DEFERRED);
          } else if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_WITH_TIME_PRORATION) {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITH_TIME_PRORATION);
          } else {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY);
          }
        }

我们目前正在如上所述传递ProrationMode 。 那么这是否意味着删除DEFERRED可以auto renew subscription DEFERRED吗?

我的意思是如果我将代码更改为:

        if (prorationMode != null && prorationMode != -1) {
          if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE) {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE);
            if (type.equals(BillingClient.SkuType.SUBS) == false) {
              String debugMessage = "IMMEDIATE_AND_CHARGE_PRORATED_PRICE for proration mode only works in subscription purchase.";
              WritableMap error = Arguments.createMap();
              error.putString("debugMessage", debugMessage);
              error.putString("code", PROMISE_BUY_ITEM);
              error.putString("message", debugMessage);
              sendEvent(reactContext, "purchase-error", error);
              promise.reject(PROMISE_BUY_ITEM, debugMessage);
              return;
            }
          } else if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION) {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION);
          } else if (prorationMode == BillingFlowParams.ProrationMode.DEFERRED) {
            // comment following line
            // builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.DEFERRED);
          } else if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_WITH_TIME_PRORATION) {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITH_TIME_PRORATION);
          } else {
            builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY);
          }
        }

那么我可以使用RNIap.requestSubscription(newSku,false,sku,4 / * DEFERRED模式* /)升级/降级订阅。 虽然我不知道它实际上适用于哪种按比例分配模式,因为没有像v2.5.5那样执行builder.setReplaceSkusProrationMode()。

以下代码来自v2.5.5:

        if (type.equals(BillingClient.SkuType.SUBS) && oldSku != null && !oldSku.isEmpty()) {
          // Subscription upgrade/downgrade
          if (prorationMode != null && prorationMode != 0) {
            builder.setOldSku(oldSku);
            if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE) {
              builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE);
            } else if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION) {
              builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION);
            } else {
              builder.addOldSku(oldSku);
            }
          } else {
            builder.addOldSku(oldSku);
          }
        }

@ howg0924嗯,这很奇怪,因为我们甚至没有在当前的master分支4.3.4设置DEFFERED 4.3.4 。 我已将此代码添加到4.4.0+

我认为原因可能有所不同。 如果有其他新闻,希望您能回来。

相关#391#555

好,我会尝试更多并报告。

相关#707

@hyochan在4.4.0-rc.1上进行进一步测试后:

IMMEDIATE_WITH_TIME_PRORATION =>有效
IMMEDIATE_AND_CHARGE_PRORATED_PRICE =>有效
IMMEDIATE_WITHOUT_PRORATION =>有效
延迟=>无效(不知道为什么)

好吧,这很奇怪,因为我们甚至没有在当前的master分支4.3.4中设置DEFFERED。 我在4.4.0+中添加了此代码。

我相信这是因为4.3.0中的

  if (prorationMode != 0 && prorationMode != -1) {
    builder.setReplaceSkusProrationMode(prorationMode);
  }

但是,以上代码在2.3.19和2.5.5中不存在。 因此,当我在2.3.19和2.5.5上调用RNIap.requestSubscription(newSku,false,sku,4 / * DEFERRED * /)时,我以为它可以工作,但是现在我意识到它实际上可以在默认的IMMEDIATE_WITH_TIME_PRORATION模式下工作。

好的,所以我们应该知道为什么Deffered无法使用。 我现在找不到原因。

我有相同的问题,但行为不同。

当我调用requestSubscription(newSku, false, oldSku, 4) ,它将引发错误,错误代码OK并且错误消息purchaseUpdatedListener事件,但无法确认购买(通过调用finishTransaction() )。 finishTransaction()给出DEVELOPER_ERROR错误。

4.4.04.3.4两个版本上都发生。

@hyochan ,我在https://github.com/dooboolab/react-native-iap/pull/893中看到您已将其标记为已解决,但我将react-native-iap更新为最新版本,但仍不能固定的。 侦听器error {"code": "OK", "debugMessage": "", "message": "purchases are null.", "responseCode": 0}仍然出现错误,并且通常收到电子邮件You updated your subscription purchase 。 所以我的问题是DEFERRED模式的正确解决方案是什么?

上次我也发现了这个问题。 奇怪的是,它仅在deferred模式下不起作用。 我们需要对此进行调查。

@ howg0924您好,您是否已解决此问题?

@ nenjamin2405不,我仍在使用默认的IMMEDIATE_WITH_TIME_PRORATION模式,我真的希望可以解决此问题。

@hyochan ,对此有任何更新吗? 我的应用程序的新功能受此问题困扰。 非常感谢您对此进行的调查,谢谢

还没。 我没有时间讨论这个问题。
我希望有人也能提供有用的信息来解决此问题。
询问GoogleStackOverflow并在此线程中分享可能会很有帮助。

嘿,看来这个问题最近没有任何活动。 问题是否已解决,还是仍然需要社区的关注? 如果没有其他活动,则可能已关闭此问题。 您也可以将此问题标记为“供讨论”或“良好的第一期”,我将其保留为开放状态。 感谢你的贡献。

我们一直在研究此问题,并希望与社区分享,这可能会帮助一些人。

问题是由于购买更新的侦听器被调用的,而该更新的监听器在递延订阅替换中显示为空购买列表,这就是Android的工作方式(请参见此处“递归替换模式...”)

我们通过做一个修复来查找错误侦听器在订阅替换中带有purchases are null错误时的调用,从而在react-native-iaphub上添加了android延迟订阅替换的支持。 (请参阅提交

当然,您还必须在服务器端进行一些修改以验证收据,在处理延迟订阅时,刷新收据是不够的。
您必须实现Android实时通知,才能检测到何时发生订阅替换并处理新令牌。

或者,您也可以使用IAPHUB来为您完成所有工作🙂

有解决此问题的计划吗?

正如@iaphub所提到的那样,问题在于使用DEFERRED模式时,调用purchases参数作为null来调用onPurchasesUpdated

谷歌文档

对于延迟的替换模式,您的应用程序会收到对PurchasesUpdatedListener的调用,其中包含购买的空列表以及升级或降级是否成功的状态。

因此,只需要在该侦听器中处理这种情况即可。

但是我不确定应该如何处理这种情况:

  • 使用先前的订阅信息解决承诺
  • undefined解决承诺
  • PURCHASE_DEFERRED代码拒绝承诺

你有什么感想?

此页面是否有帮助?
0 / 5 - 0 等级