throbber
In-App Purchase
`Programming Guide
`
`Smartflash - Exhibit 2026
`Apple v. Smartflash
`CBM2014-00106
`
`

`
`Contents
`
`About In-App Purchase 5
`At a Glance 6
`You Create and Configure Products in iTunes Connect 6
`Your App Interacts with the App Store to Sell Products 6
`Subscriptions Require Additional Application Logic 7
`Users Can Restore Purchases 7
`Apps and Products Are Submitted for Review 7
`See Also 7
`
`Designing Your App’s Products 8
`Understanding What You Can Sell Using In-App Purchase 8
`Creating Products in iTunes Connect 9
`Product Types 9
`Differences Between Product Types 10
`
`Retrieving Product Information 12
`Getting a List of Product Identifiers 12
`Embedding Product IDs in the App Bundle 13
`Fetching Product IDs from Your Server 13
`Retrieving Product Information 15
`Presenting Your App’s Store UI 16
`Suggested Testing Steps 17
`Sign In to the App Store with Your Test Account 18
`Test Fetching the List of Product Identifiers 18
`Test Handling of Invalid Product Identifiers 18
`Test a Products Request 19
`
`Requesting Payment 20
`Creating a Payment Request 20
`Detecting Irregular Activity 21
`Submitting a Payment Request 22
`
`Delivering Products 23
`Waiting for the App Store to Process Transactions 23
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`2
`
`

`
`Contents
`
`Persisting the Purchase 26
`Persisting Using the App Receipt 27
`Persisting a Value in User Defaults or iCloud 27
`Persisting a Receipt in User Defaults or iCloud 27
`Persisting Using Your Own Server 28
`Unlocking App Functionality 28
`Delivering Associated Content 29
`Loading Local Content 30
`Downloading Hosted Content from Apple’s Server 30
`Downloading Content from Your Own Server 31
`Finishing the Transaction 32
`Suggested Testing Steps 33
`Test a Payment Request 33
`Verify Your Observer Code 33
`Test a Successful Transaction 33
`Test an Interrupted Transaction 34
`Verify That Transactions Are Finished 34
`
`Working with Subscriptions 35
`Calculating a Subscription’s Active Period 35
`Expiration and Renewal 37
`Cancellation 38
`Cross-Platform Considerations 38
`Letting Users Manage Subscriptions 38
`The Test Environment 38
`
`Restoring Purchased Products 40
`Refreshing the App Receipt 41
`Restoring Completed Transactions 41
`
`Preparing for App Review 43
`Submitting Products for Review 43
`Receipts in the Test Environment 43
`Implementation Checklist 44
`
`Document Revision History 46
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`3
`
`

`
`Figures, Tables, and Listings
`
`About In-App Purchase 5
`Figure I-1
`Stages of the purchase process 6
`
`Designing Your App’s Products 8
`Table 1-1
`Comparison of product types 10
`Table 1-2
`Comparison of subscription types 10
`
`Retrieving Product Information 12
`Figure 2-1
`Stages of the purchase process—displaying store UI 12
`Table 2-1
`Comparison of approaches for obtaining product identifiers 12
`Listing 2-1
`Fetching product identifiers from your server 14
`Listing 2-2
`Retrieving product information 15
`Listing 2-3
`Formatting a product’s price 17
`
`Requesting Payment 20
`Figure 3-1
`Stages of the purchase process—requesting payment 20
`Listing 3-1
`Creating a payment request 20
`Listing 3-2
`Providing an application username 21
`
`Delivering Products 23
`Figure 4-1
`Stages of the purchase process—delivering products 23
`Table 4-1
`Transaction statuses and corresponding actions 24
`Listing 4-1
`Registering the transaction queue observer 24
`Listing 4-2
`Responding to transaction statuses 25
`Listing 4-3
`Excluding downloaded content from backups 31
`
`Working with Subscriptions 35
`Figure 5-1
`Example subscription timeline 35
`Table 5-1
`Timeline of a sample subscription 35
`
`Preparing for App Review 43
`Figure 7-1
`Development, review, and production environments 43
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`4
`
`

`
`About In-App Purchase
`
`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.
`
`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 levels to explore
`
` ● An online game that allows players to purchase virtual property
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`5
`
`

`
`About In-App Purchase
`At a Glance
`
`At a Glance
`At a high level, the interactions between the user, your app, and the App Store during the In-App Purchase
`process take place in three stages, as shown in Figure I-1. First, the user navigates to your app’s store and your
`app displays its products. Second, the user selects a product to buy and the app requests payment from the
`App Store. Third, the App Store processes the payment and your app delivers the purchased product.
`
`Figure I-1
`
`Stages of the purchase process
`
`You Create and Configure Products in iTunes Connect
`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.
`
`Relevant Chapter: Designing Your App’s Products (page 8)
`
`Your App Interacts with the App Store to Sell Products
`All apps that use In-App Purchase need to implement the core functionality described in these chapters to let
`users make purchases and then deliver the purchased products.
`
`These development tasks need to be done in order. The relevant chapters introduce them in the order you
`implement them, and they’re listed in full in Implementation Checklist (page 44). To help plan your development,
`you may want to read the full checklist before you begin.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`6
`
`

`
`About In-App Purchase
`See Also
`
`Relevant Chapters: Retrieving Product Information (page 12), Requesting Payment (page 20),
`Delivering Products (page 23)
`
`Subscriptions Require Additional Application Logic
`Apps that offer subscriptions need to keep track of when the user has an active subscription, respond to
`expiration and renewal, and determine what content the user has access to.
`
`Relevant Chapter: Working with Subscriptions (page 35)
`
`Users Can Restore Purchases
`Users can restore products that they previously purchased—for example, to bring content they’ve already paid
`for onto their new phone.
`
`Relevant Chapter: Restoring Purchased Products (page 40)
`
`Apps and Products Are Submitted for Review
`When you’re done developing and testing, you submit your app and your In-App Purchase products for review.
`
`Relevant Chapter: Preparing for App Review (page 43)
`
`See Also
`In-App Purchase Configuration Guide for iTunes Connect describes how to create and configure your app’s
`products in iTunes Connect.
`
` ●
`
` ●
`
` ●
`
`App Distribution Quick Start describes how to enable In-App purchase for your app.
`
`Receipt Validation Programming Guide describes how to work with receipts, in particular with the record
`of successful in-app purchases.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`7
`
`

`
`Designing Your App’s Products
`
`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. Examples include 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 to sell unsuitable content.
`
` ●
`
`Real-world goods and services. You must deliver a digital good or service within your app 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. Don’t use In-App Purchase to sell content that the isn’t allowed by the App Review
`Guidelines—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 determine that In-App Purchase is the
`appropriate way to sell those products, you need to create the products in iTunes Connect.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`8
`
`

`
`Designing Your App’s Products
`Creating Products in iTunes Connect
`
`Creating Products in iTunes Connect
`Before you start coding, you need to configure products in iTunes Connect for your app to interact with. As
`you develop your app, you can add and remove products and refine or reconfigure your existing products.
`
`Every product is associated with a specific app. Products created for use by one app are not available in other
`apps. Companion apps on a different platform are different apps—the products of the Mac app are not available
`in the iOS app and vice versa.
`
`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.
`
`For step-be-step information about working with products in iTunes Connect, In-App Purchase Configuration
`Guide for iTunes Connect .
`
`Product Types
`Product types let you use In-App Purchase in a range of apps by providing several different product behaviors.
`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’re 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 their subscription is active. When an
`auto-renewable subscription is about to expire, the system automatically renews it on the user’s behalf.
`
` ● 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’s 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 that 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
`don’t expire and can be offered only in Newsstand-enabled apps.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`9
`
`

`
`Designing Your App’s Products
`Differences Between Product Types
`
`Differences Between Product Types
`Each product type is designed for a particular use. The behavior of different product types varies in certain
`ways, as summarized in Table 1-1 and Table 1-2.
`
`Table 1-1
`
`Comparison of product types
`
`Product type
`
`Non-consumable
`
`Consumable
`
`Users can buy
`
`Once
`
`Multiple times
`
`Appears in the receipt
`
`Always
`
`Once
`
`Synced across devices
`
`By the system
`
`Not synced
`
`Restored
`
`By the system
`
`Not restored
`
`Table 1-2
`
`Comparison of subscription types
`
`Subscription type
`
`Auto-renewable
`
`Non-renewing
`
`Free
`
`Users can buy
`
`Multiple times
`
`Multiple times
`
`Once
`
`Appears in the receipt
`
`Always
`
`Once
`
`Always
`
`Synced across devices
`
`By the system
`
`By your app
`
`By the system
`
`Restored
`
`By the system
`
`By your app
`
`By the system
`
`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.
`
`Consumable products and non-renewing subscriptions appear in the receipt after being purchased but are
`removed the next time the receipt is updated, as discussed in more detail in Persisting Using the App
`Receipt (page 27). All other types of products have an entry in the receipt that isn’t removed.
`
`Consumable products, by their nature, aren’t synced or restored. Users understand that, for example, buying
`ten more bubbles on their iPhone doesn’t also give them ten more bubbles on their iPad. All other types of
`products are made available across all of the user’s devices. They’re also restored so users can continue to
`access their purchased content even after buying a new device. Store Kit handles the syncing and restoring
`process for auto-renewable and free subscriptions and for non-consumable products.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`10
`
`

`
`Designing Your App’s Products
`Differences Between Product Types
`
`Non-renewing subscriptions differ from auto-renewable subscriptions in a few key ways. These differences
`give your app the flexibility to implement the correct behavior for your needs, as follows:
`
` ●
`
` ●
`
` ●
`
`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’re
`purchased and for letting users restore past purchases. 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-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`11
`
`

`
`Retrieving Product Information
`
`In the first part of the purchase process, your app retrieves information about its products from the App Store,
`presents its store UI to the user, and then lets the user select a product, as shown in Figure 2-1.
`
`Figure 2-1
`
`Stages of the purchase process—displaying store UI
`
`Getting a List of Product Identifiers
`Every product you sell in your app has a unique product identifier. Your app uses these product identifiers to
`fetch information about products from the App Store, such as pricing, and to submit payment requests when
`users purchase those products. Your app can either read its list of product identifiers from a file in its app
`bundle or fetch them from your server. Table 2-1 summarizes the differences between the two approaches.
`
`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-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`12
`
`

`
`Retrieving Product Information
`Getting a List of Product Identifiers
`
`If your app has a fixed list of products, such as an in-app purchase to remove ads or enable functionality, embed
`the list in the app bundle. If the list of product identifiers can change without your app needing to be updated,
`such as a game that supports additional levels or characters, have your app fetch the list from your server.
`
`There’s no runtime mechanism to fetch a list of all products configured in iTunes Connect for a particular app.
`You’re responsible for managing your app’s list of products and providing that information to your app. If you
`need to manage a large number of products, consider using the bulk XML upload/download feature in iTunes
`Connect.
`
`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
`Host a JSON file on your server with the product identifiers. For example:
`
`[
`
`"com.example.level1",
`"com.example.level2",
`"com.example.rocket_car"
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`13
`
`

`
`Retrieving Product Information
`Getting a List of Product Identifiers
`
`]
`
`To get product identifiers from your server, fetch and read the JSON file as shown in Listing 2-1. Consider
`versioning the JSON file so that future versions of your app can change its structure without breaking older
`versions of your app. For example, you could name the file that uses the old structure products_v1.json
`and the file that uses a new structure products_v2.json. This is especially useful if your JSON file is more
`complex than the simple array in the example.
`
`Listing 2-1
`
`Fetching product identifiers from your server
`
`- (void)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 */ }
`
`NSArray *productIdentifiers = [NSJSONSerialization
`JSONObjectWithData:jsonData options:NULL error:&err];
`if (!productIdentifiers) { /* Handle the error */ }
`
`dispatch_queue_t main_queue = dispatch_get_main_queue();
`dispatch_async(main_queue, ^{
`[delegate displayProducts:productIdentifiers]; // Custom method
`});
`
`});
`
`}
`
`For information about downloading files using NSURLConnection, see Using NSURLConnection in URL Loading
`System Programming Guide .
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`14
`
`

`
`Retrieving Product Information
`Retrieving Product Information
`
`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.
`
`Retrieving Product Information
`To make sure your users see only products that are actually available for purchase, query the App Store before
`displaying your app’s 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-2 shows a simple implementation of both pieces of code.
`
`Listing 2-2
`
`Retrieving product information
`
`// Custom method
`- (void)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 *invalidIdentifier in response.invalidProductIdentifiers) {
`// Handle any invalid product identifiers.
`
`} [
`
`self displayStoreUI]; // Custom method
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`15
`
`

`
`Retrieving Product Information
`Presenting Your App’s 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’s 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.
`Payment requests are discussed in Requesting Payment (page 20).
`
`Product identifiers being returned as invalid usually indicates an error in your app’s list of product identifiers,
`although it could mean the product hasn’t been properly configured in iTunes Connect. Good logging and a
`good UI help you resolve this type of issue more easily. In production builds, your app needs to fail
`gracefully—typically, this means displaying the rest of your app’s store UI and omitting the invalid product. In
`development builds, display an error to call attention to the issue. In both production and development builds,
`use NSLog to write a message to the console so you have a record of the invalid identifier. If your app fetched
`the list from your server, you could also define a logging mechanism to let your app send the list of invalid
`identifiers back to your server.
`
`Presenting Your App’s Store UI
`Because the design of your app’s store has an important impact on your in-app sales, it’s worth investing the
`time and effort to get it right. Design the user interface for your store UI so 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 in a way that showcases your products in their best light and fits seamlessly 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 display UI indicating that that the store isn’t available or omit
`the store portion of your UI entirely.
`
`Present products naturally in the flow of your app. Find the best place in your UI to show your app’s store
`UI. Present products in context at the time when the user can use them—for example, let users unlock
`functionality when they try to use that premium feature. Pay special attention to the experience a user has
`when exploring your app for the first time.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`16
`
`

`
`Retrieving Product Information
`Suggested Testing Steps
`
`Organize products so that exploration is easy and enjoyable. If your app has a small enough number of
`products, you can display everything on one screen; otherwise, group or categorize products to make them
`easy to navigate. Apps with a large number of products, such as comic book readers or magazines with many
`issues, benefit especially from an interface that makes it easy for users to discover new items they want to
`purchase. Make the differences between your products clear by giving them distinct names and visuals—if
`necessary, include explicit comparisons.
`
`Communicate the value of your products to your users. Users want to know exactly what they’re going to
`buy. Combine information from the App Store, such as product prices and descriptions, with additional data
`from your server or the app bundle, such as images or demos of your products. Let users interact with a product
`in a limited way before buying it. For example, a game that gives the user the option to buy new race cars can
`allow users to run a test lap with the new car. Likewise, a drawing app that lets the user buy additional brushes
`can give users the chance to draw with the new brush on a small scratch pad and see the difference between
`brushes. This kind of design provides users an opportunity to experience the product and be convinced they
`want to purchase it.
`
`Display prices clearly, using the locale and currency returned by the App Store. Ensure that the price of a
`product is easy to find and easy to read. 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 differ. Consider, for example, a user in the United States who prefers
`the United Kingdom locale for its units and date formatting. Your app displays its UI according to the United
`Kingdom locale, but it still needs to display product information in the locale specified by the App Store.
`Converting prices to British pounds sterling, in an attempt to match the United Kingdom locale of the rest of
`the interface, would be incorrect. The user has an App Store account in the United States and pays in U.S.
`dollars, so prices would be provided to your app in U.S. dollars. Likewise, your app would display its prices in
`U.S. dollars. Listing 2-3 shows how to correctly format a price by using the product’s locale information.
`
`Listing 2-3
`
`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 App Store to request payment for the product.
`
`Suggested Testing Steps
`Test each part of your code to verify that you’ve implemented it correctly.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`17
`
`

`
`Retrieving Product Information
`Suggested Testing Steps
`
`Sign In to the App Store with Your Test Account
`Create a test user account in iTunes Connect, as described in Creating Test User Accounts.
`
`On a development iOS device, sign out of the App 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 the 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’re connected
`to the test environment.
`
`If the text “[Environment: Sandbox]” doesn’t appear, you’re using the production environment. Make sure
`you’re running a development-signed build of your app. Production-signed builds use the production
`environment.
`
`Important: Don’t 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.
`
`Test Fetching the List of Product Identifiers
`If your product identifiers are embedded in your app, set a breakpoint in your code after they’re 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.
`
`Test Handling of Invalid Product Identifiers
`Intentionally include an invalid identifier in your app’s list of product identifiers. (Make sure you remove it after
`testing.)
`
`In a production build, verify that the app displays the rest of its store UI and users can purchase other products.
`In a development build, verify that the app brings the issue to your attention.
`
`Check the console log and verify that you can correctly identify the invalid product identifier.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`18
`
`

`
`Retrieving Product Information
`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.
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`19
`
`

`
`Requesting Payment
`
`In the second part of the purchase process, after the user has chosen to purchase a particular product, your
`app submits a payment request to the App Store, as shown in Figure 3-1.
`
`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, and set the quantity
`if needed, as shown in Listing 3-1. The product object comes from the array of products returned by your app’s
`products request, as discussed in Retrieving Product Information (page 15).
`
`Listing 3-1
`
`Creating a payment request
`
`SKProduct *product = <# Product returned by a products request #>;
`SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
`payment.quantity = 2;
`
`2013-10-22 | Copyright © 2013 Apple Inc. All Rights Reserved.
`
`20
`
`

`
`Requesting Payment
`Detecting Irregular Activity
`
`Detecting Irregular Activity
`The App Store uses an irregular activity detection engine to help combat fraud. Some apps can provide
`additional information to improve the engine’s ability to detect unusual transactions. If your users have an
`account with you, in addition to their App Store accounts, provide this additional piece of information when
`requesting payment.
`
`By way of illustration, consider the following two examples. In the normal case, many different users on your
`server each buy coins to use in your game, and each user pays for the purchase from a different App Store
`account. In contrast, it would be very unusual for a single user on your server to buy coins multiple times,
`paying for each purchase from a different App Store account. The App Store can’t detect this kind of irregular
`activity on its own—it needs information from your app about which account on your server is associated with
`the transaction.
`
`To provide this information, populate the applicationUsername property of the payment object with a
`one-way hash of the user’s account name on your server, such as in the example shown in Listing 3-2.
`
`Listing 3-2
`
`Providing an application username
`
`#import <CommonCrypto/CommonCrypto.h>
`
`// Custom method to calculate the SHA-256 hash using Common Crypto
`- (NSString *)hashedValueForAccountName:(NSString*)userAccountName
`{
`
`const int HASH_SIZE = 32;
`unsigned char hashedChars[HASH_SIZE];
`const char *accountName = [userAccountName UTF8String];
`size_t accountNameLen = strlen(accountName);
`
`// Confirm that the length of the user name is small enough
`// to be recast when calling the hash function.
`if (accountNameLen > UINT32_MAX) {
`NSLog(@"Account name too long to hash:

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