Use Google Play Billing in your Trusted Web Activity

This guide is for web apps packaged as a Trusted Web Activity. For Android apps written in Kotlin or Java, see the Google Play Billing documentation.

Apps on Google Play that sell digital goods or subscriptions must use Google Play Billing. In a Trusted Web Activity, you integrate with it using the following web APIs, available in Chrome 101 and later on Android and ChromeOS:

Requirements

To set up Google Play Billing, you need the following:

Don't charge users to download your app from the Play Store. Your PWA is still available on the web, so a paid download doesn't restrict access. Instead, sell features or content with in-app purchases or subscriptions.

Enable Play Billing in your Android project

If you build your app with Bubblewrap, enable the playBilling feature in twa-manifest.json at the root of your project:

"features": {
  "playBilling": {
    "enabled": true
  }
}

Then run bubblewrap update followed by bubblewrap build, and upload the new Android package to the Play Store.

If you build your app in Android Studio, add the Android Browser Helper Play Billing library. For the required DelegationService and AndroidManifest.xml changes, see the twa-play-billing demo.

Check for Google Play Billing support

Call getDigitalGoodsService() with the Play Store identifier, https://play.google.com/billing. If the method is missing or the call fails, use another payment flow:

if ('getDigitalGoodsService' in window) {
  try {
    const service =
        await window.getDigitalGoodsService('https://play.google.com/billing');
    // Google Play Billing is available.
  } catch (error) {
    // Google Play Billing isn't available. Use another payment flow.
  }
}

Display product details

Use getDetails() to retrieve the title, description, and price for your product IDs, so that the prices you display match the Play Store:

const details = await service.getDetails(['shiny_sword', 'gem']);
for (const item of details) {
  const localizedPrice = new Intl.NumberFormat(
      navigator.language,
      {style: 'currency', currency: item.price.currency}
  ).format(item.price.value);

  renderProductDetails(
      item.itemId, item.title, localizedPrice, item.description);
}

The Digital Goods API can't list your product IDs. To query them from your backend, use the Google Play Developer API.

Make a purchase

Create a PaymentRequest with https://play.google.com/billing as the payment method and the product ID as sku in data. Google Play Billing uses the price from the Play Console, so total is required but ignored.

After show() resolves, send the purchase token to your backend to verify and acknowledge the purchase. If you don't acknowledge a purchase within three days, Google Play refunds the user and revokes the purchase.

async function makePurchase(service, sku) {
  const paymentMethods = [{
    supportedMethods: 'https://play.google.com/billing',
    data: {sku},
  }];
  // Required by the Payment Request API, but ignored by Google Play Billing.
  const paymentDetails = {
    total: {label: 'Total', amount: {currency: 'USD', value: '0'}},
  };

  const request = new PaymentRequest(paymentMethods, paymentDetails);
  try {
    const response = await request.show();
    const {purchaseToken} = response.details;

    if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) {
      // Optional: consume the purchase so the user can buy the item again.
      await service.consume(purchaseToken);
      await response.complete('success');
    } else {
      await response.complete('fail');
    }
  } catch (error) {
    // An AbortError usually means the user canceled the purchase.
  }
}

Check a user's purchases

Use listPurchases() to find items the user owns, such as active subscriptions, unconsumed purchases, or redeemed promo codes. Verify each purchase on your backend, and acknowledge any you haven't acknowledged:

const purchases = await service.listPurchases();
for (const p of purchases) {
  await verifyOrAcknowledgePurchaseOnBackend(p.purchaseToken, p.itemId);
  // Update the UI with items the user is entitled to.
}

Test your integration

To test on an Android device before you publish to the Play Store, follow these steps:

  1. Use Android 9 or later with developer options enabled.
  2. In Chrome, go to chrome://flags and enable #enable-debug-for-store-billing.
  3. Serve your site over HTTPS. The Digital Goods API isn't available over HTTP.

When your app is installed from the Play Store, you don't need the flag. To test with test accounts and test products, see Test your Google Play Billing Library integration.

Next steps