Не срабатывает покупка только при первом запуске

В моем приложении есть встроенная покупка. Моя покупка активируется после нажатия кнопки. Но если я открываю приложение в первый раз и нажимаю кнопку, я получаю следующий результат: No products found with identifier

из этой функции:

func purchaseProduct(identifier:String) {
    guard let product = self.product(identifier: identifier) else {
        print("No products found with identifier: \(identifier)")
            
        // fire purchase status: failed notification
        delegate?.purchaseStatusDidUpdate(PurchaseStatus.init(state: .failed, error: PurchaseError.productNotFound, transaction: nil, message:"An error occured"))
        return
    }
    //.etc
}

Но если после этого снова нажать кнопку, все работает нормально. Также, если я закрою приложение, снова открою его и нажму кнопку, покупка будет работать нормально. Почему это происходит только при первом запуске приложения? И как это исправить?

Есть следующий класс и думаю дело в нем:

class MyAppProductStore: Store {
    static let shared = MyAppProductStore()
    
    // purchase processor
    var itunes: iTunesStore = iTunesStore()
    
    init() {
        // register for purchase status update callbacks
        itunes.delegate = self
        
        validateProducts(MyProductIds.allIdentifiers())
    }
    
    /// This function is called during the purchase/restore purchase process with each status change in the flow. If the status is complete then access to the product should be granted at this point.
    ///
    /// - Parameter status: The current status of the transaction.
    internal func processPurchaseStatus(_ status: PurchaseStatus) {
        switch status.state {
        case .initiated:
            // TODO: show alert that purchase is in progress...
            break
        case .complete:
            if let productID = status.transaction?.payment.productIdentifier {
                // Store product id in UserDefaults or some other method of tracking purchases
                UserDefaults.standard.set(true , forKey: productID)
                UserDefaults.standard.synchronize()
            }
        case .cancelled:
            break
        case .failed:
            // TODO: notify user with alert...
            break
        }
    }
}

extension MyAppProductStore: iTunesPurchaseStatusReceiver, iTunesProductStatusReceiver {
    func purchaseStatusDidUpdate(_ status: PurchaseStatus) {
        // process based on received status
        processPurchaseStatus(status)
    }
    
    func restoreStatusDidUpdate(_ status: PurchaseStatus) {
        // pass this into the same flow as purchasing for unlocking products
        processPurchaseStatus(status)
    }
    
    func didValidateProducts(_ products: [SKProduct]) {
        print("Product identifier validation complete with products: \(products)")
        // TODO: if you have a local representation of your products you could
        // sync them up with the itc version here
    }
    
    func didReceiveInvalidProductIdentifiers(_ identifiers: [String]) {
        // TODO: filter out invalid products? maybe... by default isActive is false
    }
}

если после его вызова нажать на кнопку - все работать будет нормально.

Чтобы его вызвать использую следующую строку var store = MyAppProductStore() Я поместил ее в AppDelegate это выглядит так:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var store = MyAppProductStore()
.etc

Это самый быстрый способ вызвать?

No products found with identifier:

class iTunesStore: NSObject, SKProductsRequestDelegate {
    
    weak var delegate: (iTunesProductStatusReceiver & iTunesPurchaseStatusReceiver)?
    
    var transactionObserver: IAPObserver = IAPObserver()
    var availableProducts: [SKProduct] = []
    var invalidProductIDs: [String] = []
    
    deinit {
        SKPaymentQueue.default().remove(self.transactionObserver)
    }
    
    override init() {
        super.init()
        transactionObserver.delegate = self
    }
    
    func fetchStoreProducts(identifiers:Set<String>) {
        print("Sending products request to ITC")
        let request:SKProductsRequest = SKProductsRequest.init(productIdentifiers: identifiers)
        request.delegate = self
        request.start()
    }
    
    func purchaseProduct(identifier:String) {
        guard let product = self.product(identifier: identifier) else {
            print("No products found with identifier: \(identifier)")
            
            //HUD.flash(.labeledError(title: "Попробуйте снова", subtitle: "Ошибка"), delay: 2.0)
            
            // fire purchase status: failed notification
            delegate?.purchaseStatusDidUpdate(PurchaseStatus.init(state: .failed, error: PurchaseError.productNotFound, transaction: nil, message:"An error occured"))
            return
        }
        
        guard SKPaymentQueue.canMakePayments() else {
            print("Unable to make purchases...")
            delegate?.purchaseStatusDidUpdate(PurchaseStatus.init(state: .failed, error: PurchaseError.unableToPurchase, transaction: nil, message:"An error occured"))
            return
        }
        
        // Fire purchase began notification
        delegate?.purchaseStatusDidUpdate(PurchaseStatus.init(state: .initiated, error: nil, transaction: nil, message:"Processing Purchase"))
        
        let payment = SKPayment.init(product: product)
        SKPaymentQueue.default().add(payment)
        
    }
    
    func restorePurchases() {
        // Fire purchase began notification
        delegate?.restoreStatusDidUpdate(PurchaseStatus.init(state: .initiated, error: nil, transaction: nil, message:"Restoring Purchases"))
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
    
    
    // returns a product for a given identifier if it exists in our available products array
    func product(identifier:String) -> SKProduct? {
        for product in availableProducts {
            if product.productIdentifier == identifier {
                return product
            }
        }
        
        return nil
    }
    
}

// Receives purchase status notifications and forwards them to this classes delegate
extension iTunesStore: iTunesPurchaseStatusReceiver {
    func purchaseStatusDidUpdate(_ status: PurchaseStatus) {
        delegate?.purchaseStatusDidUpdate(status)
    }
    
    func restoreStatusDidUpdate(_ status: PurchaseStatus) {
        delegate?.restoreStatusDidUpdate(status)
    }
}

// MARK: SKProductsRequest Delegate Methods
extension iTunesStore {
    @objc(productsRequest:didReceiveResponse:) func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        // set new products
        availableProducts = response.products
        
        // set invalid product id's
        invalidProductIDs = response.invalidProductIdentifiers
        if invalidProductIDs.isEmpty == false {
            // call delegate if we received any invalid identifiers
            delegate?.didReceiveInvalidProductIdentifiers(invalidProductIDs)
        }
        print("iTunes Store: Invalid product IDs: \(response.invalidProductIdentifiers)")
        
        // call delegate with available products.
        delegate?.didValidateProducts(availableProducts)
    }
}

Ответы (0 шт):