【问题标题】:Issue with In app purchase in iOS?iOS中的应用内购买问题?
【发布时间】:2017-01-05 14:51:11
【问题描述】:

我已经在我的应用中进行了应用购买。我关注了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)
      }
    }

请指导一下是什么问题?

编辑: 调用失败并出现错误。“无法加载产品列表。”

【问题讨论】:

  • 错误是什么?
  • 没有得到产品

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


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 我是否需要使用产品的测试员帐户登录
  • 我是否需要使用测试员帐户登录才能获得产品-
  • 是的。否则你无法测试应用内购买
  • 我在输入详细信息时创建了一个沙盒用户,然后它说不允许创建 iTunes 帐户
  • 无法创建测试用户?
【解决方案2】:

退出 iTunes 和 iCloud 帐户后,我重置了我的 iOS 设备,并且应用内购买成功。虽然我不知道为什么。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    相关资源
    最近更新 更多