显示 IAP 页面之前的收据验证

Receipt validation before showing IAP-page

我对我们的应用内购买流程有疑问,因为它被 Apple 拒绝了。

因为我们不知道用户是否有有效订阅,所以我们必须先获取收据,这会导致 iTunes Store 密码提示(这是我们在非生产环境中正确理解的正常行为) .然后进行验证,根据结果,我们显示自动续订订阅页面或通过请求的操作。

我们的流程是:

  1. 正在获取收据
  2. 正在验证收据
  3. 如果
    • 有效:通过请求的操作;
    • 无效:显示自动续订订阅页面,用户可以在其中进行购买。

现在 Apple 在他们的拒绝中评论说他们看不到自动续订订阅页面。相反,他们从 iTunes Store 收到了密码提示。

正如我们正确理解的那样,密码提示是非生产环境中的正常行为,但 Apple 似乎并不期望这种行为。我们在获取收据的方式上没有任何改变。

我们使用 SwiftyStoreKit 以便于处理。这是我们的代码:

SwiftyStoreKit.fetchReceipt(forceRefresh: false) { result in
    switch result {
    case .success(let receiptData):
        let encryptedReceipt = receiptData.base64EncodedString(options: [])
        Log.info("Fetch receipt success")
        //further code to send the receipt to our server
    case .error(let error):
        observer.send(error: error.localizedDescription)
    }
}

我们的流程是否不正确,或者我们如何在不获取收据的情况下验证用户是否具有有效订阅?我们在这里有点困惑。有人可以在这里给我们任何建议吗?

您当前的流程没有提供很好的用户体验;他们启动您的应用程序并看到 iTunes 帐户密码提示,但没有任何关于它出现原因的上下文。

我建议您采用类似于以下的流程:

  1. 当您在此设备上验证订阅时,向 UserDefaults 添加一个布尔值
  2. 当您的应用程序启动时,检查此值。
  3. 如果值为真则刷新收据并验证订阅
  4. 如果值为 false/not,则显示您的商店界面。确保您的商店界面包含 "Restore" 按钮。
  5. 现在,如果用户知道他们有订阅,他们可以点击恢复,您可以验证他们的订阅;如果此时系统提示他们输入 iTunes 帐户密码,他们就会明白原因。
  6. 如果用户没有订阅,则他们可以购买一个。即使他们确实有一个并开始购买,StoreKit 也会处理并告诉他们他们已经有一个有效的订阅
  7. 无论订阅是购买还是恢复,您都将获得订阅的交易。然后您可以更新 UserDefaults 并按照步骤 3 继续。

或者,在尝试刷新之前检查本地收据是否存在。如果收据不存在,则可能会提示用户输入 iTunes 密码:

if let receiptDataURL = appStoreReceiptURL,
   let _ = try? Data(contentsOf: receiptDataURL)  {
       SwiftyStoreKit.fetchReceipt(forceRefresh: false) { result in

       switch result {
           case .success(let receiptData):

               let encryptedReceipt = receiptData.base64EncodedString(options: [])

               Log.info("Fetch receipt success")

    //further code to send the receipt to our server

           case .error(let error):
               observer.send(error: error.localizedDescription)
       }
   }
}  else {
    // Display purchase/restore interface
}