15
votes

I'm developing an app where the user can purchase digital maps, charts and so on. I'd like to wrap these in in-app-purchases. The thing is that I don't know beforehand how many charts there will be, as I'm getting them from another source from the net. There could be hundreds.

I have a server that periodically gets the charts from that source and stores them locally; there may appear new charts in the future or disappear existing ones. All this without manual intervention.

There are three distinct types of charts.

My first solution was to create three consumable items and let the user buy these; this was working fine but unfortunately Apple rejected it, since they require charts to be "non consumable".

But I'm quite at a loss how to implement what I want with the non-consumable type. If I create these three types as non-consumable, and the user buys one, he will get all the other charts in that group for free, since a non-consumable item can only be bought once.

The only solution I can think of is to create a non-consumable item for every single chart. But that's something I want to avoid at all costs: as it is now, the charts are periodically fetched from the remote source without any manual work on my side. I'd like to keep it that way. I don't want to manually create a new non consumable purchases every time a new chart appears.

Any ideas how to make this scalable?

4

4 Answers

19
votes

I can't completely spell it out for you with code but you can handle this problem two ways:

Currency. You do not sell non-consumable items such as maps. You sell currency. With that currency you purchase maps. The maps you feed dynamically whenever the user hits your store front. That way you only need to track a few purchase options.

The other option: The company I worked for initially set this up very simply. Our app would launch and we would reach out for a php script that handed us back the app store IDs that we had sitting in it. At that point we'd verify them and use the valid returns. This option allowed us to change our in app purchases through iTunes Connect and then in the script and everything was great.

5
votes

This is an older post, but I just had the same question and found out there is now a way to dynamically provide non-consumables by hosting the product identifier list on your own server:

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.

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.

Apple Developer In-App Purchasing Guide

3
votes

I think your limit on items is something massive like 10,000 or so.

Pre-create a big number of items, add some code to check your website to see what your highest chart number is and make sure the users can only buy charts that you have.

The app downloads the chart names and corresponding product id from your server and then you're just buying a product.

Apple doesn't care if the actual product is already in the app and unlocked by the purchase, downloaded from their server or provided from your website.

3
votes

Whether you have these purchased directly via IAP or through some kind of in-app "currency" you could simplify the amount of work you'd need to do in the future by using a naming system which would guarantee a unique map name for each item you want to sell. For example:

 NSString *myMapName = [NSString stringWithFormat:@"%@%@%@%@", app_identifier, map_type, top_left_corner_location, scale];

This way if your server passes that information for a new map, there's a programmatic way to know what the IAP identifier should be— just make it the value of the string myMapName.

In the case where you use currency (which sounds easier than the alternative option, and is what lots of big apps out there seem to be doing) you just need to make a hash with some data in your map so that people can't guess the code you're storing in their keychain/plist and magically get all your maps without paying :)

In the case where you actually have individual IAPs for each map, sadly you do have to make an IAP for every possible map once. (But you can hire some kid to do that part for minimum wage, right? It's just data entry) They can be basic shells, though, with the actual info provided via your server as described above, once it's verified that the map has actually been purchased.

Hope this helps!