throbber
In-App Purchase
`Programming Guide
`
`

`

`Contents
`
`Introduction 5
`At a Glance 5
`Understand Products and Design Your App 5
`All Apps Implement Core Behavior 6
`Some Apps Implement Additional Behavior 6
`Apps and Products are Submitted for Review 6
`See Also 6
`
`Designing Your App’s Store 7
`Understanding What You Can Sell Using In-App Purchase 7
`Creating Products in iTunes Connect 8
`Types of Product 8
`Differences Between Product Types 9
`
`Displaying Your App’s Store UI 11
`Getting a List of Product IDs 11
`Embedding Product IDs in the App Bundle 12
`Fetching Product IDs from Your Server 12
`Retrieving Product Information 14
`Present Your Store UI 15
`
`Requesting Payment 17
`Creating a Payment Request 17
`Submitting a Payment Request 18
`Suggested Testing Steps 18
`Sign In to the iTunes Store with Your Test Account 19
`Verify Your Observer Code 19
`Test Fetching the List of Products 19
`Test a Products Request 20
`Test a Payment Request 20
`
`Delivering Products 21
`Waiting for the Store to Process Transactions 21
`Persisting the Purchase 23
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`2
`
`

`

`Contents
`
`Persisting Using User Defaults or iCloud 23
`Persisting Using Your Own Server 25
`Making the Product Available 25
`Finishing the Transaction 25
`Suggested Testing Steps 26
`Test a Successful Transaction 26
`Verify That Transactions Are Finished 26
`
`Providing Purchased Content 27
`Unlocking Local Content 28
`Downloading Hosted Content from Apple’s Server 28
`Downloading Content from Your Own Server 29
`Locating and Managing Downloaded Content 29
`
`Working with Subscriptions 30
`Calculating a Subscription’s Active Period 30
`Expiration and Renewal 31
`Cancellation 32
`Cross-Platform Considerations 32
`The Test Environment 33
`
`Preparing for App Review 34
`Submitting Products for Review 34
`Receipts in the Test Environment 34
`
`Document Revision History 36
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`3
`
`

`

`Figures, Tables, and Listings
`
`Designing Your App’s Store 7
`Table 1-1
`Comparison of product types 9
`
`Displaying Your App’s Store UI 11
`Figure 2-1
`Stages of the purchase process—displaying store UI 11
`Table 2-1
`Comparison of approaches for obtaining product identifiers 11
`Listing 2-1
`Retrieving product information 14
`Listing 2-2
`Formatting a product’s price 16
`
`Requesting Payment 17
`Figure 3-1
`Stages of the purchase process—requesting payment 17
`Listing 3-1
`Creating a payment request 17
`
`Delivering Products 21
`Figure 4-1
`Stages of the purchase process—delivering products 21
`Table 4-1
`Transaction statuses and corresponding actions 21
`Listing 4-1
`Responding to transaction statuses 22
`
`Working with Subscriptions 30
`Figure 6-1
`Example subscription timeline 30
`Table 6-1
`Timeline of a sample subscription 30
`
`Preparing for App Review 34
`Figure 7-1
`Development, review, and production environments 34
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`4
`
`

`

`Introduction
`
`In-App Purchase allows you to embed a store inside your app using the Store Kit framework. This framework
`connects to the App Store on your app’s behalf to securely process payments from users, prompting them to
`authorize payment. The framework then notifies your app, which provides the purchased items to users. Use
`In-App Purchase to collect payment for additional features and content.
`
`At a Glance
`For example, using In-App Purchase, you can implement the following scenarios:
`
` ● A basic version of your app with additional premium features
`
` ● A magazine app that lets users purchase and download new issues
`
` ● A game that offers new environments (levels) to explore
`
` ● An online game that allows players to purchase virtual property
`
`Understand Products and Design Your App
`Understanding what kinds of products and behaviors are supported by In-App Purchase lets you design your
`app and in-app store to make the best use of this technology.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`5
`
`

`

`Introduction
`See Also
`
`Relevant Sections: “Designing Your App’s Store” (page 7)
`
`All Apps Implement Core Behavior
`All products require certain basic behavior in your app to support the basic In-App Purchase flow of letting
`the user select a product, requesting payment for the product, and delivering the purchased product.
`
`Relevant Sections: “Displaying Your App’s Store UI” (page 11), “Requesting Payment” (page 17),
`“Delivering Products” (page 21)
`
`Some Apps Implement Additional Behavior
`Some products require aditional behavior app: products that include digital assets need your app to perform
`the download, and subscriptions need your app to keep track of when the user has an active subscription.
`
`Relevant Sections: “Providing Purchased Content” (page 27), “Working with Subscriptions” (page
`30)
`
`Apps and Products are Submitted for Review
`When you are done developing and testing, you submit your app and your In-App Purchase products for
`review.
`
`Relevant Sections: “Preparing for App Review” (page 34)
`
`See Also
`iTunes Connect Developer Guide describes how to use iTunes Connect, in particular, how to create and
`configure your app’s products.
`
` ●
`
` ●
`
`Receipt Validation Programming Guide describes how to work with receceipts, in particular, the record of
`sucessful in-app purchases.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`6
`
`

`

`Designing Your App’s Store
`
`The first step in designing your app’s store is to determine which types of product you need to use to build
`the user experience you designed for in your app. A product is something you want to sell in your app’s store.
`You create and configure products in iTunes Connect, and your app interacts with products using the SKProduct
`and SKProductsRequest classes.
`
`Understanding What You Can Sell Using In-App Purchase
`You can use In-App Purchase to sell content, app functionality, and services:
`
` ●
`
`Content. Deliver digital content or assets, such as magazines, photos, and artwork. Content can also be
`used by the app itself—for example, additional characters and levels in a game, filters in a camera app,
`and stationery in a word processor.
`
` ● App functionality. Unlock behavior, and expand features you’ve already delivered. For example, a free
`game that offers multiplayer mode as an in-app purchase and a free weather app that lets users make a
`one-time purchase to remove ads.
`
` ●
`
`Services. Have users pay for one-time services such as voice transcription, and for ongoing services such
`as access to a collection of data.
`
`You can’t use In-App Purchase to sell real-world goods and services or unsuitable content:
`
` ●
`
`Real-world goods and services. You must deliver a digital good or service within your application when
`using In-App Purchase. Use a different payment mechanism to let your users buy real-world goods and
`services in your app, such as a credit card or payment service.
`
` ● Unsuitable content. Do not use In-App Purchase to sell content that the App Review Guidelines do not
`allow, for example, pornography, hate speech, or defamation.
`
`For detailed information about what you can offer using In-App Purchase, see your license agreement and the
`App Review Guidelines. Reviewing the guidelines carefully before you start coding helps you avoid delays and
`rejection during the review process. If the guidelines don’t address your case in sufficient detail, you can ask
`the App Review team specific questions using the online contact form.
`
`After you know what products you want to sell in your app and you determine that In-App Purchase is the
`appropriate way to sell those products, you need to create the products in iTunes Connect.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`7
`
`

`

`Designing Your App’s Store
`Creating Products in iTunes Connect
`
`Creating Products in iTunes Connect
`
`Before you can start testing code, you need to configure products for your app to interact with. You can
`configure products in iTunes Connect at any time. As you develop your app, expect to configure a few test
`products early on, and come back later to configure additional products as your app’s design develops.
`
`Products are reviewed when you submit your app as part of the app review process. Before users can buy a
`product, it must be approved by the reviewer and you must mark it as “cleared for sale” in iTunes Connect.
`
`A typical timeline for a new app might look as follows:
`
`1.
`
`Create products in iTunes Connect.
`
`2. Write code that uses those products in test environment.
`
`3.
`
`Refine your app design, and go back into iTunes Connect to create additional products or adjust the
`existing products.
`
`4. Continue iterating, refining, and testing, both your app’s code and the products.
`
`5.
`
`Submit the app and products for review.
`
`For details about configuring products in iTunes Connect, see “In-App Purchase” in iTunes Connect Developer
`Guide .
`
`Types of Product
`Product types let you use In-App Purchase in several different situations, by letting the products behave in
`different ways that are appropriate for specific use cases. In iTunes Connect, you select one of the following
`product types:
`
` ●
`
`Consumable products. Items that get used up over the course of running your app. Examples include
`minutes for a Voice over IP app and one-time services such as voice transcription.
`
` ● Non-consumable products. Items that remain available to the user indefinitely on all of the user’s devices.
`They are made available to all of the user’s devices. Examples include content, such as books and game
`levels, and additional app functionality.
`
` ● Auto-renewable subscriptions. Episodic content. Like non-consumable products, auto-renewable
`subscriptions remain available to the user indefinitely on all of the user’s devices. Unlike non-consumable
`products, auto-renewable subscriptions have an expiration date. You deliver new content regularly, and
`users get access to content published during the time period that their subscription is active. When an
`auto-renewable subscription is about to expire, the system automatically renews it on the user’s behalf.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`8
`
`

`

`Designing Your App’s Store
`Differences Between Product Types
`
` ● Non-renewable subscriptions. Subscriptions that don’t involve delivering episodic content. Examples
`include access to a database of historic photos or a collection of flight maps. It is your app’s responsibility
`to make the subscription available on all of the user’s devices and to let users restore the purchase. This
`product type is often used when your users already have an account on your server, which you can use
`to identify them when restoring content. Expiration and the duration of the subscription are also left to
`your app (or your server) to implement and enforce.
`
` ●
`
`Free subscriptions. A way to put free subscription content in Newsstand. After a user signs up for a free
`subscription, the content is available on all devices associated with the user’s Apple ID. Free subscriptions
`do not expire and can be offered only in Newsstand-enabled apps.
`
`Differences Between Product Types
`Each product type is designed for a particular use case. The behavior of different products differs in certain
`ways, as shown in Table 1-1 (page 9). For example, consumable products get used up and subscriptions
`expire, so the store lets the user buy the products of these types multiple times.
`
`Table 1-1
`
`Comparison of product types
`
`Consumable
`
`Non-consumable
`
`Auto-renewable
`
`Non-renewing
`
`Free
`Subscription
`
`Multiple
`times
`
`Once
`
`Multiple times
`
`Multiple times
`
`Once
`
`Not synced
`
`By the system
`
`By the system
`
`By your app
`
`Product
`type
`
`Users
`can buy
`
`Synced
`across
`devices
`
`By the
`system
`
`By the
`system
`
`Always
`
`Restored
`
`Not restored
`
`By the system
`
`By the system
`
`By your app
`
`Once
`
`Always
`
`Always
`
`Once
`
`Appears
`in the
`receipt
`
`Products that expire or get used up—consumable products, auto-renewable subscriptions, and non-renewing
`subscriptions—can be purchased multiple times to get the consumable item again or extend the subscription.
`Non-consumable products and free subscriptions unlock content that remains available to the user indefinitely,
`so these can only be purchased once.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`9
`
`

`

`Designing Your App’s Store
`Differences Between Product Types
`
`Products that do not get used up are made available across all of the user’s devices. These products are also
`restored so users can continue to access their purchased content even after erasing a device or buying a new
`device. Consumable products by their nature are not meant to be synced or restored. Users understand that,
`for example, buying ten more bubbles on their iPhone does not also give them ten bubbles on their iPad.
`
`Store Kit handles the syncing and restoring process for auto-renewable and free subscriptions, and for
`non-consumable products. Your app is responsible for syncing and restoring non-renewable subscriptions.
`
`Non-renewing subscriptions differ from auto-renewable subscriptions in a few key ways which give your app
`the flexibility to implement the correct behavior for your needs:
`
` ●
`
` ●
`
` ●
`
`Your app is responsible for calculating the time period that the subscription is active, and determining
`what content needs to be made available to the user.
`
`Your app is responsible for detecting that a subscription is approaching its expiration date and prompting
`the user to renew the subscription by purchasing the product again.
`
`Your app is responsible for making subscriptions available across all the user’s devices after they are
`purchased. For example, most subscriptions are provided by a server; your server would need some
`mechanism to identify users and associate subscription purchases with the user who purchased them.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`10
`
`

`

`Displaying Your App’s Store UI
`
`In the first part of the purchase process, your app presents its store UI to the user, and then lets the user selects
`a product, as shown in Figure 2-1. The second and third part of the process are described in the two chapters
`that follow this one.
`
`Figure 2-1
`
`Stages of the purchase process—displaying store UI
`
`Getting a List of Product IDs
`To get a list of product identifiers, have your app either read them from a file in your app bundle or fetch them
`from your server. Table 2-1 summarizes the differences between the two approaches. If you offer a fixed list
`of products, such as an in-app purchase to remove ads, embed the list in your app bundle. If your list of product
`identifiers can change without you updating your app, have your app fetch the list from your server.
`
`Table 2-1
`
`Comparison of approaches for obtaining product identifiers
`
`Embedded in the app bundle
`
`Fetched from your server
`
`Used for purchases that
`
`Unlock functionality
`
`Deliver content
`
`List of products can change
`
`When the app is updated
`
`At any time
`
`Requires a server
`
`No
`
`Yes
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`11
`
`

`

`Displaying Your App’s Store UI
`Getting a List of Product IDs
`
`There is no runtime mechanism to fetch a list of all products configured for an app in iTunes Connect. You are
`responsible for managing your app’s list of products and providing that information to your app.
`
`Embedding Product IDs in the App Bundle
`Include a property list file in your app bundle containing an array of product identifiers, such as the following:
`
`<?xml version="1.0" encoding="UTF-8"?>
`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
`"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
`<plist version="1.0">
`<array>
`<string>com.example.level1</string>
`<string>com.example.level2</string>
`<string>com.example.rocket_car</string>
`</array>
`</plist>
`
`To get product identifiers from the property list, locate the file in the app bundle and read it.
`
`NSURL * url = [[NSBundle mainBundle] URLForResource:@"product_ids"
`withExtension:@"plist"];
`NSArray * productIdentifiers = [NSArray arrayWithContentsOfURL:url];
`
`Fetching Product IDs from Your Server
`Store a JSON file on your server with the product identifiers. For example:
`
`[
`
`]
`
`"com.example.level1",
`"com.example.level2",
`"com.example.rocket_car"
`
`To get product identifiers from your server, fetch the JSON file and read it.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`12
`
`

`

`Displaying Your App’s Store UI
`Getting a List of Product IDs
`
`-fetchProductIdentifiersFromURL:(NSURL*)url delegate(id):delegate
`{
`
`dispatch_queue_t global_queue =
`dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
`dispatch_async(global_queue, ^{
`NSError * err;
`NSData * jsonData = [NSData dataWithContentsOfURL:url
`options:NULL
`error:&err];
`
`if (!jsonData) {
`// Handle the error...
`
`} N
`
`SArray * productIdentifiers = [NSJSONSerialization
`JSONObjectWithData:jsonData options:NULL error:&err];
`if (!productIdentifiers) {
`// Handle the error...
`
`} d
`
`ispatch_queue_t main_queue = dispatch_get_main_queue();
`dispatch_async(main_queue, ^{
`[delegate displayProducts:productIdentifiers];
`
`}
`
`});
`
`}
`
`For information about downloading files using NSURLConnection, see “Using NSURLConnection” in URL
`Loading System Programming Guide .
`
`To ensure that your app remains responsive, use a background thread to download the JSON file and extract
`the list of product identifiers. To minimize the data transferred, use standard HTTP caching mechanisms, such
`as the Last-Modified and If-Modified-Since headers.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`13
`
`

`

`Displaying Your App’s Store UI
`Retrieving Product Information
`
`Retrieving Product Information
`To make sure your users see only products that are actually available for purchase, query the App Store before
`displaying your store UI.
`
`Use a products request object to query the App Store. First, create an instance of SKProductsRequest and
`initialize it with a list of product identifiers. The products request retrieves information about valid products,
`along with a list of the invalid product identifiers, and then calls its delegate to process the result. The delegate
`must implement the SKProductsRequestDelegate protocol to handle the response from the App Store.
`Listing 2-1 shows a simple implementation of both pieces of code.
`
`Listing 2-1
`
`Retrieving product information
`
`// Custom method
`- validateProductIdentifiers:(NSArray *)productIdentifiers
`{
`
`SKProductsRequest productsRequest = [[SKProductsRequest alloc]
`initWithProductIdentifiers:[NSSet setWithArray:productIdentifiers]];
`productsRequest.delegate = self;
`[productsRequest start];
`
`} /
`
`/ SKProductsRequestDelegate protocol method
`- (void)productsRequest:(SKProductsRequest *)request
`didReceiveResponse:(SKProductsResponse *)response
`
`self.products = response.products;
`
`for (NSString * invalidProductIdentifier in response.invalidProductIdentifiers)
`
`// Handle any invalid product identifiers.
`
`} [
`
`self displayStoreUI]; // Custom method
`
`{
`
`{
`
`}
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`14
`
`

`

`Displaying Your App’s Store UI
`Present Your Store UI
`
`When the user purchases a product, you need the corresponding product object to create a payment request,
`so keep a reference to the array of product objects that is returned to the delegate. If the list of products your
`app sells can change, you may want to create a custom class that encapsulates a reference to the product
`object as well as other information—for example, pictures or description text that you fetch from your server.
`
`The way you handle invalid product identifiers depends on where the list of product identifiers came from. If
`your app loaded the list from its app bundle, log a note to aid debugging and ignore the invalid identifiers. If
`your app fetched the list from your server, let your server know which product identifiers were invalid. As with
`all other interactions between your app and your server, the details and mechanics of this are up to you.
`
`Present Your Store UI
`The design of your store has an import impact on your in-app sales, so it’s worth investing the time and effort
`to get it right. Design the user interface for your app’s store so that it integrates with the rest of your app. Store
`Kit can’t provide a store UI for you. Only you know your app and its content well enough to design your store
`UI so it showcases your products in their best light and integrates with the rest of your app.
`
`Consider the following guidelines as you design and implement your app’s store UI:
`
`Display a store only if the user can make payments. To determine whether the user can make payments,
`call the canMakePayments class method of the SKPaymentQueue class. If the user can’t make payments (for
`example, because of parental restrictions), either tell the user that the store is not currently supported (by
`displaying appropriate UI) or omit the store portion of your UI entirely.
`
`Expose as much information about a product as possible. Users want to know exactly what they’re going
`to buy. If possible, let users interact with a product. For example, a game that lets the user buy new characters
`can let users run a short course as the new character. Likewise, a drawing app that lets the user buy additional
`brushes can let users draw with the new brush on a small scratch pad. This kind of design gives users an
`opportunity to experience the product and be convinced they want to buy it.
`
`Use the properties of your product objects to populate your store’s user interface. Their properties give you
`information such as the product’s price and its description. Combine this with additional data from your server
`or the app bundle, such as images or demos of your products.
`
`Display prices using the locale and currency returned by the store. Don’t try to convert the price to a different
`currency in your UI, even if the user’s locale and the price’s locale are different. Consider, for example, an
`English-speaking user in China who pays for purchases with a Chinese credit card but prefers the US English
`locale settings for apps. You app would display its UI according to the user’s locale, using US English as requested
`by the user. It would display prices according to the products’ locale, using the currency that corresponds to
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`15
`
`

`

`Displaying Your App’s Store UI
`Present Your Store UI
`
`the Chinese locale (renminbi) with that locale’s formatting. Converting the prices to US dollars (to match the
`US English locale) would be misleading because the user is billed in renminbi, not US dollars. Listing 2-2 shows
`how to correctly format a price using the product’s locale information.
`
`Listing 2-2
`
`Formatting a product’s price
`
`NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
`[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
`[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
`[numberFormatter setLocale:product.priceLocale];
`NSString * formattedPrice = [numberFormatter stringFromNumber:product.price];
`
`After a user selects a product to buy, your app connects to the store to request payment for the product.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`16
`
`

`

`Requesting Payment
`
`In the second part of the purchase process, after the user has chosen to purchase a particular product, your
`app submits payment request to the App Store, as shown in Figure 3-1 (page 17).
`
`Figure 3-1
`
`Stages of the purchase process—requesting payment
`
`Creating a Payment Request
`When the user selects a product to buy, create a payment request using a product object. Populate the quantity
`if needed, and add the payment to the transaction queue to submit it to the App Store for processing. Adding
`a payment object to the queue multiple times results in multiple transactions—the user will be charged multiple
`times and your app will be expected to deliver the product multiple times. Listing 3-1 shows a simplified
`example of the process.
`
`Listing 3-1
`
`Creating a payment request
`
`// At app launch
`[[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
`
`// ...
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`17
`
`

`

`Requesting Payment
`Submitting a Payment Request
`
`// When the user buys a product
`SKPayment payment = [SKPayment paymentWithProduct:product];
`payment.quantity = 2;
`[[SKPaymentQueue defaultQueue] addPayment:payment];
`
`Store Kit calls the transaction queue observer to handle a completed or failed payment request. For information
`about implementing the observer, see “Providing Purchased Content” (page 27).
`
`Submitting a Payment Request
`The transaction queue plays a central role in letting your app communicate with the App Store through the
`Store Kit framework. You add work to the queue that the App Store needs to act on, such as a payment request
`that needs to be processed. After the App Store has processed the request, Store Kit calls your transaction
`queue observer to handle the result. In addition to using the transaction queue for payment requests, your
`app also uses the transaction queue to download hosted content and to find out that subscriptions have been
`renewed, as discussed in “Providing Purchased Content” (page 27) and “Working with Subscriptions” (page
`30).
`
`Register your observer when your app is launched, and make sure that the observer is ready to handle a
`transaction at any time, not only after you add a transaction to the queue. For example, consider the case of
`a user buying something in your app right before going into a tunnel. Your app isn’t able to deliver the
`purchased content because there is no network connection. The next time your app is launched, Store Kit calls
`your transaction queue observer again and delivers the purchased content at that time. Similarly, if your app
`fails to mark a transaction as finished, Store Kit calls the observer every time that your app is launched until
`the transaction in properly marked as finished.
`
`Suggested Testing Steps
`
`Test each part of your code to verify that you have implemented it correctly.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`18
`
`

`

`Requesting Payment
`Suggested Testing Steps
`
`Prerequisite: To perform the suggested tests, you must have at least one product configured for
`your app in iTunes Connect. For more information, see “Creating Products in iTunes Connect” (page
`8).
`
`Sign In to the iTunes Store with Your Test Account
`Create a test user account in iTunes Connect, as described in iTunes Connect Developer Guide .
`
`On a development iOS device, sign out of the iTunes Store in Settings. Then build and run your app from Xcode.
`
`On a development OS X device, sign out of the Mac App Store. Then build your app in Xcode and launch it
`from Finder.
`
`Use your app to make an in-app purchase. When prompted to sign in to the App Store, use your test account.
`Note that the text “[Environment: Sandbox]” appears as part of the prompt, indicating that you are connected
`to the test environment.
`
`If the text “[Environment: Sandbox]” does not appear, that indicates you are using the production environment.
`Make sure you are running a development signed build of your app. Production signed builds use the production
`environment.
`
`Important: Do not use your test user account to sign in to the production environment; if you do, the test
`user account becomes invalid and can no longer be used.
`
`Verify Your Observer Code
`Review the transaction observer’s implementation of the SKPaymentTransactionObserver protocol. Verify
`that it can handle transactions even if you aren’t currently displaying your app’s store UI and even if you didn’t
`recently initiate a purchase.
`
`Locate the call to the addTransactionObserver: method of SKPaymentQueue in your code. Verify that
`your app calls this method at app launch.
`
`Test Fetching the List of Products
`If your product identifiers are embedded in your app, set a breakpoint in your code after they are loaded and
`verify that the instance of NSArray contains the expected list of product identifiers.
`
`If your product identifiers are fetched from a server, manually fetch the JSON file—using a web browser such
`as Safari or a command-line utility such as curl—and verify that the data returned from your server contains
`the expected list of product identifiers. Also verify that your server correctly implements standard HTTP caching
`mechanisms.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`19
`
`

`

`Requesting Payment
`Suggested Testing Steps
`
`Test a Products Request
`Using the list of product identifiers that you tested, create and submit an instance of SKProductsRequest.
`Set a breakpoint in your code, and inspect the lists of valid and invalid product identifiers. If there are invalid
`product identifiers, review your products in iTunes Connect and correct your JSON file or property list.
`
`Test a Payment Request
`Create an instance of SKPayment using a valid product identifier that you have already tested. Set a breakpoint
`and inspect the payment request. Add the payment request to the transaction queue, and set a breakpoint to
`confirm that the paymentQueue:updatedTransactions: method of your observer is called.
`
`During testing, it’s ok to finish the transaction immediately without providing the content. However, even
`during testing, failing to finish the transaction can cause problems: unfinished transaction remain in the queue
`indefinitely, which could interfere with later testing.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`20
`
`

`

`Delivering Products
`
`In the last part of the purchase process, after the App Store has processed the payment request, your app
`stores information about the purchase for future launches, downloads the purchased content, and marks the
`transaction as finished, as shown in Figure 4-1 (page 21).
`
`Figure 4-1
`
`Stages of the purchase process—delivering products
`
`Waiting for the Store to Process Transactions
`Implement the paymentQueue:updatedTransactions: method on your transaction queue observer. Store
`Kit calls this method when the status of a transaction changes—for example, when a payment request has
`been processed. The transaction status tells you what action your app needs to perform, as shown in Table
`4-1 and Listing 4-1.
`
`Table 4-1
`
`Transaction statuses and corresponding actions
`
`Status
`
`Meaning
`
`Action to take in your app
`
`SKPaymentTransaction-
`StatePurchasing
`
`Transaction still in
`progress
`
`Update your UI to reflect the status, and wait
`to be called again.
`
`SKPaymentTransaction-
`StateFailed
`
`Transaction failed
`
`Use the value of the error property to present
`a message to the user.
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`21
`
`

`

`Delivering Products
`Waiting for the Store to Process Transactions
`
`Status
`
`Meaning
`
`Action to take in your app
`
`SKPaymentTransaction-
`StatePurchased
`
`Transaction
`succeeded
`
`Provide the purchased functionality.
`
`Validate the receipt, as described in Receipt
`Validation Programming Guide , and download
`any content, as described in “Providing
`Purchased Content” (page 27).
`
`SKPaymentTransaction-
`StateRestored
`
`Transaction ready
`to restore
`
`For information about restoring transactions,
`see Restoring Transactions (page $@).
`
`Listing 4-1
`
`Responding to transaction statuses
`
`- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray
`*)transactions
`{
`
`for (SKPaymentTransaction *transaction in transactions)
`{
`
`switch (transaction.transactionState)
`{
`
`case SKPaymentTransactionStatePurchased:
`[self completeTransaction:transaction];
`break;
`case SKPaymentTransactionStateFailed:
`[self failedTransaction:transaction];
`break;
`case SKPaymentTransactionStateRestored:
`[self restoreTransaction:transaction];
`default:
`break;
`
`}
`
`}
`
`}
`
`To keep your user interface up to date while waiting, the transaction queue observer can implement optional
`methods from the SKPaymentTransactionObserver protocol as follows. The
`paymentQueue:removedTransactions: method is called when transactions are removed from the queue—in
`your implementation of this method, remove the corresponding items from your app’s UI. The
`
`2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`22
`
`

`

`Delivering Products
`Persisting the Purchase
`
`paymentQueue:restoreCompletedTransactionsFailedWithError: or
`paymentQueueRestoreCompletedTransactionsFinished: method is called when Store Kit finishes
`restoring transactions, depending on whether there was an error. In your implementation of these methods,
`update your app’s UI to reflect the success or error.
`
`Persisting the Purchase
`After making the product available, your app needs to make a persistent record of the purchase, to ensure
`that it co

This document is available on Docket Alarm but you must sign up to view it.


Or .

Accessing this document will incur an additional charge of $.

After purchase, you can access this document again without charge.

Accept $ Charge
throbber

Still Working On It

This document is taking longer than usual to download. This can happen if we need to contact the court directly to obtain the document and their servers are running slowly.

Give it another minute or two to complete, and then try the refresh button.

throbber

A few More Minutes ... Still Working

It can take up to 5 minutes for us to download a document if the court servers are running slowly.

Thank you for your continued patience.

This document could not be displayed.

We could not find this document within its docket. Please go back to the docket page and check the link. If that does not work, go back to the docket and refresh it to pull the newest information.

Your account does not support viewing this document.

You need a Paid Account to view this document. Click here to change your account type.

Your account does not support viewing this document.

Set your membership status to view this document.

With a Docket Alarm membership, you'll get a whole lot more, including:

  • Up-to-date information for this case.
  • Email alerts whenever there is an update.
  • Full text search for other cases.
  • Get email alerts whenever a new case matches your search.

Become a Member

One Moment Please

The filing “” is large (MB) and is being downloaded.

Please refresh this page in a few minutes to see if the filing has been downloaded. The filing will also be emailed to you when the download completes.

Your document is on its way!

If you do not receive the document in five minutes, contact support at support@docketalarm.com.

Sealed Document

We are unable to display this document, it may be under a court ordered seal.

If you have proper credentials to access the file, you may proceed directly to the court's system using your government issued username and password.


Access Government Site

We are redirecting you
to a mobile optimized page.





Document Unreadable or Corrupt

Refresh this Document
Go to the Docket

We are unable to display this document.

Refresh this Document
Go to the Docket