如果用户卸载应用程序并重新安装,我如何获得 IAP 收据? SWIFT

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

如果我购买东西并查看购买收据,我可以通过以下方式获取它的编码值:

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) }
        }

但是如果我购买了东西,然后删除应用程序并重新安装并查看收据,我无法使用上面的代码获得任何东西。它只是得到 appStoreReceiptURL 并直接走,而不输入 do {} catch。在这种情况下如何获得收据?

如果您尝试恢复购买,用户将不会退还所购买的金额,但是您可以验证用户是否购买了该产品,并且还会收到收据包含他之前购买的所有信息,因此您可以在您的应用程序中安全地验证购买。

App Store Review Guides 中明确指出

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.

这意味着无论用户卸载应用程序的情况如何,您都应该提供某种机制(例如恢复购买按钮)。在您的情况下,您可以直接在登录屏幕上提供恢复按钮。查看 Apple Human Interface guidelines.

中恢复购买按钮的一些灵感

我想直接通过 Apple 恢复购买 API 在用户点击恢复购买按钮后,您可以使用:

SKPaymentQueue.default().restoreCompletedTransactions()

,这会触发 Apple 服务器,检查用户的 Apple ID 并获取他们之前购买的所有应用程序以及 returns 您使用以下代码观察到的 SKPaymentTransactionObserver 交易:

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

但是,如果您想要获得包含所有收据数据(包括以前的购买)的新收据,我建议不要直接使用 Apple API,而是使用 SwiftyStoreKit 库:link on github 。下面的代码示例:

    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))
        }
    }
}