Search code examples
iosswiftiphonein-app-purchase

How can I get IAP receipt If user uninstall the app and install it again? SWIFT


If I purchase something and check the purchase receipt I can get the encoded value of it by this:

if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
            FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {

            do {
                let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
                print(receiptData)

                let receiptString = receiptData.base64EncodedString(options: [])
                print("receiptString \(receiptString)")
                // Read receiptData
            }
            catch { print("Couldn't read receipt data with error: " + error.localizedDescription) }
        }

But If I purchase something, then delete the app and reinstall it again and check the receipt, I can't get anything with the upper code. It just get the appStoreReceiptURL and go straight away without entering do {} catch. How can I get the receipt in this scenario?


Solution

  • If you attempt to restore purchase , the user will not be refunded the purchased amount, however you would be able to verify that user purchased the product, and will also receive receipt that contants all the information about his previous purchase, therefore you can safely verify the purchase in your App.

    In App Store Review Guides is clearly stated that

    Any credits or in-game currencies purchased via in-app purchase may not expire, and you should make sure you have a restore mechanism for any restorable in-app purchases.

    That means you should provide some mechanism (e.g. Restore Purchase Button) anyway, regardless of scenario when the user uninstalls Application. In your case, you can provide the Restore button directly on your Login screen. Check some inspiration on Restore purchase button in Apple Human Interface guidelines.

    I you want to restore purchase directly with Apple API after user taps the Restore Purchase button, you can use:

    SKPaymentQueue.default().restoreCompletedTransactions()
    

    ,which triggers Apple servers, checks the users Apple ID and gets all of the app purchases they have made before and returns you transaction that you observe with SKPaymentTransactionObserver with this code:

        func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction in transactions {
            if transaction.transactionState == .restored {
                //here is your restored transaction
            }
        }
    }
    

    If you however want to get hold of the new receipt with all receipt data, including previous purchases, I recommend not using directly Apple API, but using SwiftyStoreKit library : link on github . Code example below:

        func restoreYourPurchases( completion: @escaping (Result<Bool,Error>) -> Void) {
        SwiftyStoreKit.restorePurchases(atomically: true) { results in
            var restoreSuccessfull = false
            if results.restoreFailedPurchases.count > 0 {
                print("Restore Failed: \(results.restoreFailedPurchases)")
            }
            else if results.restoredPurchases.count > 0 {
                print("Restore Success: \(results.restoredPurchases)")
                for purchase in results.restoredPurchases {
                    if purchase.productId == "yourID" {
                        let timeOfPurchase = purchase.originalPurchaseDate
                    }
                }
            }
            else {
                print("Nothing to Restore")
                completion(.success(false))
            }
        }
    }