Getting Started with In-App Purchases

Instant Games In-App Purchases (IAP) provide a way for developers to leverage micro-transactions in their Instant Games on Facebook.com and Messenger for Android. Developers will be able to immediately test IAP in their games. Once a game has passed through In App Purchase review, players will be able to make purchases on Android and Facebook.com.

In App Purchases are supported on Android 6 and above.

Getting Started

The first step of enabling In App Purchases is to configure the products that you would like to make available to players and configure payout information. This can be done on the In App Purchase tab under the Instant Games product.

Select or create a company that will the designated recipient of payouts from Instant Games in-app purchases. You can find more information here.

Integrating on Web

Detecting whether payments is available

Payments in Instant Games are only supported on Facebook.com (not Messenger.com) and on Android once you have passed review. Your code should ensure that payments are available on the player's device before showing any payments functionality.

As with other Instant Games APIs, use getSupportedAPIs and look for payments.purchaseAsync.

If available, subscribe to payments.onReady with a callback as follows.

FBInstant.payments.onReady(function () {
  console.log('Payments Ready!');
});

If getSupportedAPIs does not contain payments.purchaseAsync, then payments is not supported on the device.

If the callback set in payments.onReady is never called, payments is also not supported for this session and no payment related functionality should be used.

Rendering the store

Use the getCatalogAsync method to get product information.

FBInstant.payments.getCatalogAsync().then(function (catalog) {
  console.log(catalog); // [{productID: '12345', ...}, ...]
});

Handling a purchase

When a player shows intent to purchase an item, you can trigger the purchase confirmation dialog using purchaseAsync.

FBInstant.payments.purchaseAsync({
  productID: '12345',
  developerPayload: 'foobar',
}).then(function (purchase) {
  console.log(purchase);
  // {productID: '12345', purchaseToken: '54321', developerPayload: 'foobar', ...}
});

Verifying a Purchase

It is possible to verify that a payment has occurred on a backend system by parsing the signedRequest value that is returned with the payment object.

The signedRequest consists of two parts seperated by the . character. The first part is a Base64 encoded SHA256 hash of the payment information, while the second part is the same payment information encoded directly in Base64.

You can validate that the payment information is authentic by using the following code (Node.js sample supplied):

Never embed your app secret into your game. The signedRequest should only be validated in server-side code.

const CryptoJS = require('crypto-js');
var firstpart = signedRequest.split('.')[0];
firstpart = firstpart.replace(/-/g, '+').replace(/_/g, '/');
const signature = CryptoJS.enc.Base64.parse(firstpart).toString();
const dataHash = CryptoJS.HmacSHA256(signedRequest.split('.')[1], '<APP_SECRET>').toString();
var isValid = signature === dataHash;
const json = CryptoJS.enc.Base64.parse(request.split('.')[1]).toString(CryptoJS.enc.Utf8);
const data = JSON.parse(json);

console.log(validated); // this will be true if the payment is verified as coming from the game
console.log(data); // a JSON object as follows:

/*
{  
   "algorithm": "HMAC-SHA256",
   "developer_payload": "foobar",
   "is_consumed": false,
   "issued_at": 1524772799,
   "payment_id": "12345667512",
   "product_id": "your_product_id",
   "purchase_time": 1524772796,
   "purchase_token": "14245790188",
}
*/

Getting a player's purchased items

Use getPurchasesAsync to get the player's unconsumed purchases.

FBInstant.payments.getPurchasesAsync().then(function (purchases) {
  console.log(purchases); // [{productID: '12345', ...}, ...]
});

Consuming a purchased item

When a player decides to use a purchased item, call consumePurchaseAsync and award the effect of the item. Once called, the item will no longer be returned by getPurchasesAsync.

If the item is a non-consumable product, don't call consumePurchaseAsync. This purchase will always be listed in getPurchasesAsync.

FBInstant.payments.consumePurchaseAsync('54321').then(function () {
  // Purchase successfully consumed!
  // Game should now provision the product to the player
}).catch(function(error) {
  // Handle error
});

Testing Transactions

Users added to the Testers section of the Set Up pane on the In App Purchase tab will not be charged for items in your game. This can be used to test purchase functionality without performing real transactions.

Test transactions are only supported on Android at this time.

Sending for Review

Before In App Purchases will work across all platforms, there are several checks that must me made.

The app must be approved for Audience Network and also pass a functional In App Purchase review. Instant Games can be submitted for In App Purchases on the Review tab.

On the In App Purchase tab, statuses are shown to help you determine which of these activities need to be completed.

Payout

Payout should be received in 90 day windows.

For purchases made in web versions of Instant Games on Facebook.com, the revenue share model will remain what it has been historically for games on the Facebook platform at 70%/30%.

On mobile, Instant Games follow in-app billing terms from each platform. For purchases made in games on Google Play, a 30% revenue share will apply after the standard mobile platform revenue share. Our primary goal is to build IAP in a way so that our developer partners can sustain and grow, and we'll continue to evaluate rev/share with that goal in mind.

On Facebook.com: developers take home $0.70 of every dollar earned with $0.30 fee to Facebook.

On Google Play: After a standard revenue share of 30% to Google, developers will take home $0.49 of each dollar earned in IAP - i.e. $0.49 to developers, $0.30 to mobile platform, and $0.21 to Facebook