As we all know, Windows Phone 7 doesn’t have support for in-app purchases. The support was added in Windows Phone 8. This isn’t a huge deal in most countries as WP7 phones weren’t that popular. Except here in Finland. The big problem is that if your app targets Finnish users and you want to provide some content as in-app purchases, you really can’t skip the WP7 users or you’re going to miss a big part of your market. How big you may ask? Over half:
The Lumia 800 was really popular here. And it still is as it has been sold with big discounts in the past few months:
I’ve been battling with the problem recently as I’ve added some in-app products to an app which targets Finnish users only. And I’m quite happy with the outcome. Here’s first some features of the implementation and then some more details on how it is done:
The app only has one XAP (which targets Windows Phone 7.1). The same XAP gets deployed to both WP8 and WP7 phones.
In-app purchases are managed through Dev Center
The in-app purchases are managed through the Dev Center, just like when we are targeting Windows Phone 8 only:
There’s no “if platform wp 8 then else” code. The product purchase is initiated with the following code:
var license = await store.RequestProductPurchaseAsync("live2013", true);
Native on Windows Phone 8
If the app is run on Windows Phone 8, it uses the native in-app purchase features:
Custom code on Windows Phone 7
If the app is run on Windows Phone 7, it uses custom code which mimics the in-app purchase experience of WP8:
Note: The WP7 version gets the product details (price etc.) from the Dev Center.
PayPal on Windows Phone 7
User is taken to PayPal’s mobile checkout site when she decides to purchase the product (on Windows Phone 7):
On Windows Phone 8 the user can select from any of her payment methods. Remember, the app uses the native in-app purchase functionality on WP8 device.
And that’s about it on the feature side.The best part is that I don’t have to worry about if the user has Windows Phone 7 or 8 device as the same code works on both platforms. Biggest limitation is that the WP7 side is currently PayPal only.
The idea behind the implementation was taken from the code sample “WP8 Store Wrapper for IAP”. The original code sample shows how it is possible to wrap the WP8 store so that it can be used when a WP7 app is run on a WP8 device.
I used a similar wrapping mechanism but in addition I implemented a custom store which is used on WP7 devices. Here’s a StoreFactory-class which decides what store to use:
public static class StoreFactory
public static StoreBase Create()
StoreBase store = null;
if (Environment.OSVersion.Version.Major >= 8)
store = StoreLauncher.GetStoreInterface("WP8StoreWrapper.Store, WP8StoreWrapper, Version=184.108.40.206, Culture=neutral, PublicKeyToken=null");
store = StoreLauncher.GetStoreInterface("CustomStore.MyCustomStore, CustomStore, Version=220.127.116.11, Culture=neutral, PublicKeyToken=null");
Here’s an example which shows how to check if the user owns product “myproduct”:
var ownsProduct = store.LicenseInformation.ProductLicenses.ContainsKey("myproduct");
Without the wrapper, using directly the Windows Phone 8 SDK, the above code would be written like this:
var ownsProduct = CurrentApp.LicenseInformation.ProductLicenses.ContainsKey("myproduct");
The custom store includes the product details page. The page is similar to WP8’s page, showing the product’s price with the buy and cancel buttons.
The custom store isn’t just a client side thing. There’s a service which the client uses to get the product details and to communicate with the PayPal. The whole thing could be implemented without a service but in that case, if the user changes her phone, the purchase would be lost. With the help of the service, user can install her previously purchased products on a new phone.
The service itself is just a ASP.NET MVC site, which returns the product details to client in JSON format, communicates with PayPal using their old WebService interface and stores the receipts for purchases.
Code isn’t yet available as it needs some fine tuning. But if you’re interested, just give me a shout and can provide more details about the implementation.