Uploading iOS In-app Purchase Downloadable Content

Tony Spinelli
6 min readNov 11, 2018

--

In-app purchases allow a developer to add content to their apps that can be purchased to enable additional features. Developers also have the option of downloading additional content to a device once a purchase is made. This content can be hosted however the developer would like, but the most cost effective is to allow Apple to host your in-app purchase content.

Unfortunately, Apple has not made this a seamless experience. The process has changed over the years and at times has been easy, but my most recent experience was very frustrating.

Application Loader

Up until a year ago, a developer could use Application Loader to upload in-app purchase content. This tool is available as part of XCode under the XCode application menu->Open Developer Tools.

Image 1. Application Loader

This tool made it very easy to upload content and the removal of this feature about a year ago is unfortunate. This tool appeared to be an interface on top of the iTMSTransporter tool that I will detail below.

XCode Organizer

The XCode Organizer does appear to support the uploading of In-App Purchase content, however this has been hit-and-miss for me but it is worth trying for your application as it should be much easier than using the command-line.

When I attempt to use this option I get the error shown in Image 3 below. XCode is unable to find the application record that corresponds to the upload.

Image 2. XCode Organizer option for In-App Purchase content
Image 3. XCode Organizer error

iTMSTransporter Command-line Tool

This is the option I am currently using to successfully upload my In-App Purchase content.

To start, follow the instructions to setup iTMSTransporter on your development machine

If required, create an app-specific password for using with iTMSTransporter as it will need to access your iTunes Connect portal.

Use the following command to test your connection:

iTMSTransporter -m diagnostic -t Aspera

There are lots of different command-line options for iTMSTransporter depending on what you’re trying to do. I will only detail the minimum number of commands/options to accomplish my goal of uploading In-App Content for my application.

Download App Metadata

To start, we need to download the app metadata for the application that we need to upload content for. To accomplish this we need to find the Vendor ID for the specific application we are uploading content for.

The Vendor ID can be found by logging in to iTunesConnect, go to your apps and select the application for which you want to upload content for. Under App Information look for the SKU value — this is your Vendor ID.

The following command will download an iTunes Store Package for your application to the current directory:

iTMSTransporter -m lookupMetadata -u <itunes connect userID> -p <app specific password> -vendor_id <Vendor ID> -destination .

There will now be a directory called <Vendor ID> within your current directory containing your app metadata.

Prepare In-App Content

You will need to export your In-App Content as an Installer Package. This can be accomplished by Archiving your In-App content within XCode and selecting the Installer Package method of distribution and saving your content locally

Image 4. Installer Package option for distributing content

At this point, you should have an iTunes Store Package with a name of your app SKU number that contains your Installer Package files. For example, if your SKU was Example:

Image 5. Example.itmsp directory created using iTMSTransporter

Using Finder, move the files within your Installer Package directory into this Vendor ID folder. You can select Show Package Contents to browse to this directory.

After copying the files to the iTunes Store Package you should see the following list of files where inapptest.pkg is the name of your In-App Purchase identifier in iTunes Connect:

Almost Done — metadata.xml Changes!

The last step in preparing our content is to update the metadata.xml file. Use your favorite editor to open this file. To start, we need to remove a bunch of content — this should not be the case, but if we do not do this step our file will fail verification as of the time of writing this blog:

Remove everything between <versions> and </versions> (including the XML tags) and everything between <products> and </products> (again, including the XML tags). To clarify, the <version> tag, all the content and the closing </versions> tag need to be deleted. The same for the <products> tag and content.

Now, search in the file for your In-App Purchase Product ID. You should find a section in the document enclosed within <in_app_purchase> tags.

Assuming you have setup your purchase properly, you should see an embedded XML section for this In-App Purchase:

<has_hosted_content>true</has_hosted_content>

If you do not have this, you should go Turn On Hosted Content for your In-App Purchase within iTunes Connect. Once you enable this, you would need to perform the iTMSTransporter lookupMetadata command again to download a new metadata.xml file.

Image 6. Content Hosting Option for an In-App Purchase

Immediately after the <has_hosted_content> tag add the following if it does not already exist:

<software_assets>
<asset type="in-app-purchase-content">
<data_file>
<size>323170674</size>
<file_name>inapptest.pkg</file_name>
<checksum type="md5">e04ba40c68effe5fc3fcce666761b2d0</checksum>
</data_file>
</asset>
</software_assets>

We need to modify the <size>, <file_name> and <md5> values to match your content. The <file_name> should match the filename for your .pkg file — in my case that is inapptest.pkg. You can get the <size> and <md5> values by running the following commands and replace the values in the file with the results:

stat -f ‘%z’ <pkg filename>  -- Size value
md5 <pkg filename> -- md5 value

Last Step!

From the parent directory that contains your iTunes Store Package we will verify the package using the following command, replacing Example.itmsp with your .itmsp package name:

iTMSTransporter -m verify -u <itunes connect userID> -p <app specific password> -f Example.itmsp/

Assuming the package verifies properly, you then upload your content again replacing Example.itmsp with your .itmsp package name:

iTMSTransporter -m upload -u <itunes connect userID> -p <app specific password> -f Example.itmsp/

At this point, assuming you receive a success message, you have to wait for the content to show up in iTunes connect. You can query the servers using the following command, however I find the status to be very delayed

iTMSTransporter -m statusAll -u <itunes connect userID> -p <app specific password> -vendor_id <Vendor ID> -outputFormat xml

Patience

It typically takes a few hours for content to show up and it can be frustrating because the status command does not typically show that they received the content.

Good luck and I hope this helps you upload your content for an In-App Purchase!

Here is the app that I was uploading content for — iBird Lite

Check out our newest application supporting photo recognition — iBird Photo Sleuth

--

--