In-App Purchases in PWAs
Updated: Feb 20, 2025
This topic discusses how to integrate add-ons with in-app purchase into your PWAs.
The
Digital Goods API is a web API that allows Progressive Web Apps (PWAs) to sell digital goods and services, such as in-app purchases. This API enables PWAs to provide a seamless purchasing experience for users, while also generating additional revenue streams.
Currently, Meta Horizon OS only supports the in-app purchase feature of Digital Goods API in WebXR PWAs, with the support of subscriptions coming at a later date.
This is a Platform SDK feature requiring Data Use Checkup
To use this or any other Platform SDK feature, you must complete a Data Use Checkup (DUC). The DUC ensures that you comply with Developer Policies. It requires an administrator from your organization to certify that your use of user data aligns with platform guidelines. Until the app review team reviews and approves your DUC, platform features are only available for test users.Currently in Meta Horizon OS, the Digital Goods service is only available for WebXR PWAs that’s installed from the Meta Horizon Store (including ALPHA and BETA channels). If available, the method window.getDigitalGoodsService()
can be called in Javascript with a the quest billing URL. The method returns a promise that is rejected if the given service provider is not available.
Here is an example wrapper function that calls window.getDigitalGoodsService()
:
async function getDigiGoodsService() {
if (!("getDigitalGoodsService" in window)) {
throw new Error('Digital Goods service not supported in this browser.');
}
let service = undefined;
try {
service = await window.getDigitalGoodsService('https://quest.meta.com/billing');
console.log('got digital goods service');
} catch (e) {
service = undefined;
console.error(`Error! ${e.message}`);
throw e;
}
return service;
}
Querying item details by item ID (SKU)
The getDetails()
method returns server-side details about a given set of items, intended to be displayed to the user in a menu, so that they can see the available purchase options and prices without having to go through a purchase flow.
For example:
const service = await getDigiGoodsService();
const details = await service.getDetails([itemId]);
The item ID is a string representing the primary key of the items, configured in the Meta Horizon Store Developer Center as the item’s “SKU”. There is no function to get a list of item IDs; those have to be hard-coded in the client code or fetched from the developer’s own server.
The returned ItemDetails
sequence can be in any order and might not include an item if it doesn’t exist on the server (i.e., there is not a 1:1 correspondence between the input list and output).
The
Payment Request API can be used to initiate a user in-app purchase inside a WebXR PWA with a specific item ID. After this API is called, a system in-app purchase dialog would pop up and the user can make the payment with Meta Horizon Store.
For example:
async function purchase(itemId) {
const paymentMethods = [{ supportedMethods: "https://quest.meta.com/billing", data: { sku: itemId, } }];
const request = new PaymentRequest(paymentMethods);
const response = await request.show();
const purchaseToken = response.details.purchaseToken;
console.log(`got purchase token: ${purchaseToken}`);
return purchaseToken;
}
To test purchases with a sideloaded .apk, visit chrome://flags in Browser and enable #enable-debug-for-store-billing
. This is not a requirement when installing the app from the Store.
Retrieve the user’s purchased items
You can call the listPurchases()
API to retrieve a list of IAP purchases that the user has made. The returned list includes all durable type purchases and any consumable type purchases that have not been consumed.
For example:
async function listPurchases() {
const service = await getDigiGoodsService();
const purchases = await service.listPurchases();
return purchases;
}
Meta Horizon Store doesn’t support purchase history. The return value of
listPurchaseHistory() API would be the same data as the
listPurchases()
method.
All Meta Quest developers are required to indicate their app’s intended age group via a self-certification flow. For more information, check
determining your app age group.
If your PWA’s target age group is Mixed Ages, then you are required to implement the Get Age Category API in your PWA and make sure it is called every time your PWA is launched. For more information, check
Age group self-certification and youth requirements.
The DigitalGoodsService.getUserAccountAgeCategory()
API is exclusive to PWAs running on Meta Horizon OS.
async function getUserAccountAgeCategory() {
const service = await getDigiGoodsService();
const userAgeCategory = await service.getUserAccountAgeCategory();
return userAgeCategory;
}
Retrieve ID of the current user
You can retrieve the unique ID for the current user, you can use
DigitalGoodsService.getLoggedInUserId()
. This method returns a 16 digit id and would return
6
if something goes wrong. The most common cause of faiulre is the absence of
Data Use Checkup of your application. The user ID returned by this method is specific only to this application.
Note: The DigitalGoodsService.getLoggedInUserId()
API is exclusive to PWAs running on Meta Horizon OS.
async function getLoggedInUserId() {
const service = await getDigiGoodsService();
const userId = await service.getLoggedInUserId();
return userId;
}