iOS中的应用内购买问题?

时间:2016-12-31 10:30:23

标签: ios iphone swift xcode in-app-purchase

我已经在我的应用程序中购买了应用程序。我跟着this tutorial

现在在我的应用程序中,当我尝试加载产品时,它不会加载。它显示错误,因为无法连接到iTunes商店。我已经在iTunes上创建了一个产品。

以下是代码

/

    *
    * Copyright (c) 2016 Razeware LLC
    *
    * Permission is hereby granted, free of charge, to any person obtaining a copy
    * of this software and associated documentation files (the "Software"), to deal
    * in the Software without restriction, including without limitation the rights
    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    * copies of the Software, and to permit persons to whom the Software is
    * furnished to do so, subject to the following conditions:
    *
    * The above copyright notice and this permission notice shall be included in
    * all copies or substantial portions of the Software.
    *
    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    * THE SOFTWARE.
    */

    import StoreKit

    public typealias ProductIdentifier = String
    public typealias ProductsRequestCompletionHandler = (_ success: Bool, _ products: [SKProduct]?) -> ()

    open class IAPHelper : NSObject  {

      static let IAPHelperPurchaseNotification = "IAPHelperPurchaseNotification"
      fileprivate let productIdentifiers: Set<ProductIdentifier>
      fileprivate var purchasedProductIdentifiers = Set<ProductIdentifier>()
      fileprivate var productsRequest: SKProductsRequest?
      fileprivate var productsRequestCompletionHandler: ProductsRequestCompletionHandler?

      public init(productIds: Set<ProductIdentifier>) {
        productIdentifiers = productIds
        for productIdentifier in productIds {
          let purchased = UserDefaults.standard.bool(forKey: productIdentifier)
          if purchased {
            purchasedProductIdentifiers.insert(productIdentifier)
            print("Previously purchased: \(productIdentifier)")
          } else {
            print("Not purchased: \(productIdentifier)")
          }
        }
        super.init()
        SKPaymentQueue.default().add(self)
      }

    }

    // MARK: - StoreKit API

    extension 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: - SKProductsRequestDelegate

    extension IAPHelper: SKProductsRequestDelegate {

      public func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        let products = response.products
        print("Loaded list of 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: - SKPaymentTransactionObserver

    extension 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...")
        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)
      }
    }

请指导问题是什么?

编辑: 失败并出现错误被调用。&#34;无法加载产品列表。&#34;

2 个答案:

答案 0 :(得分:0)

确保您已退出设备上的所有生产iTunes帐户。

我在测试手机上收到此错误,该手机已使用我的实际iTunes帐户登录。 您无法使用生产iTunes帐户测试应用,因此出现错误。我只是希望Apple提供更好的错误,以避免这种猜测......

解决方案创建测试用户帐户,如果您没有。使用该帐户测试应用内购买。

注意:如果您没有收到产品,请确保您在发送与itunes上的产品标识符完全匹配的请求时使用的是产品标识符。

另一个愚蠢的原因,我们在模拟器上运行时会遇到这个错误。检查是否

  

您的应用正在模拟器中运行,该模拟器不支持In-App   购买

答案 1 :(得分:0)

退出iTunes&amp; iCloud帐户我重置了我的iOS设备&amp;在应用程序购买工作。虽然我不知道为什么。

您无需登录iOS设备即可从应用内购买产品。要购买产品,我们必须登录设备。