restoreCompletedTransactions()无法正常工作

时间:2019-02-06 18:26:17

标签: ios swift in-app-purchase

我正在尝试使用SKPaymentQueue.default()。restoreCompletedTransactions()恢复非消耗性IAP,但按照计划没有任何效果。在沙盒中,我收到“没有可用的应用内购买信息。请稍后再试。21105”,在Prod中,什么也没有发生。从我可以看到,实际的SKPaymentQueue.default()。restoreCompletedTransactions()行引发了沙箱中的错误,此后未进行任何处理。我确信一切都正确,因为我可以手工购买并且可以正常使用,所以我也可以再次购买任何有错误的东西,即我已经拥有它,然后激活该项目,但是“还原”按钮不起作用(restorePurchases()) 。我的应用程序中确实有38个IAP,但是我不确定这是否以任何方式关联,并且它们都是非消耗性的。出售贴纸的是iMessage Extension。另一个奇怪的是,Apple确实取消了我的应用程序,因为我在未经我自己许可的情况下使用了自己的Art(这很有趣),但是所有情况都表明,使用非消耗品必须具有Restore(还原)功能,Apple对此进行检查。情况一切都在不工作的情况下通过了。

我的IAP类别是:

import Foundation
import StoreKit
import os.log


class IAPService: NSObject
{
    private override init() {} // make sure there is no extra copies

    static let shared = IAPService() // makes this singleton
    fileprivate var products = [SKProduct]()
    let paymentQueue = SKPaymentQueue.default()
    let defaults = UserDefaults.standard
    var haveData = false
    var reference = StickewrsCollectionViewController()
    fileprivate var request = SKProductsRequest()
    let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "IAPService")

    let receiptFetcher = ReceiptFetcher()


    func getProducts()
    {
        let allStickersIAP = “IAP reference”
        var iapList = Dictionary<String, String>()
        if let path = Bundle.main.path(forResource: "StickersData", ofType: ".plist")
        {
            let dict = NSDictionary(contentsOfFile: path) as! Dictionary<String, AnyObject>
            let globalData = dict["StickerData"] as! Array<AnyObject>
            iapList = (globalData[1]) as! Dictionary<String, String>
        }
        var products: Set = [allStickersIAP]
        for iap in iapList
        {
            products.insert(iap.value)
        }
        request = SKProductsRequest(productIdentifiers: products)
        request.delegate = self
        request.start()
        paymentQueue.add(self)
        SKPaymentQueue.default().add(self)
        os_log("Getting products")


    }

    func purchase(product: String)
    {
        if (SKPaymentQueue.canMakePayments())
        {
            guard let productToPurchase = products.filter({$0.productIdentifier == product}).first
            else {return}

            let payment = SKPayment(product: productToPurchase)
            paymentQueue.add(payment)
        }
    }

    func restorePurchases()
    {
        print("Restoring purchases")
        os_log("Restoring purchases")

        SKPaymentQueue.default().restoreCompletedTransactions()

    }

    func iapCheck() -> Bool
    {
        return SKPaymentQueue.canMakePayments() && haveData
    }

    func getProductData(iap: String) -> SKProduct
    {
        return products.filter({$0.productIdentifier == iap}).first ?? SKProduct()
    }

    func priceStringForProduct(item: SKProduct) -> String? {
        let price = item.price
        if price == NSDecimalNumber(decimal: 0.00) {
            return NSLocalizedString("free", comment: "") 
        } else {
            let numberFormatter = NumberFormatter()
            let locale = item.priceLocale
            numberFormatter.numberStyle = .currency
            numberFormatter.locale = locale
            return numberFormatter.string(from: price)
        }
    }

    func setReference(ref: StickewrsCollectionViewController)
    {
        reference = ref
    }

    public func passPopUp(_ text: String)
    {
        reference.ShowPopUp(text)
    }

    // Called when the application is about to terminate.
    func applicationWillTerminate(_ application: UIApplication) {
        // Remove the observer.
        SKPaymentQueue.default().remove(self)
    }

}

extension IAPService: SKProductsRequestDelegate, SKPaymentTransactionObserver
{
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        products = response.products

        haveData = true
    }

    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction in transactions {
           switch  transaction.transactionState
            {
                case .purchasing: break
                case .purchased:
                    do {
                        defaults.set(true, forKey: transaction.payment.productIdentifier)
                        defaults.synchronize() // save changes in PlayerPrefs
                        print(transaction.payment.productIdentifier)
                        queue.finishTransaction(transaction)
                        }
            case .restored:
                do {
                    print("Do actual restoring")
                    os_log("Now restoring %@",  transaction.original!.payment.productIdentifier)
                    reference.ShowPopUp("Restoring purchase \(transaction.original!.payment.productIdentifier)")
                    defaults.set(true, forKey: transaction.original!.payment.productIdentifier)
                    defaults.synchronize() // save changews in PlayerPrefs
                    print(transaction.payment.productIdentifier)
                    queue.finishTransaction(transaction)
                }
                default: queue.finishTransaction(transaction)
            }
        }
        reference.redrawnAfterPurchase()
    }

    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        for transaction in queue.transactions {
            let t: SKPaymentTransaction = transaction
            let prodID = t.payment.productIdentifier as String

            defaults.set(true, forKey: prodID)
            defaults.synchronize() // save changews in PlayerPrefs
            print(prodID)
            queue.finishTransaction(transaction)
        }
        reference.redrawnAfterPurchase()
        reference.ShowPopUp(NSLocalizedString("restoreCompleted", comment: ""))
    }

}

extension SKPaymentTransactionState
{
    func status() -> String
    {
        switch self {
        case .deferred: return "deferred"
        case .failed: return "failed"
        case .purchased: return "purchased"
        case .purchasing: return "purchasing"
        case .restored: return "restored"

        }
    }
}

我做错了什么,如何使RestorePurchases实际执行某些操作?

0 个答案:

没有答案