ios - Storekit 和处理已购买 IAP 的用户

标签 ios swift in-app-purchase subscription storekit

我正在关注this RW 教程,和很多 IAP 和 Storekit 教程一样,他们讨论了用户第一次购买 IAP 的流程,但没有详细说明当用户购买 IAP 时应用程序如何运行。已购买 IAP 的用户再次打开应用程序。

当我发现问题的关键时更新我的​​问题:

据我所知,阻止/显示内容的代码是对 (1) 收据和 (2) SessionID 的查找……他没有详细介绍教程 SessionID 的用途或者它是否仅作为教程演示的一部分。例如,它仅在调用 uploadReceipt 时设置(仅在调用 handlePurchasedStatehandleRestoredState 时调用)。换句话说,如果用户打开已经订阅的应用,则不会运行任何代码来设置 SessionID,因此内容永远不会解锁?

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?

  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    SKPaymentQueue.default().add(self)
    SubscriptionService.shared.loadSubscriptionOptions()
    return true
  }  
}


// MARK: - SKPaymentTransactionObserver

extension AppDelegate: SKPaymentTransactionObserver {

  func paymentQueue(_ queue: SKPaymentQueue,
                    updatedTransactions transactions: [SKPaymentTransaction]) {

    for transaction in transactions {
      switch transaction.transactionState {
      case .purchasing:
        handlePurchasingState(for: transaction, in: queue)
      case .purchased:
        handlePurchasedState(for: transaction, in: queue)
      case .restored:
        handleRestoredState(for: transaction, in: queue)
      case .failed:
        handleFailedState(for: transaction, in: queue)
      case .deferred:
        handleDeferredState(for: transaction, in: queue)
      }
    }
  }

  func handlePurchasingState(for transaction: SKPaymentTransaction, in queue: SKPaymentQueue) {
    print("User is attempting to purchase product id: \(transaction.payment.productIdentifier)")
  }

  func handlePurchasedState(for transaction: SKPaymentTransaction, in queue: SKPaymentQueue) {
    print("User purchased product id: \(transaction.payment.productIdentifier)")

    queue.finishTransaction(transaction)
    SubscriptionService.shared.uploadReceipt { (success) in
      DispatchQueue.main.async {
        NotificationCenter.default.post(name: SubscriptionService.purchaseSuccessfulNotification, object: nil)
      }
    }
  }

  func handleRestoredState(for transaction: SKPaymentTransaction, in queue: SKPaymentQueue) {
    print("Purchase restored for product id: \(transaction.payment.productIdentifier)")
    queue.finishTransaction(transaction)
    SubscriptionService.shared.uploadReceipt { (success) in
      DispatchQueue.main.async {
        NotificationCenter.default.post(name: SubscriptionService.restoreSuccessfulNotification, object: nil)
      }
    }
  }

  func handleFailedState(for transaction: SKPaymentTransaction, in queue: SKPaymentQueue) {
    print("Purchase failed for product id: \(transaction.payment.productIdentifier)")
  }

  func handleDeferredState(for transaction: SKPaymentTransaction, in queue: SKPaymentQueue) {
    print("Purchase deferred for product id: \(transaction.payment.productIdentifier)")
  }
}

最佳答案

每次用户启动应用程序时,您都不会收到购买通知,但从技术上讲,您可以在每次程序运行时验证应用程序收据并重新处理每个 IAP。这看起来效率很低。您的应用程序应该只在购买时跟踪已购买的商品。

如果应用被删除并重新安装,或者用户将其安装在其他设备上,您应该提供“恢复应用内购买”功能来刷新应用收据并验证它。

关于ios - Storekit 和处理已购买 IAP 的用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47763691/

相关文章:

ios - 如何在 Swift UIView 类中将 SubLayer 添加到图层

ios - SKReceiptReceiptRequest - 在模拟器上,只有请求 :didFailWithError method is called. 我无法让我的应用程序获取沙箱收据

android - 在 Google Play 开发者控制台中更改应用内产品价格和描述时的传播延迟

Android 应用内购买问题

iphone - if 语句推送到 els 上的 viewController 不起作用

ios - 未调用中央管理器方法 ..

android - 调试 android/ios 应用程序 sqlite 数据库

swift - 如何在 Swift 中打印调用堆栈?

iOS 应用程序图像大小

ios - 具有关联类型的 Functor 协议(protocol)的实现(Swift)