我正在为我的应用实施应用内购买(即将发布),并为iOS6和iOS7提供支持。我的问题与iOS6和iOS7上的非续订订阅机制之间的差异有关,更具体地说,关于如何实现恢复。为了适应iOS6和iOS7,我实现了一个服务器端解决方案来启用恢复。我可以选择允许用户创建可以在不同设备上使用的用户名/密码(如果数据丢失,则使用同一设备)进行恢复。我的大部分工作基本上都在工作,但随着我的测试进展,我发现了一些奇怪的东西。
iOS7恢复过程的初始部分使用SKReceiptRefreshRequest来刷新应用中的收据。当我从iOS7设备上删除应用程序时,重新安装(此时没有收据;使用iExplorer进行测试),并进行恢复,SKReceiptRefreshRequest恢复10次购买(我在测试期间为此特定用户创建) 。其中一个是非消耗品, 九个收据不续订 。这让我很困惑。从Apple文档中,我预计只会在刷新的收据中看到非消费品购买。来自https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateLocally.html:
“消耗品和非续订订阅:应用程序内” 购买消费品的收据或不续订 购买时,订阅会添加到收据中。它是 保留在收据中,直到您的应用程序完成该交易。 在那之后,它将在下次从收据中删除 收据已更新 - 例如,当用户进行另一次购买时 或者如果您的应用明确刷新收据。“
与非续订订阅相关,来自https://developer.apple.com/in-app-purchase/In-App-Purchase-Guidelines.pdf:
使用iCloud或您自己的服务器跟踪购买情况并允许用户访问 将购买的订阅恢复到单个所有的iOS设备 用户
任何人都有任何见解?
问题: 为什么SKReceiptRefreshRequest会在收据中留下非续订产品的购买?这是Apple文档中的错误吗? 或者还有其他事情发生了吗?
14年2月23日;更新:我最近向Apple发布了一个错误报告。还没回来。虽然,实际上,我不希望这个“虫子”消失!
15年10月20日;更新:似乎Apple实际上已经解决了这个“错误”。现在,当我使用SKReceiptRefreshRequest
进行恢复时(这似乎是Apple推荐的恢复方法,请参阅https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Restoring.html),我现在不获得不续订订阅购买显示在收据中。我只获得非消耗品(我的应用程序只有非续订订阅和非消耗品购买)。在我写完这篇文章后,我会立即向Apple提交一份错误报告,他们的文档对预期的行为不明确。
到目前为止,我对此的测试包括我的应用程序在iOS 8.4和iOS9上运行(实际上因为我没有正确的设备运行生产版本,所以9.1 beta),所以看来这是Apple的服务器端更改并不严格地说是iOS /设备方面的变化。另请注意,到目前为止,我的所有测试都是在我的应用程序的开发版本中,因此在应用内购买沙箱中也是如此。我很快就会进行生产测试。
15年12月3日;更新; 在Apple技术支持的提示下,我又进行了一些测试。这一次,在运行iOS9.2 beta 4(13C75)的iPad上。现在看来我们已经恢复“正常”,不续订订阅。也就是说,当我进行恢复时,我再次看到收据中没有续订订阅。
答案 0 :(得分:3)
请注意,在App Receipt中持续不续订订阅不能保证App Store审阅者不会接受。成功取决于特定的评论者。我最近收到了Apple发来的消息:
我们发现您的应用包含之前要恢复的功能 通过输入用户的Apple ID和购买的应用内购买产品 密码。但是,非续订订阅应用程序内购买不能 以这种方式恢复。
修改二进制文件以删除此功能是合适的。 如果您希望用户能够恢复不续订 订阅应用内购买产品,您需要实施您的 自己的恢复机制。
所以提交应用程序的最后一次尝试是不吉利的。与前几个不同。
现在,我的计划是将应用程序收据存储在iCloud Key-Value Storage上并自动恢复所有购买。它会满足苹果的要求:
对于非续订订阅,请使用iCloud或您自己的服务器保留 持久记录。 (c)Store Kit编程指南
这是Apple为此目的提供的代码:
#if USE_ICLOUD_STORAGE
NSUbiquitousKeyValueStore *storage = [NSUbiquitousKeyValueStore defaultStore];
#else
NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
#endif
NSData *newReceipt = transaction.transactionReceipt;
NSArray *savedReceipts = [storage arrayForKey:@"receipts"];
if (!receipts) {
// Storing the first receipt
[storage setObject:@[newReceipt] forKey:@"receipts"];
} else {
// Adding another receipt
NSArray *updatedReceipts = [savedReceipts arrayByAddingObject:newReceipt];
[storage setObject:updatedReceipts forKey:@"receipts"];
}
[storage synchronize];
答案 1 :(得分:2)
这也令我感到困惑。在查看文档很多次之后,我终于在Receipt Validation Programming Guide的收据字段说明中看到了以下内容:
添加耗材的应用内购买收据 购买时的收据。它一直保留在收据中,直到 您的应用完成该交易。在那之后,它被删除 从下次收据更新时的收据 - 例如, 当用户进行另一次购买或明确表示您的应用时 刷新收据。
非消费品的应用内购买收据, 自动续订,不续订或免费 订阅无限期地保留在收据中。
In-App Purchase Programming Guide中“持久使用应答程序收据”部分仍然表示消费品和非续订订阅的处理方式相同。
我猜测我们观察到IAP文档过时的行为?我希望如此。
答案 2 :(得分:0)
Apple 推荐以下内容(阅读概览 here)
<块引用>... 自动续订订阅的收入会随着时间的推移而增长,因为 续订交易永远保留在收据中。 优化 性能,App Store 可能会截断沙箱收据以删除旧的 交易。在验证交易收据时 沙盒环境,考虑创建新的测试帐户而不是 重复使用旧帐户来测试订阅购买。