首页 > 代码库 > In-App Purchase Programming Guide----(七) ----Restoring Purchased Products

In-App Purchase Programming Guide----(七) ----Restoring Purchased Products

Restoring Purchased Products

Users restore transactions to maintain access to content they’ve already purchased. For example, when they upgrade to a new phone, they don’t lose all of the items they purchased on the old phone. Include some mechanism in your app to let the user restore their purchases, such as a Restore Purchases button. Restoring purchases prompts for the user’s App Store credentials, which interrupts the flow of your app: because of this, don’t automatically restore purchases, especially not every time your app is launched.

In most cases, all your app needs to do is refresh its receipt and deliver the products in its receipt. The refreshed receipt contains a record of the user’s purchases in this app, on this device or any other device. However, some apps need to take an alternate approach for one of the following reasons:

  • If you use Apple-hosted content, restoring completed transactions gives your app the transaction objects it uses to download the content.

  • If you need to support versions of iOS earlier than iOS 7, where the app receipt isn’t available, restore completed transactions instead.

  • If your app uses non-renewing subscriptions, your app is responsible for the restoration process.

Refreshing the receipt asks the App Store for the latest copy of the receipt. Refreshing a receipt does not create any new transactions. Although you should avoid refreshing multiple times in a row, this action would have same result as refreshing it just once.

Restoring completed transactions creates a new transaction for every completed transaction the user made, essentially replaying history for your transaction queue observer. While transactions are being restored, your app maintains its own state to keep track of why it’s restoring completed transactions and how it needs to handle them. Restoring multiple times creates multiple restored transactions for each completed transaction.

Note: If the user attempts to purchase a product that’as already been purchased, rather than using your app’s restoration interface, the App Store creates a regular transaction instead of a restore transaction. The user isn’t charged again for the product. Treat these transactions the exact same way you treated the original transactions.

 

Give the user an appropriate level of control over what content is redownloaded. For example, don’t download three years worth of daily newpapers or hundreds of megabytes worth of game levels all at once.

Refreshing the App Receipt

Create a receipt refresh request, set a delegate, and start the request. The request supports optional properties for obtaining receipts in various states during testing such as expired receipts—for details, see the values for the initWithReceiptProperties: method of SKReceiptRefreshRequest.

request = [[SKReceiptRefreshRequest alloc] init];
request.delegate = self;
[request start];

After the receipt is refreshed, examine it and deliver any products that were added.

Restoring Completed Transactions

Your app starts the process by calling the restoreCompletedTransactions method of SKPaymentQueue. This sends a request to the App Store to restore all of your app’s completed transactions. If your app sets a value for the applicationUsername property of its payment requests, as described in “Detecting Irregular Activity,” use the restoreCompletedTransactionsWithApplicationUsername: method to provide the same information when restoring transactions.

The App Store generates a new transaction for each transaction that was previously completed. The restored transaction has a reference to the original transaction: instances of SKPaymentTransaction have a originalTransaction property, and the entries in the receipt have an Original Transaction Identifier field.

Note: The date fields have slightly different meanings for restored purchases. For details, see the Purchase Date and Original Purchase Date fields in Receipt Validation Programming Guide.

 

Your transaction queue observer is called with a status of SKPaymentTransactionStateRestored for each restored transaction, as described in “Waiting for the App Store to Process Transactions.” The action you take at this point depends on the design of your app.

  • If your app uses the app receipt and doesn’t have Apple-hosted content, this code isn’t needed because your app doesn’t restore completed transactions. Finish any restored transactions immediately.

  • If your app uses the app receipt and has Apple-hosted content, let the user select which products to restore before starting the restoration process. During restoration, re-download the user-selected content and finish any other transactions immediately.

    NSMutableArray *productIDsToRestore = <# From the user #>;
    SKPaymentTransaction *transaction = <# Current transaction #>;
     
    if ([productIDsToRestore containsObject:transaction.transactionIdentifier]) {
        // Re-download the Apple-hosted content, then finish the transaction
        // and remove the product identifier from the array of product IDs.
    } else {
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    }
  • If your app doesn’t use the app receipt, it examines all completed transactions as they’re restored. It uses a similar code path to the original purchase logic to make the product available and then finishes the transaction.

    Apps with more than a few products, especially products with associated content, let the user select which products to restore instead of restoring everything all at once. These apps keep track of which completed transactions need to be processed as they’re restored and which transactions can be ignored by finishing them immediately.

NextPrevious