Clément Tengip
Clément Tengip

Reputation: 678

StoreKit problem while restoring In-App Purchase

I tried to find a tutorial about IAP, and I found : This one

But when I call function to restore, nothing happens. OnTap button I call : store.restorePurchase()

extension Store {
    func product(for identifier: String) -> SKProduct? { ...}
    func purchaseProduct (_ product: SKProduct){ ...}
    func restorePurchases() {
        SKPaymentQueue.default().restoreCompletedTransactions()
        print("restore")
    }
}

restore is print in my console. It is the only thing that is printed in console. But in the code above, you can see .restored:that should print "UserIsPremium"

extension Store : SKPaymentTransactionObserver {
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions : [SKPaymentTransaction]){
        for transaction in transactions {
            var shouldFinishTransaction = false
            switch transaction.transactionState{
            case .purchased, .restored:
                completedPurchases.append(transaction.payment.productIdentifier)
                print("UserIsPremium")
                shouldFinishTransaction = true
            case .failed:
                print("NotPremium")
                shouldFinishTransaction = true
            case .deferred, .purchasing:
                print("...")
                break
            @unknown default:
                print("unknown")
                break
            }
            if shouldFinishTransaction {
                print("shouldfinish")
                SKPaymentQueue.default().finishTransaction(transaction)
                DispatchQueue.main.async {
                    self.purchaseCompletionHandler?(transaction)
                    self.purchaseCompletionHandler = nil
                }
            }
        }
    }
}

My class Store :

import StoreKit

typealias FetchCompletionHandler = (([SKProduct]) -> Void)
typealias PurchaseCompletionHandler = ((SKPaymentTransaction?) -> Void)

class Store: NSObject, ObservableObject {

@Published var allFullVersion = [FullVersion]()

private let allProductsIdentifiers = Set ([
"ClemPapplis.OrientationEPS.versionFull"
])
private var completedPurchases = [String]() {
    didSet {
        DispatchQueue.main.async{ [weak self] in
            guard let self = self else { return }
            for index in self.allFullVersion.indices {
                if self.completedPurchases.contains(self.allFullVersion[index].id){
                    print("completedPurchases")
                    UserDefaults.standard.setValue(true, forKey: "Premium")
                }
                self.allFullVersion[index].isLocked =
                    !self.completedPurchases.contains(self.allFullVersion[index].id)
            }
        }
    }
}

I use sandbox testers. If I buy item, no problem, datas are print in console.

Did I forget something ?

Upvotes: 0

Views: 1158

Answers (2)

Halis Bilal Kara
Halis Bilal Kara

Reputation: 126

I followed the same tutorial i think you did not select the select the none in here

configuration

to restore in your simulator you should select none when you select none it tries to connect apple developers in app purchase configuration. give it a try and let me know.

Upvotes: 0

user7014451
user7014451

Reputation:

It's been a few years since I used StoreKit, but I remember having an issue with restore purchases also (and yes, @ElTomato is correct, use a separate case - I'm surprised your code actually builds). I found that the following worked:

public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction:AnyObject in transactions {
        if let trans = transaction as? SKPaymentTransaction {
            switch trans.transactionState {
            case .purchased:
                SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                delegate.purchaseComplete()
            case .failed:
                SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
            case .restored:
                SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
            default:
                break
            }}}
}
func restorePurchases() {
    SKPaymentQueue.default().add(self)
    SKPaymentQueue.default().restoreCompletedTransactions()
}
public func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
    for _ in queue.transactions {
        alreadyPurchased = true
        delegate.purchasesRestored()
    }
    showAlert("Purchases have been restored.")
}

Don't worry about showAlert, that's just an extension I have for UIViewController. But what I'm not seeing in your code is paymentQueueRestoreCompletedTransactionsFinished(_ queue:).

Upvotes: 2

Related Questions