使用Apple托管的内容进行应用程序内购买时更新内容

Jas*_*ien 22 in-app-purchase ios

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

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

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

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

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

我的第一个想法是为特定的购买做一个恢复,但似乎没有办法恢复单个产品(只有所有产品).第二个想法只是重新购买产品,但这会向用户发出警报,表明他们将再次收费 - 但是,他们不会被收费,因为重新购买后会显示另一个警报,通知用户内容已经购买并将免费重新下载 - 但对我而言,这感觉就像一个糟糕的用户体验,他们可能不一定知道在同意购买之前不会再收取费用.

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

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

Joh*_*oft 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"];
Run Code Online (Sandbox Code Playgroud)

然后,如果您发现该版本已更改,则可以提示用户进行更新.如果他们同意,那么就开始恢复.

[[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];
    }
}
Run Code Online (Sandbox Code Playgroud)


Jas*_*ien 5

我和WWDC的一些Store Kit工程师进行了交谈,并向他们提出了这个问题.

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

他们确认缺少用于将单个产品还原为错误的API,并鼓励我提交两个错误(一个用于商店工具包中针对该API的增强请求,另一个用于在此升级产品领​​域的文档太少) .

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

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

编辑

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