我正在使用Apple托管的内容实施应用内购买。以前我使用Urban Airship来托管我的内容,并使用他们的SDK来提供应用内商店用户界面和购买功能。
由于Urban Airship今年7月停止了对IAP的支持,我需要更换它。
Urban Airship SDK支持更新购买的内容。我看到StoreKit提供了这种功能(至少在一定程度上)但不确定如何正确实现内容更新本身。
SKProduct
有一个downloadContentVersion
,用于指定可从Apple下载的内容版本。我会跟踪应用程序当前下载的版本 - 所以我知道何时有更新。
我遇到的部分是如何实际下载更新的内容?
我的第一个想法是为该特定购买进行还原,但似乎无法恢复单个产品(仅限所有产品)。第二个想法只是重新购买产品,但这会向用户发出警报,表明他们将再次收费 - 但是,他们不会被收费,因为重新购买后会显示另一个警报,通知用户内容已经购买并将免费重新下载 - 但对我而言,这感觉就像一个糟糕的用户体验,他们可能不一定知道在同意购买之前不会再收取费用。
文档说不要自己创建SKDownload
个实例,所以我不能只创建一个并将其添加到下载队列。
在使用Apple托管的内容时,我应该如何为应用内购买实施内容更新?
答案 0 :(得分:16)
感谢Jasarien与Apple联系。以下是找到此主题的任何人尝试了解如何更新应用内内容的示例代码。
首先,当您从SKProductsRequest获得响应时,请针对您之前下载的内容的版本检查downloadContentVersion。您可以使用以下代码获取现有内容的内容版本:
NSString *pathToYourContent = @""; // Put your path here
NSString *contentInfoPath = [pathToYourContent stringByAppendingPathComponent:@"ContentInfo.plist"];
NSDictionary *contentInfo = [NSDictionary dictionaryWithContentsOfFile:contentInfoPath];
NSString *contentVersion = [contentInfo objectForKey:@"ContentVersion"];
NSString *iapProductIdentifier = [contentInfo objectForKey:@"IAPProductIdentifier"];
然后,如果您发现该版本已更改,则可以提示用户进行更新。如果他们同意,那就开始恢复。
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
然后,当事务开始进入时,您需要决定接受哪些以及忽略哪些事务。在这个下载歌曲内容的应用程序的示例中,我有一个YHSongVersion类,它存储我们下载的所有歌曲的ID和版本,并且这些存储在数组self.ownedSongVersions中。此示例将接受版本号不同或我们没有内容的任何恢复。
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStateFailed:
break;
case SKPaymentTransactionStatePurchased:
[self provideContentForTransaction:transaction];
break;
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStateRestored:
[self restorePurchaseIfRequired:transaction];
break;
}
}
}
/// On a restore download the content if either we don't have the content or the version number has changed.
- (void)restorePurchaseIfRequired:(SKPaymentTransaction *)transaction {
BOOL haveSong = NO;
SKDownload *download = [transaction.downloads objectAtIndex:0];
for (YHSongVersion *ownedSongVersion in self.ownedSongVersions) {
BOOL isSongForThisDownload = [ownedSongVersion.iapProductIdentifier isEqualToString:download.contentIdentifier];
if (isSongForThisDownload) {
haveSong = YES;
BOOL hasDifferentVersionNumber = ![ownedSongVersion.contentVersion isEqualToString:download.contentVersion];
if (hasDifferentVersionNumber) {
[self provideContentForTransaction:transaction];
}
else {
// Do nothing
[self completeTransaction:transaction];
NSLog(@"Ignoring restore for %@", ownedSongVersion.iapProductIdentifier);
}
}
}
if (!haveSong) {
[self provideContentForTransaction:transaction];
}
}
答案 1 :(得分:5)
我和WWDC的一些商店工具包工程师交谈,并问他们这个问题。
他们的反应并不像我希望的那样积极。
他们确认没有用于将单个产品还原为错误的API,并鼓励我提交两个错误(一个用于商店工具包中针对该API的增强请求,另一个用于在该区域周围的文档太稀疏)升级产品)。
至于眼前的问题,他们的建议是实施“全部更新”功能,其中所有产品都已恢复以获取其交易及其下载对象(我最终选择的选项),或类似地,恢复所有产品,但忽略除了您要更新的产品之外的所有产品(毫无意义,最终,因为如果您对每种产品都采用这种方法,您将多次恢复所有产品)。
一旦我这样做,我会用我提交的错误的雷达号更新这个答案,以便其他人可以在必要时复制它们(记住,欺骗错误!)
我已报告该错误,其编号为rdar:// 14174034 - 随意复制。