React-native-iap: finishTransactionIOS / finishTransaction macht nichts für iOS

Erstellt am 19. Feb. 2020  ·  34Kommentare  ·  Quelle: dooboolab/react-native-iap

Version von react-native-iap

4.4.1

Version von React-Native

0,60,4

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

iOS

Erwartetes Verhalten

Wenn Sie finishTransactionIOS (purchaseId) oder finishTransaction (purchase) für ein Abonnement aufrufen, sollte die Transaktion abgeschlossen sein und beim nächsten Start nicht erneut an die App gesendet werden. Wenn es ein Problem damit gab, würde ich erwarten, dass etwas entweder an den Fehler-Listener oder in einem Versprechen von einer der finishTransaction-Funktionen zurückgegeben wird, nichts passiert.

Android scheint gut zu funktionieren.

Tatsächliches Verhalten

Die Transaktion wird bei jedem einzelnen Start ausgegeben, es sei denn, clearTransactionIOS wird aufgerufen, was andere Nebenwirkungen zu haben scheint.

Getestete Umgebung (Emulator? Reales Gerät?)

Echtes Gerät

Schritte zum Reproduzieren des Verhaltens

  • Erstellen Sie ein Abonnementprodukt.
  • Kaufen Sie das Abonnement
  • Simulieren Sie die Backend-Validierung
  • Rufen Sie für dieses Abonnement finishTransactionIOS oder finishTransaction auf. Hat keine Wirkung.

Ich habe diese Stapel auf verschiedene Arten ausprobiert, und absolut nichts scheint zu funktionieren, egal was ich tue, außer die Transaktionen zu löschen, wird der Kauf bei jedem Start erneut an die App gesendet. Irgendwelche Ideen, was los ist oder was ich möglicherweise falsch machen oder verstehen könnte?

ℹ needs more info 📱 iOS 🙏 help wanted 🚶🏻 stale

Hilfreichster Kommentar

@hyochan irgendein Update zu diesem Thema? Wir stecken schon seit einiger Zeit fest und können unsere App nicht veröffentlichen.

Alle 34 Kommentare

Ich habe das gleiche Problem.

Können Sie die ackResult teilen?

          try {
            const ackResult = await finishTransaction(purchase);
            console.log('ackResult', ackResult);
          } catch (ackErr) {
            console.warn('ackErr', ackErr);
          }

@ Hyochan
In meinem Fall:
ackResult undefined

@ Hyochan
In meinem Fall:
ackResult undefined

Hier gilt das gleiche

Auch in meinem Fall ist der zurückgegebene Wert undefiniert (echtes Gerät mit einem Sandbox-Benutzer).

Es sieht verwandt mit # 366 aus. Auch für ios finishTransaction wird nichts zurückgegeben.
Können Sie sich alle auf # 366 konzentrieren und zum Update zurückkehren?

Es sieht verwandt mit # 366 aus. Auch für ios finishTransaction wird nichts zurückgegeben.
Können Sie sich alle auf # 366 konzentrieren und zum Update zurückkehren?

Nur zur Klarstellung - da es bei # 366 um Tests geht, schlagen Sie vor, dass dies in der Produktion ohne die Notwendigkeit von clearTransactionIOS gut funktionieren sollte?

@hyochan Wenn ich die Debug-Konfiguration mit einem Sandbox-Konto

`` `tsx
useEffect (() => {
purchaseUpdateSubscription.current = purchaseUpdatedListener (
asynchron (Kauf: InAppPurchase | SubscriptionPurchase) => {
const quittung = purchase.transactionReceipt;
if (Quittung) {
Versuchen {
warte auf myBackendHandler ({
Nutzer,
Kauf,
});
const result = warte auf RNIap.finishTransaction (Kauf, falsch);
console.log ('Ergebnis', Ergebnis);
} catch (e) {
// MACHEN
}}
}}
}}
);
return () => {
if (purchaseUpdateSubscription.current) {
purchaseUpdateSubscription.current.remove ();
purchaseUpdateSubscription.current = null;
}}
};
}, []);
`` ``

Hey Team, danke für die harte Arbeit an dieser Bibliothek, es macht unser Leben wirklich einfacher. Ich kommentiere, weil dieses Problem nicht behoben wurde und ich nicht sehe, wie alte Transaktionen, die nicht gelöscht wurden, etwas mit # 366 zu tun haben.

Mein Anwendungsfall ist

  1. Benutzer 1 gewährt Kauf- und Prämienvorteile auf sein Konto.
  2. Benutzer 1 meldet sich ab
  3. Benutzer 2 meldet sich an

Erwartetes Ergebnis:

  • Transaktionen von Benutzer 1 werden nicht über den Kauf-Listener ausgegeben

Tatsächliche Ergebnis

  • Transaktionen von Benutzer 1 werden NICHT gelöscht und erneut ausgegeben. Obwohl sich ein neuer Benutzer angemeldet hat, führt dies zu fehlerhaften Daten.

Dies ist nur ein Beispiel dafür, warum es wichtig ist, diesem Thema Priorität einzuräumen. Vielen Dank für das Lesen dieses langen Kommentars ...

hier gilt das gleiche

Genau das gleiche Problem wie oben, es sieht so aus, als ob der Stapel überhaupt nicht gelöscht wird, selbst nachdem das Sandbox / iTunes-Konto getrennt, das Gerät neu gestartet und die App neu installiert wurde ..: /

Könnten Sie überprüfen, ob finishTransaction in der Datei RNIapIos.m wirklich nichts bewirkt?
Ich habe es gerade ausgecheckt und es beendet seine Transaktion korrekt.

Bitte überprüfen Sie die Methode clearTransaction oder finishTransactionWithIdentifier und versuchen Sie, alle Protokolle darin abzulegen. Versuchen Sie, die folgenden Codes zu finden.

RCT_EXPORT_METHOD(clearTransaction) {
    NSArray *pendingTrans = [[SKPaymentQueue defaultQueue] transactions];
    NSLog(@"\n\n\n  ***  clear remaining Transactions. Call this before make a new transaction   \n\n.");
    for (int k = 0; k < pendingTrans.count; k++) {
        [[SKPaymentQueue defaultQueue] finishTransaction:pendingTrans[k]];
    }
-(void)finishTransactionWithIdentifier:(NSString *)transactionIdentifier {
    SKPaymentQueue *queue = [SKPaymentQueue defaultQueue];
    for(SKPaymentTransaction *transaction in queue.transactions) {
        if([transaction.transactionIdentifier isEqualToString:transactionIdentifier]) {
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        }
    }
}

Ich kann dieses Problem nicht vorantreiben, da ich keine Ahnung habe, was passiert. Ich hoffe, jemand kann Dinge in seiner Umgebung debuggen und teilen 🙏

Gibt es ein Update zu diesem Problem?

Ich habe auch dieses Problem.

das gleiche hier finishTransactionIOS / finishTransaction dies funktioniert nicht in IOS

Ich scheine das Gleiche zu erleben.
Der Kauf von IAP wird erfolgreich abgeschlossen, aber der letzte Aufruf von finishTransaction gibt undefined .

// Finish transaction
const ackResult = await finishTransaction(purchase);
console.log("Ack result: ", ackResult); // Ack result: undefined

_Real Gerät "iPhone 6s" mit App Store Sandbox-Umgebung._

Was ist das erwartete Ergebnis von finishTransaction? Ist undefined ein gutes Ergebnis oder sollte ich etwas anderes erwarten?

Ich habe dieses Problem auch unter iOS, wo weder finishTransactionIOS noch finishTransaction diese Transaktionen tatsächlich entfernen, was mich daran hindert, die App freizugeben. Irgendein Update?

@hyochan Obwohl ich Objective-C definitiv nicht fließend finishTransaction und finishTransactionWithIdentifier hinzugefügt und es scheint, dass sie korrekt ausgeführt werden (ID wird übergeben und abgeglichen). Das einzige, woran ich denken kann, ist, dass [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; keine Verbindung zu StoreKit herstellt und die Transaktion abschließt. Ich weiß nicht wirklich, wohin ich von hier aus gehen soll, aber hoffentlich ist dies beim Debuggen hilfreich

Behandeln Sie auch Abonnementstatusbenachrichtigungen aus dem App Store? In meinem Fall hatte ich dieses Problem, bis ich sicherstellte, dass mein Server alle Benachrichtigungsereignisse ordnungsgemäß behandelte und mit 200 antwortete.

@espenjanson Interessant. Nein, war ich nicht. Aber ich habe gestern gerade zum InAppPurchases-Modul von expo gewechselt und jetzt funktioniert alles hervorragend.

@lachlanglen Nevermind. Es war nur ein einziger Glücksfall (?) Oder etwas anderes. Erstellt eine andere Version der App und das Problem ist wieder da. Ich denke daran, dasselbe zu tun, bin aber ein wenig besorgt, dass das Expo-Repo nicht sehr gut gepflegt ist.

Ich habe es mir angesehen und es ist richtig, dass es undefiniert zurückgibt, da der Aufruf von finishTransactions nichts in obj-c zurückgeben soll.
Ich habe einige Tests durchgeführt und in meinem Fall scheint es, als ob sie korrekt abgeschlossen wurden (einfacher Test, Pull PendingTransactions, wenn nichts vorhanden ist, funktioniert es gut).

@espenjanson Ich weiß nicht,

Gibt es eine Möglichkeit, dies zu lösen?
Ich habe dies auf TestFlight auch mit neuen Sandbox-Benutzern getestet und es passiert immer noch.

Meine purchaseUpdateListener erhalten weiterhin "alte" Transaktionen.
Ich rufe finishTransaction(purchase,false) da ich automatisch erneuerbare Abonnements verwende.
Das Ergebnis des Aufrufs ist undefined .

Kann jemand eine Problemumgehung oder Erklärung anbieten, warum dies geschieht?

@zatloeri Das ist anscheinend ein gewünschtes Verhalten. Ich habe eine Weile gebraucht, um das zu realisieren. Der App Store legt eine neue Quittung zur Erneuerung in StoreKit ab, die den Beobachter auslöst. Sie sollten diese Quittung verarbeiten und die Transaktion abschließen.

https://developer.apple.com/videos/play/wwdc2018/705/
https://developer.apple.com/videos/play/wwdc2020/10671

(In Safari auf HD-Qualität achten)

@ziyoshams Danke für die schnelle Antwort und für die Ressourcen, die ich gleich

Aber zuerst möchte ich nur auf eines hinweisen, weil ich nicht glaube, dass ich es anscheinend gemacht habe.
Was Sie beschreiben, erscheint mir logisch und ich habe damit gerechnet, aber was mich verwirrt, ist Folgendes:

Produkt A ist abgelaufen, wie durch receipt validation .
Ich erhalte eine alte Transaktion (vom Vortag) für Produkt A, wenn ich die App starte oder in den Vordergrund stelle.
Wenn ich die App das nächste Mal wieder in den Vordergrund stelle, erhalte ich eine weitere alte (möglicherweise etwas neuere als die vorherige, nicht sichere) Transaktion für Produkt A.
Auf einem anderen Vordergrund möglicherweise ein anderer und so weiter.

Ich würde erwarten, dass alle auf einer App gestartet werden, wenn das Abonnement bereits nach Ablauf ist.
Wird dieses Verhalten auch erwartet oder passiert etwas faul?

@zatloeri Jede Transaktion, die nicht abgeschlossen ist, wird in dieser Warteschlange

Ich habe das gleiche Problem unter iOS, die Transaktion wird nicht abgeschlossen, die Warteschlange wird nicht leer und der Empfang wird jedes Mal neu angezeigt, wenn die App gestartet wird. Ich habe den Empfang auf der Serverseite überprüft und dann die Transaktion abgeschlossen. Bitte schauen Sie sich meinen Code unten an

Ich habe unten einige Ausschnitte aus meinem Code erwähnt ...

`` `
RNIap importieren, {
In-App-Kauf,
Produkt,
PurchaseError,
Abonnement,
AbonnementKauf,
finishTransaction,
finishTransactionIOS,
purchaseErrorListener,
purchaseUpdatedListener,
clearTransactionIOS,
} von 'react-native-iap';

async componentDidMount () {
const result = warte auf RNIap.initConnection ();
const itemSubs = Platform.select ({
Android: [
get (this.props, 'subscriptionStore.subscription.android_product_id', null)
],
ios: [
get (this.props, 'subscriptionStore.subscription.ios_product_id', null)
]]
});

const subscriptions = warte auf RNIap.getSubscriptions (itemSubs);
purchaseUpdateSubscription = purchaseUpdatedListener (
asynchron (Kauf) => {
const quittung = purchase.transactionReceipt;
Abonnement lassen = {
Abonnement-ID: get (this.props, 'subscriptionStore.subscription.id', null)
};
if (Platform.OS === 'ios') {
Abonnement = {
...Abonnement,
order_id: get (Kauf, 'transactionId', null),
purchase_token: get (purchase, 'originalTransactionIdentifierIOS', null),
Quittung: get (Kauf, 'transactionReceipt', null), // (In TEXT speichern)
os: 'IOS'
}}
} else if (Platform.OS === 'android') {
const data = JSON.parse (Quittung);
Abonnement = {
...Abonnement,
order_id: get (data, 'orderId', null),
purchase_token: get (data, 'purchaseToken', null),
os: 'ANDROID'
}}
}}
Versuchen {
finishTransaction (Kauf, falsch); // Dies ist hier für Zeit, es wird später auf Erfolg gesetzt.
this.props.notificationStore.showToast ('Erfolgreich abonniert. Bitte warten ...', 'Erfolg', 5000);
const resp = warte auf this.props.subscriptionStore.onPurchase (Abonnement); // Überprüfen von Transaktionen am Serverende.
if (resp.success) {// Erfolgsantwort
this.props.userStore.setUser ({is_premium: 1});
this.props.navigation.replace ('FixFooter');
}}
} catch (Fehler) {
console.log ("onPurchase API ERROR:", Fehler);
}}
}}
)

purchaseErrorSubscription = purchaseErrorListener (
asynchron (Fehler) => {
console.log ('Kauffehler:', Fehler);
}}
)
}}

/ * onPurchase Button * /
async onPurchase () {
Versuchen {
const request = warte auf RNIap.requestSubscription (Platform.OS === 'android'?
get (this.props, 'subscriptionStore.subscription.android_product_id', null):
get (this.props, 'subscriptionStore.subscription.ios_product_id', null))
} catch (Fehler) {
console.log ('error:', error)
}}
}}

@ sufyan297 Kannst du bitte einen Ausschnitt aus deinem serverseitigen Code teilen? Ich versuche auch, eine Quittungsüberprüfung einzurichten, aber Apples Dokument ist äußerst verwirrend

@ziyoshams Erhalten Sie null auch mit der Methode finishTransaction des expo iap-Moduls?

@bcbcbcbcbcl Ich verwende das Expo-Modul nicht.

+1 für mich gibt es undefiniert zurück

@hyochan irgendein Update zu diesem Thema? Wir stecken schon seit einiger Zeit fest und können unsere App nicht veröffentlichen.

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.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen