Configuring Cordova In App Purchases on iOS and Android

The first step of integrating in app purchases plugin into a cordova app is to decide what kind of products you want to offer and setup these products on iTunes Connect and Google Play.

This post goes over the differences between setting up consumable and non-consumable in app purchases on iOS and Android and restoring non-consumable purchases from different devices.

Non-Consumables

Non-Consumables are products that the user can purchase only once. For example, if you have a game with multiple levels, you can configure every level to be a paid purchase and define a product for each level (such as com.yourcompany.level1, com.yourcompany.level2, etc). When users purchase one of these products, they should own it forever (or for as long as there are humans and iPhones) which means that you have to provide a way to restore this product if the app is opened from another device using the same iTunes/google account.

To purchase a consumable on iOS using the cordova-plugin-inapppurchase plugin, use inAppPurchase.buy():

const productId = 'com.yourcompany.level1';
inAppPurchase
  .buy(productId)
  .then((res) => {
    console.log('purchase completed!');
    // unlock level 1
  })
  .catch(err => console.log(err) );

When you offer non-consumable products, you must provide functionality to restore these purchases so the user will not have to pay for them again if they re-download the app or use if from a different device.

To restore non-consumable purchases, use inAppPurchase.restorePurchases():

inAppPurchase
  .restorePurchases()
  .then((purchases) => {
    purchases.forEach(purchase => console.log(purchase.productId + ' should be restored') );
    // unlock the relevant feature based on this product id
  })
  .catch(err => console.log(err) );

Iterate over the purchases array and unlock all the features for the products that were previously purchased.

Consumables

Consumables are products that the user can purchase multiple times such as credits or coins. For example, in a slot machine app, you may charge the user 1 credit for each game and let them purchase a package of 20 credits by offering the product com.yourcompany.20_credits.

When you are adding a new consumable product on iOS, one of the options will be to add a consumable in app purchase:

Consumable Product iTunes Connect

On Android, there is no distinction between consumable and non-consumable products. They both fall under the "Managed Product" Category.

Managed Product Android Google Play

To indicate that this product is consumed, you need to call the inAppPurchase.consume(productId) function. It's important to remember to consume the product, otherwise you will get an error the next time you will try to purchase it.

To purchase a consumable product:

const productId = 'com.yourcompany.20_credits';
let validationData = {};
inAppPurchase
  .buy(productId)
  .then((res) => {
    validationData = res;
    // give the user credits for their purchase
    return inAppPurchase.consume(productId); // <- consumable products must be consumed
  })
  .then(() => {
    validateOnYourBackend({
      receipt: validationData.receipt,
      signature: validationData.signature,
    });
  })
  .catch(err => console.log(err) )

It's important to validate consumable in app purchases on your backend to make sure that the purchase was authentic.

Consumable purchases cannot be restored like non-consumable purchases. You should avoid putting a "Restore Purchases" button if your app only offers consumable products. Instead ask the user to authenticate and sync their purchased consumable products.

When a user purchases credits, you will need to keep track how many credits the user owns and the usage of credits. You can do that by uniquely identifying the user (by his credentials or any other unique identifier) and sending the information about purchases and games played to your server to sync this data between devices. You can also store this data locally using any of the available storage solutions (local storage, sqlite, etc). If your app doesn't use a backend, there is a solution to persist the data on the device even if the app is uninstalled.

Follow me for updates on similar new posts I write or tweet about this post.