The Digital Goods API is a web API for selling digital goods and services from a PWA.
Meta Horizon OS currently supports in-app purchases through the Digital Goods API only in WebXR PWAs. Subscriptions are not currently supported.
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 team 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.
Getting started
Currently in Meta Horizon OS, the Digital Goods service is only available for WebXR PWAs that are installed from the Meta Horizon Store (including ALPHA and BETA channels). If available, the method window.getDigitalGoodsService() can be called in JavaScript with 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. That is, there is not a 1:1 correspondence between the input list and output.
Initiate a purchase
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) {
// The 'paymentDetails' values are not actually used in the paymentRequest so dummy values are okay. The most important is that paymentMethods should be correctly populated.
const paymentDetails = { total: { label: 'Total', amount: {currency: 'USD', value: '0'} } };
const paymentMethods = [{ supportedMethods: "https://quest.meta.com/billing", data: { sku: itemId, } }];
const request = new PaymentRequest(paymentMethods, paymentDetails);
const response = await request.show();
const purchaseToken = response.details.purchaseToken;
console.log(`got purchase token: ${purchaseToken}`);
await response.complete('success');
return purchaseToken;
}
Call complete() after recording the purchase token. Otherwise, Chromium can block user input until the payment response times out.
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.
Getting user age group
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 WebXR PWA’s target age group is Mixed Ages, then you are required to implement the Get Age Category API and call it every time your WebXR PWA launches. For more information, check Age group self-certification and youth requirements.
The DigitalGoodsService.getUserAccountAgeCategory() API is exclusive to WebXR PWAs running on Meta Horizon OS.
async function getUserAccountAgeCategory() {
const service = await getDigiGoodsService();
const userAgeCategory = await service.getUserAccountAgeCategory();
return userAgeCategory;
}
Retrieve the current user’s ID
Use DigitalGoodsService.getLoggedInUserId() to retrieve the current user’s app-scoped ID. A value of 0 means that no logged-in user ID is available. Review the Data Use Checkup requirements before requesting user data.
Note: The DigitalGoodsService.getLoggedInUserId() API is exclusive to WebXR PWAs running on Meta Horizon OS.
async function getLoggedInUserId() {
const service = await getDigiGoodsService();
const userId = await service.getLoggedInUserId();
return userId;
}