22

我正在使用 Apple 托管的内容实施应用内购买。以前我使用 Urban Airship 来托管我的内容,并使用他们的 SDK 来提供应用内商店 UI 和购买功能。

由于 Urban Airship 在今年 7 月停止了对 IAP 的支持,我需要更换它。

Urban Airship SDK 支持更新购买的内容。我看到 StoreKit 提供了这个功能(至少在一定程度上),但不确定如何正确实现内容更新本身。

SKProduct有一个downloadContentVersion指定可从 Apple 下载的内容的版本。我会跟踪应用程序中当前下载的版本 - 所以我知道什么时候有可用的更新。

我坚持的部分是如何实际下载更新的内容?

我的第一个想法是为该特定购买进行恢复,但似乎没有办法恢复个别产品(仅限所有产品)。第二个想法是重新购买产品,但这会向用户显示一个提醒,表明他们将再次被收费 - 但是他们不会被收费,因为在重新购买后会显示另一个提醒,通知用户内容已经购买,将免费重新下载——但对我来说,这感觉像是一种糟糕的用户体验,他们可能不一定知道在同意购买之前不会再次收费。

文档说不要自己创建SKDownload实例,所以我不能只创建一个并将其添加到下载队列中。

使用 Apple 托管的内容时,我应该如何为应用内购买实施内容更新?

4

2 回答 2

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];
    }
}
于 2013-06-17T11:56:42.800 回答
5

我与 WWDC 的一些 Store Kit 工程师交谈并问了他们这个问题。

他们的反应并不像我希望的那样积极。

他们确认没有用于将单个产品恢复为错误的 API,并鼓励我提交两个错误(一个是针对商店套件中该 API 的增强请求,另一个是关于升级产品这一领域的文档太少) .

至于眼前的问题,他们的建议是要么实现“全部更新”功能,其中恢复所有产品以获取它们的交易和下载对象(我最终选择的选项),或者类似地恢复所有产品,但忽略除您尝试更新的产品之外的所有产品(最终毫无意义,因为如果您对每个产品都采用这种方法,您将多次恢复所有产品)。

一旦我这样做,我将使用我提交的错误的雷达编号更新此答案,以便其他人可以在必要时复制它们(记住,欺骗碰撞错误!)

编辑

我已经报告了这个错误,它的编号是 rdar://14174034 - 随意复制。

于 2013-06-16T10:07:47.083 回答