We are using Unity, which provides an excellent "codeless" plugin for in-app purchase. However, things are never that simple, and if you want to support restoring purchases (required for App Store), then you need to punch a few keys.
Our implementation started as a "codefull" implementation, were we set up a catalog in code, and made our own purchase buttons. We had a default price shown of $0.99, built into a nice pixel-art button. It worked great in the editor.
However, when you set up the products on the app store side, you realise there are local prices, and you need to be able to display a lot of local currency symbols, which we didn't want to make art for - so we switch to a localisation-friendly font called Noto. So, now we had a string value of $0.99 showing on the button in that font if the local price could not be obtained from the store. In editor mode, Unity's IAP provides a placeholder price of $0.01, so we could see which prices had been replaced correctly.
The first challenge came when trying to get local prices for products in Closed Alpha, on Google Play Store, and in Test Flight on App Store. It didn't work and this resulted in our in-app buttons showing the default $0.99 - which turned out to be very confusing for users - because it indicates something is purchasable, but really it isn't.
Once things are working in test, it was time to push to production. In our first release version for App Store we missed attaching the in-app items to the version submission. The binary passed, but none of the in-app products were available, because they weren't associated with the build and approved.
Our next iteration replaced the default $0.99 with helpful and informative "No Price. Try Later" message, in contemplation of someone being on a WiFi only iPad without the network, their purchases might work later when connected. However, this doesn't get past Apple's app review (we got rejected with "price is not shown" issue), so we settled on the better (best?) practice of hiding any in-app purchase button unless that purchase was available.
Also, this story is difficult to tell in a linear fashion, because we could quickly push updates to the Google Play store along the way (sometimes two or three in a day), but the cycle time to find out the build was rejected for App Store was a day or two. While we were solving in-app purchase issues, there were also minor bug fixes we wanted to get out. So a week in, we ended up with a nicely working Google Play version, but an App Store version we couldn't update with the latest bug fixes because we couldn't get the in-app purchase passed review. [UPDATE: Next day, all sorted on App Store!]
This release was "soft-launch", only live in New Zealand, Australia, and Singapore. However, we probably went public with our soft-launch about a week too early. Next time I'd try having a week on the store under the radar to check things before telling friends!
After four-weeks in soft-launch, we plan to go live world-wide (this article having been written at the end of week one).
By Stephen McIntyre