iOS StoreKit – Quand appeler – (void) restoreCompletedTransactions?

J'ai beaucoup de 1 FAI d'achat de time à l'intérieur de mon application. Les users peuvent les acheter très bien.

Mon problème est que j'intègre avec Flurry pour suivre les achats réels par rapport à la simple restauration d'un achat, mais SKPaymentTransaction mon SKPaymentTransaction revient toujours comme SKPaymentTransactionStatePurchased plutôt que SKPaymentTransactionStateRestored .

Apparemment, SKPaymentTransactionStateRestored est seulement appelé quand - (void)restoreCompletedTransactions , mais quand dois-je appeler cette méthode?

Mon process de pensée est qu'un achat devrait aller comme ceci: 1) L'user choisit le produit, 2) On request à l'user s'il voudrait acheter le produit pour le montant de X. 3) Le server vérifie si l'user a déjà acheté, et s'il l'a restauré en définissant SKPaymentTransactionStateRestored . Sinon, traitez la transaction et définissez SKPaymentTransactionStatePurchased . Apparemment, c'est faux et je suis supposé appeler - (void)restoreCompletedTransactions quelque part entre les deux ???

Merci,

Volonté

MODIFIER:

À l'origine j'avais posté une méthode très longue et inutile pour get ce dont j'avais besoin, mais comme vous le verrez ci-dessous, Matt m'a aidé à find la variable que je cherchais.

Par exemple, imaginons qu'un user ait déjà acheté mon application, acheté tous les IAP non consommables disponibles, puis supprimé l'application. Lorsque l'user réinstalle l'application, je veux être en mesure de déterminer quand il va "acheter" les produits à nouveau, sera-ce un achat original (première fois), ou un achat de restauration?

J'ai mis en place un button "Restaurer tous les achats", mais disons que l'user l'ignore / ne le voit pas, et essaie de sélectionner un produit qu'il a déjà acheté.

Comme avec un achat normal, je fais ce qui suit:

 if ([SKPaymentQueue canMakePayments]) { self.productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:productID]]; self.productRequest.delegate = self; [self.productRequest start]; } else { //error message here } 

Une fois que l'user s'est connecté à son count iTunes, l'application lui indiquera qu'il l'a déjà acheté et il sera maintenant restauré. La méthode de délégué suivante sera appelée:

  -(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: { [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; if(transaction.originalTransaction) { NSLog(@"Just restoring the transaction"); } else { NSLog(@"First time transaction"); } break; } default: break; } } } 

Peu importe si la transaction était une restauration ou un achat SKPaymentTransactionStatePurchased , transaction.transactionState sera égal à SKPaymentTransactionStatePurchased .

Maintenant, à partir de ce point, comment pouvons-nous déterminer si cet achat est un achat original ou de restauration?

Simple: Comme vu ci-dessus, il suffit de voir si transaction.originalTransaction est initialisée. Note d'Apple: // Uniquement valide si l'état est SKPaymentTransactionStateRestored.

Si la SKPaymentTransaction originalTransaction SKPaymentTransaction est initialisée, cela signifie qu'il y avait une transaction précédente. Sinon, cette transaction est originale!

Encore une fois, merci à Matt de m'avoir orienté dans la bonne direction, et d'avoir rendu la logique beaucoup plus propre!

L'attente canonique semble être que vous fournissez un button de restauration qui appelle restoreCompletedTransactions . En ce qui concerne ce qui se passe si l'user ne tient pas count de ce fait et essaie simplement de passer à travers votre interface d'achat pour ramener des fonctionnalités qu'il a déjà achetées, vous risquez de vous inquiéter inutilement; les docs disent:

Si l'user tente d'acheter un produit restaurable (au lieu d'utiliser l'interface de restauration que vous avez implémentée), l'application reçoit une transaction normale pour cet élément, et non une transaction de restauration. Cependant, l'user n'est plus facturé pour ce produit. Votre application doit traiter ces transactions de manière identique à celles de la transaction d'origine.

Le magasin mettra en place des dialogs interagissant avec l'user ("Vous l'avez déjà acheté, voulez-vous le download à nouveau gratuitement?"), Et la notification du rachat gratuit aura lieu dans votre paymentQueue:updatedTransactions: as d'habitude, et vous pouvez utiliser son originalTransaction.transactionIdentifier pour l'identifier avec l'achat original.

Si vous mettez en place des achats via l'application, vous devez placer un button de restauration quelque part dans votre application, sinon il s'agit d'une raison de refus. Vous pouvez regarder Obtenir la list des produits achetés, inApp Acheter iPhone pour une incidence.

EDIT 2: Il peut y avoir d'autres moyens que de mettre un button pour éviter le rejet. Une façon de suggérer dans les commentaires est de restaurer le lancement de l'application, ce qui me semble suffisant pour me conformer aux directives d'Apple.

Jetez également un oeil à la dernière partie de ce tutoriel, il mentionne le même problème, et montre une façon simple de l'implémenter: http://www.raywenderlich.com/21081/introduction-to-in-app-purchases-in-ios -6-tutoriel

MODIFIER:

 //Draft implementation of transaction observer delegate -(void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { for (SKPaymentTransaction * transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: ... case SKPaymentTransactionStateFailed: ... case SKPaymentTransactionStateRestored: ... default: break; } }; } 

La documentation Apple IOS SDK est en fait trompeuse sur ce problème car elle dit que:

 @property(nonatomic, readonly) SKPaymentTransaction *originalTransaction The contents of this property are undefined except when transactionState is set to SKPaymentTransactionStateRestored. 

Le problème est que lorsque l'user clique sur votre button d'achat, passe par le process d'achat, et obtient enfin un message qu'il a déjà payé et qu'il peut download gratuitement, votre observateur ne vous envoie pas un SKPaymentTransactionStateRestored. Il vous envoie en fait un SKPaymentTransactionStatePurchased.

Les bonnes nouvelles sont que malgré la documentation, vous obtiendrez réellement la propriété originalTransaction même lorsque l'état de votre transaction est SKPaymentTransactionStatePurchased. Juste tester pour voir si cette propriété est nulle ou non et vous saurez si la transaction était un nouvel achat ou un ancien acheté restauré gratuitement.