Restaurer l'achat: Non-Consommable

J'ai complété une petite application où j'ai une option d'achat non-consommable. C'est sur l'App Store.

L'achat du produit fonctionne bien. C'est ma fonction d'achat de restauration qui semble ne rien faire.

J'ai ajouté ce code pour l'achat de restauration @IBAction :

 @IBAction func restorePurchases(sender: AnyObject) { SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().restoreCompletedTransactions() } 

Mais rien ne se passe lorsque j'appuie sur le button d'achat de restauration.

Je pense que je dois append une fonction qui vérifie si la restauration a réussi ou non. Je prévois de modifier le code comme suit:

 @IBAction func restorePurchases(sender: AnyObject) { SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().restoreCompletedTransactions() } func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) { for transaction:AnyObject in transactions { if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{ switch trans.transactionState { case .Restored: SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction) var alert = UIAlertView(title: "Thank You", message: "Your purchase(s) were restored.", delegate: nil, cancelButtonTitle: "OK") alert.show() break; case .Failed: SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction) var alert = UIAlertView(title: "Sorry", message: "Your purchase(s) could not be restored.", delegate: nil, cancelButtonTitle: "OK") alert.show() break; default: break; } } } 

Est-ce que cela fera l'affaire?

J'ai été à travers chaque thread par rapport à effectuer des transactions d'achat de restauration, et ma search m'a conduit à ce qui précède. Donc, je ne pense pas que ce soit une copy d'une question, mais peut-être clarifier comment restaurer avec succès les achats pour les autres confrontés à ma situation similaire.

Vos codes semblent assez bien pour la plupart, bien que certaines parties semblent provenir de tutoriels plus anciens. Il y a quelques changements que vous devriez faire, l'un d'eux est que vous devez appeler à nouveau votre fonction unlockProduct.

C'est le code que j'utilise (Swift 3).

 /// Updated transactions func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .purchasing: // Transaction is being added to the server queue. case .purchased: // Transaction is in queue, user has been charged. Client should complete the transaction. defer { queue.finishTransaction(transaction) } let productIdentifier = transaction.payment.productIdentifier unlockProduct(withIdentifier: productIdentifier) case .failed: // Transaction was cancelled or failed before being added to the server queue. defer { queue.finishTransaction(transaction) } let errorCode = (transaction.error as? SKError)?.code if errorCode == .paymentCancelled { print("Transaction failed - user cancelled payment") } else if errorCode == .paymentNotAllowed { // Will show alert automatically print("Transaction failed - payments are not allowed") } else { print("Transaction failed - other error") // Show alert with localised error description } case .restored: // Transaction was restored from user's purchase history. Client should complete the transaction. defer { queue.finishTransaction(transaction) } if let productIdentifier = transaction.original?.payment.productIdentifier { unlockProduct(withIdentifier: productIdentifier) } case .deferred: // The transaction is in the queue, but its final status is pending external action // eg family member approval (FamilySharing). // DO NOT freeze up app. Treate as if transaction has not started yet. } } } 

Que d'utiliser les methods de délégué pour afficher l'alerte de restauration

 /// Restore finished func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { guard queue.transactions.count != 0 else { // showAlert that nothing restored return } // show restore successful alert } /// Restore failed func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: NSError) { /// handle the restore error if you need to. } 

Débloquer le produit est juste une méthode que je suis sûr que vous avez déjà aussi.

  func unlockProduct(withIdentifier productIdentifier: Ssortingng) { switch productIdentifier { /// unlock product for correct ID } } 

En note, vous devriez déplacer cette ligne

  SKPaymentQueue.default().add(self) 

hors de votre fonction de restauration et d'achat et le mettre dans viewDidLoad.

Apple vous recommand d'append l'observateur de transaction dès que votre application est lancée et de ne la supprimer que lorsque votre application est fermée. Beaucoup de tutoriels ne vous apprennent malheureusement pas correctement. De cette façon, vous n'êtes pas sûr que toutes les transactions incomplètes, par exemple en raison d'une erreur de réseau, reprennent toujours correctement.

https://developer.apple.com/library/content/technotes/tn2387/_index.html

Dans mes projets réels, mon code pour les IAP est dans une class Singleton, donc j'utiliserais la délégation pour transmettre la méthode unlockProduct à ma class qui gère gameData. Je peux aussi m'assurer que l'observateur est ajouté au lancement de l'application.

J'espère que cela t'aides