Ever since Apple announced OS 3.0 with in-app purchases, I knew I had implement it in Flower Garden. The concept of in-app purchases fits very well with the idea of a flower shop where virtual gardeners can purchase extra items for their gardens. It was just a matter of justifying the time necessary to implement it. I knew from my previous experience with downloadable content in games that only a small amount of the people who originally purchased the game would be interested in buying additional content. Flower Garden has been extremely well received, both by the media and the players, but it never got high-up enough on the charts to be a big seller, so in-app purchases were doomed from the start to be very limited.
The situation improved as soon as Apple announced the availability of in-app purchases in free apps. Flower Garden Free had been out for a few weeks at that point, so that effectively doubled the potential audience.
The final consideration that convinced me to plunge ahead was the realization that while only a small percentage of users would buy extra content, a fraction of those would make multiple purchases, and some people would probably buy every available item. So maybe it would be worthwhile after all.
Having said that, I gave myself one week to completely implement in-app purchases in Flower Garden. That included everything, from implementing the actual purchasing through StoreKit, to server code, and, of course, creating the additional content itself.
For those of you familiar with Flower Garden, the new content I created specifically for in-app purchases was a flower shop offering:
- An extra garden screen with 12 pots
- Liquid plant fertilizer that speeds up plant growth. This is a consumable item with a fixed number of doses and can be repurchased after it’s used up.
Additionally, the flower shop in the free version of Flower Garden had these items that would bring it functionality up to par with the full version of Flower Garden:
- Extra pots in the main garden
- Extra common seeds
- Set of bonus seeds
My initial estimate of one week turned out to be very optimistic, and it ended up taking closer to two and a half weeks. Most of it was spent creating the new content and integrating it smoothly in the game.
In this post and the next few ones, I’ll share my experiences with in-app purchases. From implementation details, tips and tricks, how it might help with piracy, mistakes I made along the way, and even how many sales in-app purchases generated.
Displaying Store Items
Apple did a good job documenting the overview of how to implement in-app purchases. Some of the details are missing, but they’re small enough that I was able to fill in the blanks pretty easily and get things working in a couple of days.
However, I really think the process should have been implemented very differently in Apple’s part. The sequence of actions that needs to be done feels overly complicated. It may be great if someone is trying to do a very customized and integrated store with all sorts of crazy features, but really, in 99% of the cases, developers just want to sell something and be done with it. Forcing us to go through all those steps seems overkill. A simplified higher-level set of helper functions would be a welcome addition to the SDK. For suggestions on how to go about it, look at the SDK for game consoles. They got that part right (or at least much more right than the iPhone SDK).
Getting the catalog
The first step towards implementing in-app purchases, is to get a list of all the products you want to sell in your store. It’s a good idea to keep this list off your app and on a web server instead, that way you can add, remove, or edit any products without going through a full app update. That in itself makes in-app purchases very attractive, doesn’t it? You can have a look at the master Flower Garden shop catalog.
Getting product info
Step two is to go through each of those products, and get the official product information from the App Store. That involves creating a set with the product ids you want to query, and sending a request.
The code in Flower Garden to query for product ids looks like this:
NSArray* products = m_appData->m_shopCatalog.m_products; NSMutableSet* productIds = [[NSMutableSet alloc] initWithCapacity:32]; for (int i=0; i<[products count]; ++i) { ShopProduct* product = [products objectAtIndex:i]; if (!product.m_alreadyIncluded) [productIds addObject:product.m_id]; } SKProductsRequest* request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIds]; request.delegate = self; #ifdef WORK_WITHOUT_APP_STORE [self productsRequest:request didReceiveResponse:nil]; #else [request start]; #endif [productIds release];
There are a couple interesting things in that code. First of all, notice that before we ask for the product info, we check if the product is already included in the app. That’s because some items, such as the extra pots or the common seeds, already come as part of Flower Garden Full. But at the same time, I wanted to show them in the store and mark them as purchased. So I need to have a parallel path for those items that doesn’t go through the App Store. More on that in a future post.
The other interesting bit is the #ifdef. This one really sucks, so get ready: The simulator can’t make any StoreKit calls. It fails with a nice message box explaining why, but it fails nonetheless. To put it in highly technical terms: That blows! Seriously, that means you’re stuck developing on the device. Turnaround times are about 20-30 seconds, and debugging on the device directly is no fun at all. I’m convinced that alone was part of the reason it took me longer than my initial estimate. So that #ifdef was my attempt to try to get as much done on the simulator as possible. At least I was able to display the products on the flower shop. The actual buying had to be done on the device though. No way around it as far as I know. Why, oh, why, doesn’t Apple let us add a test account on the simulator? Maybe a feature for SDK 4.0?
Displaying the products
Some time after sending the request for info on the products, and assuming we have a valid internet connection and that the App Store is in a good mood (to their credit, Apple’s servers have been very reliable), we’ll get a response. The response will include more information for each of the products we requested, including localized name, description, and price. This is all information taken from the in-app purchases you created in iTunes Connect. And yes, that means that you need to keep multiple sets of data in sync: Your shop catalog and the in-app purchases in iTunes Connect.
Notice that because everything we’ve done so far has been asynchronous (and asynchronous is the name of the game for a lot of the remaining steps as well) it introduces a lot of complexity. What do we do during that time? Do we let the user wander around to other parts of the program? Do we block and make the UI modal? I went with the latter approach for simplicity both coding and in the UI for the user.
At this point you can display them in your shop. In my case I ended up using a very similar interface to the App Store on the iPhone. I figured users are already familiar with that kind of interface, so might as well build on top of that. So that meant the flower shop is a table showing all available products. Clicking on a cell brings up a view with details and a description of each product.
To make my life easier, the only elements that are hardwired on the product page are the icon, the title, and the price/purchase button. The actual description and screenshots is just an embedded web view and part of the product description in the catalog has the correct URL for each project. You can even access some of them directly here.
So far all this has done for us is let us populate a list of products that are available to be sold. Next entry will cover the details of the actual transaction and a few things to watch out for.
Really good material, thanks for covering this! , will be useful for my current project. 🙂
test
Good Stuff. There are also a few open source project and plugins that can help.
Open Source In-App Purchase – http://www.github.com/soomla/ios-store
3 Options for In-App Purchase Unity Plugins  – http://soom.la/In-App-Purchase-Unity/