React-native-iap: Fehler beim Upgrade / Downgrade-Abonnement unter Android mit DEFERRED-Modus

Erstellt am 28. Dez. 2019  ·  31Kommentare  ·  Quelle: dooboolab/react-native-iap

Version von react-native-iap

4.3.3

Version von React-Native

0,59,10

Plattformen, auf denen Sie den Fehler hatten (IOS oder Android oder beides?)

Android

Erwartetes Verhalten

Beim Upgrade / Downgrade eines Abonnements im DEFERRED-Modus sollte der Listener für den Kaufupdate mit neuem Transaktionsbeleg aufgerufen werden.

Tatsächliches Verhalten

Kauffehler Listener wird mit folgendem Fehler aufgerufen:

{message: 'Einkäufe sind null.',
Code: 'OK',
debugMessage: '',
responseCode: 0}

Getestete Umgebung (Emulator? Reales Gerät?)

Echtes Gerät - Sandbox

Schritte zum Reproduzieren des Verhaltens

1. Kaufen Sie ein Abonnement mit RNIap.requestSubscription (sku), dies funktioniert korrekt.

2.Upgrade oder Downgrade des Abonnements mit RNIap.requestSubscription (newSku, false, sku, 4). (4 ist der VERZÖGERTE Proration-Modus.) Der Google Play-Abrechnungsdialog zeigt an, dass das Abonnement erfolgreich geändert wurde, und Sie erhalten eine Benachrichtigungs-E-Mail von Google Play darüber. Der Fehlerlistener wird jedoch mit dem oben genannten Fehler aufgerufen.

3.Wenn Sie RNIap.requestSubscription (newSku, false, sku, 4) erneut aufrufen, wird im Google Play-Abrechnungsdialog angezeigt, dass das Abonnement nicht geändert werden kann, und der Fehlerlistener wird mit dem folgenden Fehler aufgerufen:

{message: 'Google zeigt an, dass wir ein Problem mit der Zahlung haben.',
Code: 'E_DEVELOPER_ERROR',
debugMessage: '',
Antwortcode: 5}

Manchmal sagt der Google Play-Abrechnungsdialog jedoch, dass Ihre Bestellung in Bearbeitung ist und Ihr Produkt bald geliefert werden sollte. Der Fehler-Listener wird mit dem folgenden Fehler aufgerufen:

{message: 'Du besitzt diesen Gegenstand bereits.',
Code: 'E_ALREADY_OWNED',
debugMessage: '',
Antwortcode: 7}

Ich denke, dies liegt an der Transaktion von Schritt 2, die darauf wartet, bestätigt zu werden. Da Schritt 2 jedoch keine Quittung zurücksendet, können wir diese nicht bestätigen.

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

Hilfreichster Kommentar

Haben Sie Pläne, dieses Problem zu beheben?

Alle 31 Kommentare

Versuchen Sie, getAvailablePurchases anzurufen, nachdem Sie das Upgrade / Downgrade-Abonnement abgeschlossen haben.
Siehe Dokument The list of Purchase objects in onPurchasesUpdated() does not contain paused subscriptions. .

Ich bin mir nicht ganz sicher, ob es hilft. Bitte zögern Sie nicht, andere Versuche und Diskussionen zu hinterlassen.

Ich habe getAvailablePurchases () nach dem Upgrade / Downgrade des Abonnements ausprobiert, aber leider befindet sich nur der Transaktionsbeleg des ursprünglichen Kaufs im zurückgegebenen Array.

RNIap v2.3.19 & v2.5.5 funktioniert ordnungsgemäß. BuySubscription () gibt beim Upgrade / Downgrade des Abonnements eine neue Quittung zurück. Ich möchte jedoch auf v3 oder v4 upgraden, die nach Möglichkeit ein besseres ereignisbasiertes Modell haben.

In diesem Referenzdokument wird erläutert, wie das Upgrade / Downgrade von Android-Abonnements funktioniert und warum wir den neuen Beleg nach dem Upgrade / Downgrade benötigen.

@ howg0924 Danke, dass hast . Ich möchte die Unterschiede mit v2 und unserer aktuellen Version vergleichen und sehen, wie ich dieses Problem beheben kann.

Ich habe den Code am Wochenende für Sie in # 893 nachgeschlagen
Das neue Update wird in 4.4.0 .

Könnten Sie bitte die Version [email protected] testen?

@hyochan Ich habe gerade 4.4.0-rc.1 ausprobiert, aber die Situation ist immer noch dieselbe.

Nach dem Aufruf von RNIap.requestSubscription (oldSku, false, newSku 4) und dem Abschluss des Upgrades / Downgrades wird der Fehlerlistener mit folgendem Fehler aufgerufen:

{message: 'Einkäufe sind null.',
Code: 'OK',
debugMessage: '',
responseCode: 0}

Und getAvailablePurchases () enthält nur alte Quittungen.

@ howg0924 Wenn Sie wissen, wie man android debuggt , hoffe ich, dass Sie testen, wie Sie einige Log.d und sehen, ob es if Bedingungen in buyItemByType erfüllt. Wäre das für dich möglich? Ich möchte sehen, wie sie ausgeführt werden.

@ howg0924 Oh warte ~! Ich glaube, ich habe das Problem gefunden. Lassen Sie mich bald auf Sie zurückkommen!

@ howg0924 Könnten Sie 4.4.0-rc.2 versuchen? Ich denke, diesmal wird es funktionieren.

@hyochan 4.4.0-rc.2 Build fehlgeschlagen am:

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

@hyochan Ich habe buyItemByType () von 4.4.0-rc.1 überwacht. Beim Upgrade / Downgrade wurde Folgendes ausgeführt:

builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.DEFERRED);

und auch ausgeführt:

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

Soll ich einen Fluss / Daten überwachen / sichern?

(aufgrund eines Missverständnisses entfernt)

@ howg0924 Entschuldigung, dass ich einen Fehler gemacht habe, weil ich kein gutes Debugging hatte env . Ich habe dies in 4.4.0-rc.3 . Es sieht so aus, als würde auf Ihrem Code nicht builder.setOldSku(oldSku) was am wichtigsten ist.

Nach dem Vergleich mit 2.5.5 habe ich festgestellt, dass 2.5.5 nicht anruft

builder.setReplaceSkusProrationMode (BillingFlowParams.ProrationMode.DEFERRED);

bei Verwendung des DEFERRED-Modus.

Also versuche ich diese Zeile auf 4.4.0-rc.1 zu entfernen und es funktioniert! Aber ich weiß nicht:

1. In welchem ​​Prorationsmodus wird gerade gearbeitet?
2. Warum funktioniert es nicht, wenn es von setReplaceSkusProrationMode () in den DEFERRED-Modus versetzt wird?

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

Wir geben derzeit die ProrationMode wie oben weiter. Bedeutet das also, dass Sie auto renew subscription wenn Sie DEFERRED ?

Ich meine, wenn ich den Code ändere in:

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

dann kann ich RNIap.requestSubscription (newSku, false, sku, 4 / * DEFERRED-Modus * /) verwenden, um ein Abonnement zu aktualisieren / herunterzustufen. Obwohl ich nicht sicher bin, in welchem ​​Prorationsmodus es tatsächlich funktioniert, da builder.setReplaceSkusProrationMode () nicht wie in Version 2.5.5 ausgeführt wird.

Der folgende Code stammt aus Version 2.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 Nun, das ist sehr seltsam, da wir in unserer aktuellen Hauptniederlassung, die 4.3.4 ist, nicht einmal DEFFERED 4.3.4 . Ich habe diesen Code in 4.4.0+ hinzugefügt.

Ich denke, der Grund könnte etwas anderes sein. Ich hoffe, Sie können wiederkommen, wenn es andere Neuigkeiten gibt.

Verwandte # 391 # 555

OK, ich werde mehr versuchen und berichten.

Verwandte # 707

@hyochan Nach weiterem Test am 4.4.0-rc.1:

IMMEDIATE_WITH_TIME_PRORATION => funktioniert
IMMEDIATE_AND_CHARGE_PRORATED_PRICE => funktioniert
IMMEDIATE_WITHOUT_PRORATION => funktioniert
DEFERRED => NICHT ARBEITEN (weiß nicht warum)

Nun, das ist sehr seltsam, da wir in unserem aktuellen Hauptzweig, der 4.3.4 ist, nicht einmal DEFFERED eingestellt haben. Ich habe diesen Code in 4.4.0+ hinzugefügt.

Ich glaube, das liegt daran, dass der folgende Code in 4.3.0 ihn immer noch in den DEFERRED-Modus versetzt hat:

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

Der obige Code ist jedoch in 2.3.19 und 2.5.5 nicht vorhanden. Als ich RNIap.requestSubscription (newSku, false, sku, 4 / * DEFERRED * /) unter 2.3.19 und 2.5.5 aufrief, dachte ich, dass es früher funktioniert hat, aber jetzt wurde mir klar, dass es tatsächlich im Standardmodus IMMEDIATE_WITH_TIME_PRORATION funktioniert.

Ok, wir sollten wissen, warum der Deffered nicht funktioniert. Ich konnte den Grund für jetzt nicht finden.

Ich habe das gleiche Problem, aber das Verhalten ist anders.

Wenn ich requestSubscription(newSku, false, oldSku, 4) aufrufe, wird ein Fehler mit dem Fehlercode OK und einer leeren Fehlermeldung ausgegeben. Die Zahlung auf der Google Play-Seite erfolgt wie erwartet (sie wird zurückgestellt). Wenn die nächste Abonnementgebühr anfällt, erhalte ich beim Start der App ein Ereignis von purchaseUpdatedListener , kann den Kauf jedoch nicht bestätigen (indem ich finishTransaction() ). finishTransaction() gibt einen DEVELOPER_ERROR Fehler aus.

Passiert für beide Versionen 4.4.0 und 4.3.4 .

Hallo @hyochan , ich habe gesehen, dass Sie dies in https://github.com/dooboolab/react-native-iap/pull/893 als behoben markiert haben, aber ich habe react-native-iap auf die neueste Version aktualisiert, aber diese ist es immer noch nicht Fest. Ich habe immer noch einen Fehler im Listener error {"code": "OK", "debugMessage": "", "message": "purchases are null.", "responseCode": 0} und habe die E-Mail You updated your subscription purchase normal erhalten. Meine Frage ist also, was ist die richtige Lösung für den DEFERRED-Modus?

Das letzte Mal habe ich dieses Problem auch gefunden. Es funktioniert seltsamerweise nicht nur im deferred -Modus. Wir müssen das untersuchen.

Hallo @ howg0924 , hast du schon eine Lösung für dieses Problem bekommen?

@ nenjamin2405 Nein, ich verwende immer noch den Standardmodus IMMEDIATE_WITH_TIME_PRORATION und hoffe wirklich, dass dies behoben werden kann.

Hallo @hyochan , irgendein Update dazu? Die neue Funktion meiner App bleibt von diesem Problem betroffen. Vielen Dank für Ihre Bemühungen, dies zu untersuchen, danke

Noch nicht. Ich hatte keine Zeit, mich mit diesem Thema zu befassen.
Ich hoffe, jemand bringt auch nützliche Informationen zur Lösung dieses Problems.
Wenn Sie Google oder StackOverflow fragen und dies in diesem Thread mitteilen, kann dies sehr hilfreich sein.

Hey, es sieht so aus, als ob in letzter Zeit keine Aktivitäten zu diesem Thema stattgefunden haben. Wurde das Problem behoben oder erfordert es immer noch die Aufmerksamkeit der Community? Dieses Problem kann geschlossen werden, wenn keine weitere Aktivität auftritt. Sie können diese Ausgabe auch als "Zur Diskussion" oder "Gute erste Ausgabe" bezeichnen, und ich werde sie offen lassen. Vielen Dank für Ihre Beiträge.

Wir haben uns dieses Problem angesehen und wollten es mit der Community teilen. Es kann einigen Leuten da draußen helfen.

Das Problem ist darauf zurückzuführen, dass der vom Kauf aktualisierte Listener mit einer leeren Liste der Käufe für ein aufgeschobenes Abonnement aufgerufen wird. So funktioniert Android (siehe hier "Für den aufgeschobenen Ersatzmodus ...").

Wir haben die Unterstützung von Android Deferred Subscription Replace auf React-Native-Iaphub hinzugefügt, indem wir einen Fix durchgeführt haben, der untersucht, wann der Fehler-Listener mit dem Fehler purchases are null bei einem Abonnement -Replace aufgerufen wird. ( Siehe Festschreiben )

Natürlich müssen Sie auch auf Ihrer Serverseite einige Änderungen vornehmen, um Ihre Belege zu validieren. Das Aktualisieren des Belegs reicht nicht aus, wenn Sie mit zurückgestellten Abonnements arbeiten.
Sie müssen die Android-Echtzeitbenachrichtigungen implementieren, um zu erkennen, wann das Abonnement ersetzt wird, und ein neues Token verarbeiten.

Oder Sie können einfach IAPHUB verwenden, das all das für Sie erledigt 🙂

Haben Sie Pläne, dieses Problem zu beheben?

Wie @iaphub erwähnt, besteht das Problem darin, dass onPurchasesUpdated mit dem Argument purchases als null aufgerufen wird, wenn der DEFERRED-Modus verwendet wird.

Aus Google Docs :

Für den verzögerten Ersetzungsmodus erhält Ihre App einen Anruf an Ihren PurchasesUpdatedListener mit einer leeren Liste der Käufe und dem Status, ob das Upgrade oder Downgrade erfolgreich war.

Es geht also nur darum, diesen Fall in diesem Hörer zu behandeln.

Ich bin mir jedoch nicht sicher, wie ich mit dieser Situation richtig umgehen soll:

  • Lösen Sie das Versprechen mit den vorherigen Abonnementinformationen
  • Das Versprechen mit undefined lösen
  • Das Versprechen mit einem PURCHASE_DEFERRED Code ablehnen

Was denkst du?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen