ios – 自动恢复应用内购买耗材

ios – 自动恢复应用内购买耗材,第1张

概述我正在进行我的第一次应用内购买,一种奇怪的行为是正在恢复耗材产品而不是创建新的交易. 我跟着tuto https://www.raywenderlich.com/122144/in-app-purchase-tutorial 我发现了一种优雅的方法. 这是我的StoreKit助手: import StoreKitpublic typealias ProductIdentifier = Stri 我正在进行我的第一次应用内购买,一种奇怪的行为是正在恢复耗材产品而不是创建新的交易.

我跟着tuto https://www.raywenderlich.com/122144/in-app-purchase-tutorial

我发现了一种优雅的方法.

这是我的StoreKit助手:

import StoreKitpublic typealias ProductIDentifIEr = Stringpublic typealias ProductsRequestCompletionHandler = (_ success: Bool,_ products: [SKProduct]?) -> ()open class IAPHelper : NSObject  {    fileprivate let productIDentifIErs: Set<ProductIDentifIEr>    fileprivate var purchasedProductIDentifIErs: Set<ProductIDentifIEr> = Set()    fileprivate var productsRequest: SKProductsRequest?    fileprivate var productsRequestCompletionHandler: ProductsRequestCompletionHandler?    static let IAPHelperPurchaseNotification = "IAPHelperPurchaseNotification"    public init(productIDs: Set<ProductIDentifIEr>) {        productIDentifIErs = productIDs        super.init()        SKPaymentQueue.default().add(self)    }}// MARK: - StoreKit APIextension IAPHelper {    public func requestProducts(_ completionHandler: @escaPing ProductsRequestCompletionHandler) {        productsRequest?.cancel()        productsRequestCompletionHandler = completionHandler        productsRequest = SKProductsRequest(productIDentifIErs: productIDentifIErs)        productsRequest!.delegate = self        productsRequest!.start()    }    public func buyProduct(_ product: SKProduct) {        print("Buying \(product.productIDentifIEr)...")        let payment = SKPayment(product: product)        SKPaymentQueue.default().add(payment)    }    public func isProductPurchased(_ productIDentifIEr: ProductIDentifIEr) -> Bool {        return purchasedProductIDentifIErs.contains(productIDentifIEr)    }    public class func canMakePayments() -> Bool {        return SKPaymentQueue.canMakePayments()    }    public func restorePurchases() {        SKPaymentQueue.default().restoreCompletedTransactions()    }}// MARK: - SKProductsRequestDelegateextension IAPHelper: SKProductsRequestDelegate {    public func productsRequest(_ request: SKProductsRequest,dIDReceive response: SKProductsResponse) {        print("Loaded List of products...")        let products = response.products        productsRequestCompletionHandler?(true,products)        clearRequestAndHandler()        for p in products {            print("Found product: \(p.productIDentifIEr) \(p.localizedTitle) \(p.price.floatValue)")        }    }    public func request(_ request: SKRequest,dIDFailWithError error: Error) {        print("Failed to load List of products.")        print("Error: \(error.localizedDescription)")        productsRequestCompletionHandler?(false,nil)        clearRequestAndHandler()    }    private func clearRequestAndHandler() {        productsRequest = nil        productsRequestCompletionHandler = nil    }}// MARK: - SKPaymentTransactionObserverextension IAPHelper: SKPaymentTransactionObserver {    public func paymentQueue(_ queue: SKPaymentQueue,updatedTransactions transactions: [SKPaymentTransaction]) {        for transaction in transactions {            switch (transaction.transactionState) {            case .purchased:                complete(transaction: transaction)                break            case .Failed:                fail(transaction: transaction)                break            case .restored:                restore(transaction: transaction)                break            case .deferred:                break            case .purchasing:                break            }        }    }    private func complete(transaction: SKPaymentTransaction) {        print("complete...")        valIDateReceipt()        deliverPurchaseNotificationFor(IDentifIEr: transaction.payment.productIDentifIEr)        SKPaymentQueue.default().finishTransaction(transaction)    }    private func restore(transaction: SKPaymentTransaction) {        guard let productIDentifIEr = transaction.original?.payment.productIDentifIEr else { return }        print("restore... \(productIDentifIEr)")        deliverPurchaseNotificationFor(IDentifIEr: productIDentifIEr)        SKPaymentQueue.default().finishTransaction(transaction)    }    private func fail(transaction: SKPaymentTransaction) {        print("fail...")        if let transactionError = transaction.error as? NSError {            if transactionError.code != SKError.paymentCancelled.rawValue {                print("Transaction Error: \(transaction.error?.localizedDescription)")            }        }        SKPaymentQueue.default().finishTransaction(transaction)    }    private func deliverPurchaseNotificationFor(IDentifIEr: String?) {        guard let IDentifIEr = IDentifIEr else { return }        purchasedProductIDentifIErs.insert(IDentifIEr)        UserDefaults.standard.set(true,forKey: IDentifIEr)        UserDefaults.standard.synchronize()        NotificationCenter.default.post(name: NSNotification.name(rawValue: IAPHelper.IAPHelperPurchaseNotification),object: IDentifIEr)    }}

我可以买一次,然后自动恢复:

This in-app purchase has already been bought. It will be restored for
free

当我收到此消息时,不会调用任何IAPHelper方法.

我的iTunes显示它是耗材:

即使卸载仍在恢复购买的应用程序.

它真的看起来像一个苹果虫,因为我的第一次测试我可以购买2..3次没有这个消息.

如果它不是错误,我该如何防止这种情况?

解决方法 对于那些陷入这种愚蠢局面的人来说,这里有一些WA和解决方案:

queue.finishTransaction(transaction)

重要信息:使用paymentQueue方法完成交易:

public func paymentQueue(_ queue: SKPaymentQueue,updatedTransactions transactions: [SKPaymentTransaction]) {    for transaction in transactions {        switch (transaction.transactionState) {        case .purchased:            complete(transaction: transaction)            queue.finishTransaction(transaction)            break        case .Failed:            fail(transaction: transaction)            queue.finishTransaction(transaction)            break        case .restored:            restore(transaction: transaction)            queue.finishTransaction(transaction)            break        case .deferred:            break        case .purchasing:            break        }    }}

这样可以避免这种情况.

如果你已经坚持下去,这里是工作,只是为了测试目的!

for transaction in SKPaymentQueue.default().transactions {        print(transaction)        SKPaymentQueue.default().finishTransaction(transaction)    }

您可以将其放在临时按钮上,并在一次测试时清除所有交易.

至少它今天救了我的命.

总结

以上是内存溢出为你收集整理的ios – 自动恢复应用内购买耗材全部内容,希望文章能够帮你解决ios – 自动恢复应用内购买耗材所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1073295.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存