Apple 应用内购买和收据刷新

Apple In-App Purchase and Receipt Refresh

我有一个业余项目,我最近在开发我的收据管理器,以使其更强大并更多地依赖于应用程序的收据,而不是在交易后持久存储一个值。

但是,有两个要点,虽然我在网上阅读了 Apple 文档和其他答案,但我仍然感到困惑:

1.当用户恢复购买时,收据是否会刷新?

我在沙盒中做了几次测试,我看到恢复时,收据会刷新,当我通过 iTunes 服务器验证收据时,它 returns JSON 包括最新交易。这非常有用,因为即使我 close/open 应用程序,应用程序收据也会更新,我可以随时验证它而无需刷新它。 但是,在生产中,这不起作用。恢复购买后应用程序收据没有刷新,我的用户被要求连续恢复购买。有人可以回答这个问题吗?

2。刷新收据请求是否会触发要求在生产中提供 Apple ID 密码的警报?

从前面的观点来看,我认为可以,我会在用户恢复购买后强制刷新收据。但是,在开发/沙箱中,每次我尝试刷新收据时,我都会被要求插入沙箱用户的通行证(尽管我可以在要求刷新之前无需密码请求就可以恢复购买)。我读了很多关于这个的文章,有人说这可能不会在生产中发生。你们有没有人对此做出澄清?

注意: 我知道在恢复/购买时我会用收据取回交易,但是,我需要使用 App Receipt 来验证交易(这也是 Apple 要求做的)。

提前致谢。

1。正在刷新收据

理论上,调用恢复购买应该得到最新的收据。如果您遇到问题,请查看 SKReceiptRefreshRequest。通常,当恢复购买的调用遇到错误时,我会在生产中使用它。

明智地使用它,触发 API 可以导致显示 App Store 的登录提示。

2。何时要求用户登录?

遗憾的是,我看到了这种变化,所以我无法给出明确的答案。通常情况下,恢复购买的调用不应触发登录。显式使用 SKReceiptRefreshRequest 会。

如果用户未登录商店,调用任何商店 API 尝试购买或恢复购买可能会触发登录流程。

Apple 的说法

来自docs

Refreshing a receipt doesn't create new transactions; it requests the latest copy of the receipt from the App Store. Refresh the receipt only once; refreshing multiple times in a row has the same result. Restoring completed transactions creates a new transaction for every transaction previously completed, essentially replaying history for your transaction queue observer. Your app maintains its own state to keep track of why it’s restoring completed transactions and how to handle them. Restoring multiple times creates multiple restored transactions for each completed transaction.

我的推荐

  1. 存储您在设备上使用的最后一张收据的哈希值。您可以使用此散列来检查最新的收据,以便了解是否有任何更改。每当您的应用程序恢复时,您始终可以检查当前收据哈希值是否与上次缓存的值不同。
  2. 尝试尽快提交收据。通常在应用程序启动时。
  3. 如果用户试图手动恢复购买,我会先调用 restoreCompletedTransactions。这可以触发 App Store 登录,但通常不太可能。大多数时候这就足够了,因为设备上的收据通常是最新的。
  4. 如果用户尝试再次恢复购买,或者如果调用失败,则转到 SKReceiptRefreshRequest 以保证收到新收据。
  5. 使用 SKReceiptRefreshRequest 时,我建议将其包装在 UIAlertController 后面。我通常会显示一些表明它失败的东西,并且有一个使用该请求的 "Retry" 按钮。这将触发新的商店登录。

使用restoreCompletedTransactions 获取设备知道的所有已完成交易的回放。

  1. When a user restore their purchase, does the receipt get refreshed?

是的,应该。但这听起来也像是你在做一些服务器端验证?如果是这种情况,您可以将用户的 any 收据发送到 /verifyReceipt 端点以获取最新状态。您不需要发送最新的收据,因为 /verifyReceipt 也会刷新它。

  1. Does the refresh receipt request triggers an alert asking for the Apple ID's password in production?

没有关于此的明确 Apple 文档,但如果应用程序中没有收据文件(在生产中很少见),它肯定会。但是,如果您正在进行服务器端验证(请参阅#1),那么您可以发送您拥有的任何收据,而无需刷新它。因此,如果什么都不存在,您只会刷新收据,这将触发登录。请记住,在沙盒中安装后设备上不存在收据文件 - 仅在购买后存在。这与安装后生成收据文件的生产有很大不同。

从你正在尝试做的事情来看,我的建议是检查启动时是否存在任何收据文件,将其发送到 /verifyReceipt 以获取用户和缓存的最新状态结果。您可以在每次启动应用程序时执行此操作。

在一个完美的世界中,您将收据存储在服务器端并在那里保持最新状态,但您提到了副项目,所以这听起来有点矫枉过正。然而,一个开箱即用的解决方案可以正确地实现所有这些并且可以随你扩展——比如 RevenueCat——是另一种选择(免责声明:我在那里工作)。

经过多次测试并在生产环境中发送我的应用程序后,我现在能够正确回答我的问题:

1.当用户恢复购买时,收据是否会刷新?

,这对于沙盒来说是直接的,但是问题是收据不包括非消耗品采购。 换句话说,这意味着收据将包括购买的订阅,但您不会找到非消耗品的购买。 但是,当用户恢复或购买时,您会在 return 中获取交易,并且您可以提取非消耗品,并将此信息存储在 UserDefaults 或 Keychain 之类的地方,以便在用户打开您的时使用它们应用程序。 对于其余部分,最好的方法是在打开应用程序时始终验证和检查收据。

2。刷新收据请求是否会触发一个警报,要求在生产中提供 Apple ID 的密码?

。肯定是第一次。

感谢 Danielenc 的回答仍然有用。