Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么不';t用户在Swift iOS中获得应用内购买确认?_Ios_Swift_In App Purchase - Fatal编程技术网

为什么不';t用户在Swift iOS中获得应用内购买确认?

为什么不';t用户在Swift iOS中获得应用内购买确认?,ios,swift,in-app-purchase,Ios,Swift,In App Purchase,我将在警报视图中显示IAP选项,下面是我用于此操作的代码: paidAlert.addAction(UIAlertAction(title: "Purchase", style: UIAlertAction.Style.default, handler: { (action) in IAPHandler.shared.purchaseMyProduct(index: 0) })) paidAlert.addActi

我将在警报视图中显示IAP选项,下面是我用于此操作的代码:

paidAlert.addAction(UIAlertAction(title: "Purchase", style: UIAlertAction.Style.default, handler: { (action) in
                IAPHandler.shared.purchaseMyProduct(index: 0)

            }))
            paidAlert.addAction(UIAlertAction(title: "Restore", style: UIAlertAction.Style.default, handler: { (action) in
                IAPHandler.shared.restorePurchase()

            }))
            paidAlert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: { (action) in

            }))
我在另一个Swift文件中处理实际IAP,该文件发布在此处:

    import UIKit
import StoreKit

enum IAPHandlerAlertType{
    case disabled
    case restored
    case purchased

    func message() -> String{
        switch self {
        case .disabled:

            let notificationFeedbackGenerator = UINotificationFeedbackGenerator()
            notificationFeedbackGenerator.prepare()
            notificationFeedbackGenerator.notificationOccurred(.error)

            return "Purchases are disabled on your device."
        case .restored:

            let notificationFeedbackGenerator = UINotificationFeedbackGenerator()
            notificationFeedbackGenerator.prepare()
            notificationFeedbackGenerator.notificationOccurred(.success)

            return "Unlimited strategies have been successfully unlocked. You can restore this purchase using this Apple ID on other devices."
        case .purchased:

            let notificationFeedbackGenerator = UINotificationFeedbackGenerator()
            notificationFeedbackGenerator.prepare()
            notificationFeedbackGenerator.notificationOccurred(.success)

            return "Unlimited strategies have been successfully unlocked. You can restore this purchase using this Apple ID on other devices."
        }
    }
}

class IAPHandler: NSObject {
    static let shared = IAPHandler()

    let NON_CONSUMABLE_PURCHASE_PRODUCT_ID = "com.isaranjha.opc.fullversion"

    fileprivate var productID = ""
    fileprivate var productsRequest = SKProductsRequest()
    fileprivate var iapProducts = [SKProduct]()

    var purchaseStatusBlock: ((IAPHandlerAlertType) -> Void)?

    // MARK: - MAKE PURCHASE OF A PRODUCT
    func canMakePurchases() -> Bool {  return SKPaymentQueue.canMakePayments()  }

    func purchaseMyProduct(index: Int){
        if iapProducts.count == 0 { return }

        if self.canMakePurchases() {
            let product = iapProducts[index]
            let payment = SKPayment(product: product)
            SKPaymentQueue.default().add(self)
            SKPaymentQueue.default().add(payment)

            print("PRODUCT TO PURCHASE: \(product.productIdentifier)")
            productID = product.productIdentifier
        } else {
            purchaseStatusBlock?(.disabled)
        }
    }

    // MARK: - RESTORE PURCHASE
    func restorePurchase(){
        SKPaymentQueue.default().add(self)
        SKPaymentQueue.default().restoreCompletedTransactions()
    }

    // MARK: - FETCH AVAILABLE IAP PRODUCTS
    func fetchAvailableProducts(){

        // Put here your IAP Products ID's
        let productIdentifiers = NSSet(objects: NON_CONSUMABLE_PURCHASE_PRODUCT_ID
        )

        productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
        productsRequest.delegate = self
        productsRequest.start()
    }
}

extension IAPHandler: SKProductsRequestDelegate, SKPaymentTransactionObserver{
    // MARK: - REQUEST IAP PRODUCTS
    func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {

        if (response.products.count > 0) {
            iapProducts = response.products
            for product in iapProducts{
                let numberFormatter = NumberFormatter()
                numberFormatter.formatterBehavior = .behavior10_4
                numberFormatter.numberStyle = .currency
                numberFormatter.locale = product.priceLocale
                let price1Str = numberFormatter.string(from: product.price)
                print(product.localizedDescription + "\nfor just \(price1Str!)")
            }
        }
    }

    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        purchaseStatusBlock?(.restored)
    }

    // MARK:- IAP PAYMENT QUEUE
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction:AnyObject in transactions {
            if let trans = transaction as? SKPaymentTransaction {
                switch trans.transactionState {
                case .purchased:
                    print("purchased")
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    purchaseStatusBlock?(.purchased)
                    break

                case .failed:
                    print("failed")
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    break
                case .restored:
                    print("restored")
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                    break

                default: break
                }}}
    }
}
导入UIKit
进口存储套件
枚举IapHandlereType{
案例残疾
案件恢复
购买的箱子
func message()->字符串{
切换自身{
案例.残疾人:
让notificationFeedbackGenerator=UINotificationFeedbackGenerator()
notificationFeedbackGenerator.prepare()
notificationFeedbackGenerator.NotificationOccurrent(.error)
return“设备上已禁用购买。”
案件.恢复:
让notificationFeedbackGenerator=UINotificationFeedbackGenerator()
notificationFeedbackGenerator.prepare()
notificationFeedbackGenerator.NotificationOccursed(.success)
return“无限策略已成功解锁。您可以在其他设备上使用此Apple ID还原此购买。”
案例。购买:
让notificationFeedbackGenerator=UINotificationFeedbackGenerator()
notificationFeedbackGenerator.prepare()
notificationFeedbackGenerator.NotificationOccursed(.success)
return“无限策略已成功解锁。您可以在其他设备上使用此Apple ID还原此购买。”
}
}
}
类IAPHandler:NSObject{
静态let shared=IAPHandler()
让非消耗品购买产品\u ID=“com.isaranjha.opc.fullversion”
fileprivate var productID=“”
fileprivate var productsRequest=SKProductsRequest()
fileprivate var iapProducts=[SKProduct]()
var purchaseStatusBlock:((IAPHandlerAlertType)->无效)?
//马克:-购买产品
func canMakePurchases()->Bool{return SKPaymentQueue.canMakePayments()}
func purchaseMyProduct(索引:Int){
如果iapProducts.count==0{return}
如果self.canMakePurchases(){
let product=iapProducts[index]
let payment=SKPayment(产品:产品)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(付款)
打印(“要购买的产品:\(PRODUCT.productIdentifier)”)
productID=product.productIdentifier
}否则{
purchaseStatusBlock?(.禁用)
}
}
//MARK:-恢复购买
func restorepourchase(){
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().restoreCompletedTransactions()
}
//MARK:-获取可用的IAP产品
func fetchAvailableProducts(){
//把你的IAP产品ID放在这里
让productIdentifiers=NSSet(对象:非消耗品\采购\产品\ ID
)
productsRequest=SKProductsRequest(productIdentifiers:productIdentifiers as!Set)
productsRequest.delegate=self
productsRequest.start()
}
}
扩展IAPHandler:SKProductsRequestDelegate,SKPaymentTransactionObserver{
//马克:-申请IAP产品
func productsRequest(uRequest:SKProductsRequest,didReceive response:SKProductsResponse){
如果(response.products.count>0){
iapProducts=response.products
对于iapProducts中的产品{
设numberFormatter=numberFormatter()
numberFormatter.formatterBehavior=.behavior10\u 4
numberFormatter.numberStyle=.currency
numberFormatter.locale=product.priceLocale
让price1Str=numberFormatter.string(from:product.price)
打印(product.localizedDescription+“\n仅适用于\(price1Str!)”)
}
}
}
func paymentQueueRestoreCompletedTransactionsFinished(队列:SKPaymentQueue){
purchaseStatusBlock?(.已还原)
}
//标记:-IAP付款队列
func paymentQueue(queue:SKPaymentQueue,updatedTransactions事务:[SKPaymentTransaction]){
对于事务:事务中的任何对象{
如果let trans=交易作为?SKPaymentTransaction{
开关trans.transactionState{
案例。购买:
印刷品(“购买”)
SKPaymentQueue.default().finishTransaction(事务为!SKPaymentTransaction)
purchaseStatusBlock?(.已购买)
打破
案例。失败:
打印(“失败”)
SKPaymentQueue.default().finishTransaction(事务为!SKPaymentTransaction)
打破
案件.恢复:
打印(“恢复”)
SKPaymentQueue.default().finishTransaction(事务为!SKPaymentTransaction)
打破
默认值:中断
}}}
}
}
但是,多个用户(但不是所有用户)报告说他们可以购买IAP罚款(它向他们和所有人收取费用),但他们没有得到任何确认,即我已编码(警告说购买成功等),因此没有购买的功能。我们能找到的唯一解决办法是,用户需要停止应用程序的多任务处理,再次进入初始IAP购买警报,但选择恢复,然后它会相应地提示,并且功能被解锁

我不知道我在这方面哪里出了问题,但鉴于恢复功能似乎是如何工作的,我假设我在实际购买中遗漏了一些东西,这些东西将被称为案例。正确购买并显示警报


非常感谢您的帮助。

您的
.purchased
状态出现逻辑错误-在更新解锁或处理购买所需的任何状态之前,您不应完成交易。在调用可选的
purchaseStatusBlock