如果您正在使用服务器端收据验证,是否有必要刷新收据?
Is it ever necessary to refresh receipt if you are using doing server-side receipt validation?
我创建了一个具有自动续订订阅功能的应用程序。
以下是我用来了解用户是否有有效订阅的逻辑。
- 每当调用
SKPaymentQueue
的 paymentQueue(_:updatedTransactions:)
时,我都会尝试使用以下步骤执行收据验证
- 我检查本地收据是否存在。如果它不存在,我使用
SKReceiptRefreshRequest
刷新收据。
- 我将收据信息发送到 App Store 服务器的
verifyReceipt
端点。
- 服务器 return 的响应包含有关订阅到期日期的信息。
- 我将到期日期存储在应用程序中,并根据用户是否有有效订阅显示适当的 UI。
App Store 审核多次拒绝我的应用程序,因为 SKReceiptRefreshRequest
错误。我无法重现 App Store 审查委员会面临的错误。
在网上搜索解决问题的过程中,我了解了以下关于本地收据的事实-
- 本地收据始终存在于生产模式中。如果应用程序是使用 Testflight 安装或在测试期间安装的,则本地收据可能不会出现。 (link)
- App Store 服务器将 return 最新的订阅信息,即使它发送了旧的本地收据 (link)
从以上2条信息,我推断在生产环境中没有必要调用SKReceiptRefreshRequest
因为App Store服务器会提供最新的细节,即使本地收据是旧的和本地的生产中始终存在收据。
为了让我的应用程序通过 App Store 审核,我决定删除 SKReceiptRefreshRequest
,因为它会在 Testflight 构建中给出错误,并且在生产中不需要。
任何人都可以确认我这样做是否正确吗?
我已经通过以下方式生成收据并将生成的收据发送到服务器进行验证:
你的逻辑有多个缺陷:
1) paymentQueue(_:updatedTransactions:)
在后台调用并且(据我所知)已经更新了本地收据。此外,从 App Store 下载的应用程序始终包含收据。所以没有必要在那个方法中调用SKReceiptRefreshRequest
。
2) SKReceiptRefreshRequest
要求用户输入他的密码以允许收据刷新。由于您触发了 paymentQueue(_:updatedTransactions:)
内的方法,该方法在后台调用,我认为这就是刷新请求失败并且 Apple 拒绝您的应用程序的问题。尽管如此,这种方法有其存在的理由:在生产中,您需要它来允许用户在重新安装应用程序或在其他设备上恢复购买,并且对于调试和 TestFlight 构建,您需要它来获取最新的收据。
3) 您不应将收据从您的应用程序发送到 Apple 的端点
Warning
Do not call the App Store server verifyReceipt endpoint from your app. You can't build a trusted connection between a user’s device and the App Store directly, because you don’t control either end of that connection, which makes it susceptible to a man-in-the-middle attack.
如何进行?
我建议做以下事情:
1) 不要在paymentQueue(_:updatedTransactions:)
中触发SKReceiptRefreshRequest
2) 如果尚未完成,请在您的应用中提供一个 "restore purchases" 按钮(调用 SKReceiptRefreshRequest
)
3) 实施 local or server-to-server 收据验证
我创建了一个具有自动续订订阅功能的应用程序。
以下是我用来了解用户是否有有效订阅的逻辑。
- 每当调用
SKPaymentQueue
的paymentQueue(_:updatedTransactions:)
时,我都会尝试使用以下步骤执行收据验证 - 我检查本地收据是否存在。如果它不存在,我使用
SKReceiptRefreshRequest
刷新收据。 - 我将收据信息发送到 App Store 服务器的
verifyReceipt
端点。 - 服务器 return 的响应包含有关订阅到期日期的信息。
- 我将到期日期存储在应用程序中,并根据用户是否有有效订阅显示适当的 UI。
App Store 审核多次拒绝我的应用程序,因为 SKReceiptRefreshRequest
错误。我无法重现 App Store 审查委员会面临的错误。
在网上搜索解决问题的过程中,我了解了以下关于本地收据的事实-
- 本地收据始终存在于生产模式中。如果应用程序是使用 Testflight 安装或在测试期间安装的,则本地收据可能不会出现。 (link)
- App Store 服务器将 return 最新的订阅信息,即使它发送了旧的本地收据 (link)
从以上2条信息,我推断在生产环境中没有必要调用SKReceiptRefreshRequest
因为App Store服务器会提供最新的细节,即使本地收据是旧的和本地的生产中始终存在收据。
为了让我的应用程序通过 App Store 审核,我决定删除 SKReceiptRefreshRequest
,因为它会在 Testflight 构建中给出错误,并且在生产中不需要。
任何人都可以确认我这样做是否正确吗?
我已经通过以下方式生成收据并将生成的收据发送到服务器进行验证:
你的逻辑有多个缺陷:
1) paymentQueue(_:updatedTransactions:)
在后台调用并且(据我所知)已经更新了本地收据。此外,从 App Store 下载的应用程序始终包含收据。所以没有必要在那个方法中调用SKReceiptRefreshRequest
。
2) SKReceiptRefreshRequest
要求用户输入他的密码以允许收据刷新。由于您触发了 paymentQueue(_:updatedTransactions:)
内的方法,该方法在后台调用,我认为这就是刷新请求失败并且 Apple 拒绝您的应用程序的问题。尽管如此,这种方法有其存在的理由:在生产中,您需要它来允许用户在重新安装应用程序或在其他设备上恢复购买,并且对于调试和 TestFlight 构建,您需要它来获取最新的收据。
3) 您不应将收据从您的应用程序发送到 Apple 的端点
Warning
Do not call the App Store server verifyReceipt endpoint from your app. You can't build a trusted connection between a user’s device and the App Store directly, because you don’t control either end of that connection, which makes it susceptible to a man-in-the-middle attack.
如何进行?
我建议做以下事情:
1) 不要在paymentQueue(_:updatedTransactions:)
SKReceiptRefreshRequest
2) 如果尚未完成,请在您的应用中提供一个 "restore purchases" 按钮(调用 SKReceiptRefreshRequest
)
3) 实施 local or server-to-server 收据验证