If your PWA is listed in Google Play and you want to monetize it by selling in-app products or subscriptions, Play policywill require you to implement Play Billing. There are two APIs that you will need to implement in your PWA: the Digital Goods APIand the Payment Request API.
The Digital Goods APIis an interface between your app and Google Play. It allows you to retrieve the digital products and details you’ve entered for your in-app products and subscriptions in the Play Console as well as retrieve existing purchases a user has made. If you haven’t added in-app products or subscriptions in the Play Console yet, make sure to follow the Play Console setup for Play Billing.
Note that the Digital Goods API is currently available through an Origin Trial- a mechanism that allows developers early access to new Web APIs. You will need to register for the trialand request a token. You will see a “Valid Until” date which is when your token is guaranteed to work until. Remember to renew your token when that date approaches to continue participating in the trial. APIs offered as an origin trial are subject to change, in case of any issues, refer to the Digital Goods API documentation.
The Payment Request APIhandles the actual payment transaction when a purchase is made. It utilizes the item details that the Digital Goods API provides to make the in-app purchase using the appropriate payment method, which in our case is Google Play Billing.
The Digital Goods API is currently only supported by Chrome if your PWA was installed via a Google Play app. You can detect if the API is available by checking for the
getDigitalGoodsService method in the
The Digital Goods API was designed to be compatible with various browsers and digital stores, similar to how the Payment Request API is browser-agnostic and can be used with different payment providers. To obtain an instance of the service associated with Google Play Billing, pass the string
"https://play.google.com/billing" as the payment method to
If the Google Play Billing payment method is not available (e.g. the user is accessing your PWA through the browser), you may offer another payment method for transactions.
Once you have the Digital Goods service connected to Google Play, you can use the API to retrieve information about products and purchases.
getDetails() method lets you get information about the items you’ve set up in the Play Console. Information like the product title, description, and price should be displayed to the user in your app UI so they know what is available for purchase and for how much.
getDetails() method will need a list of item IDs which correspond to the product IDs of the in-app products and subscriptions you created in the Play Console.
To get the appropriate price for the user’s locale, you will need to do some additional formatting:
Once your products and details are displayed to the user, you can build the purchase flow with the Payment Request API. When used in conjunction with the Digital Goods API, only one input parameter is required:
Play Billing only allows the purchase of a single item at a time; the price and details of the item are already known by the Play server, so the
detailsparameter is not necessary. See the explainerfor a more detailed explanation.
supportedMethods member of the
methodDataparameter in the
PaymentRequest to identify Google Play Billing as the payment method with the string
"https://play.google.com/billing". Then in the
data member, pass along the item ID as the
Then create the payment request and call
show() to start the payment flow:
This will display the Play purchase UI to the user, where they’ll see the details about the product they’re trying to purchase. They can either abandon the transaction or proceed with the payment. If the user cancels the payment, the promise returned by
show() will be rejected with an error. If they successfully pay and complete the purchase, the promise will resolve with a
PaymentResponse. In the
details property of the payment response, a purchase token is returned.
To prevent fraud, it’s critical to verify the purchase and purchase token on your back-end server. It’s also a good idea to keep track of users and their associated purchase tokens. Learn how to implement the verification on your back-end server.
After validating the purchase, call
complete() on the payment response to finish the payment flow and close out the billing UI. You can also pass in an optional
result string to indicate the state of the payment process. It is up to the browser whether to provide any indication of this result to the user. Chrome does not create any user-visible cues so it is recommended that you display your own error or success messages in your PWA.
This purchase flow is the same for both in-app products and subscription purchases. However, for subscriptions, Google Play has additional purchase options you can implement: upgrade and downgrade. When building the
data for the payment method, you’ll need to pass in the following to initiate an upgrade or downgrade flow:
sku: This is the item ID for the new subscription to be upgraded or downgraded to.
oldSku: This is the item ID for the user’s current subscription.
purchaseToken: This is the purchase token for the user’s current subscription. Like it was noted earlier, it’s a good idea to keep track of the purchase tokens in your backend. And for this scenario and others, you should associate a user to their current purchases and purchase tokens as well.
prorationMode: This is how the new subscription will be charged when it replaces the user’s current subscription.
|immediateAndChargeProratedPrice||The subscription is upgraded immediately, and the billing cycle remains the same. The price difference for the remaining period is then charged to the user.|
|immediateWithoutProration||The subscription is upgraded or downgraded immediately, and the new price is charged when the subscription renews. The billing cycle remains the same.|
|immediateWithTimeProration||The subscription is upgraded or downgraded immediately. Any time remaining is adjusted based on the price difference, and credited toward the new subscription by pushing forward the next billing date. This is the default behavior.|
|deferred||The subscription is upgraded or downgraded only when the subscription renews. This is useful for downgrades especially.|
|unknownSubscriptionUpgradeDowngradePolicy||No set policy. This is not recommended.|
Learn more about the different proration modes in the Google Play Billing Library reference documentation. Check out the Android developer docs for more on subscription upgrade and downgradesand proration mode recommendations.
The usage of these additional fields will look something like this:
item is the
ItemDetails of the new subscription the user is trying to upgrade or downgrade to, and
oldPurchase is the
PurchaseDetails of the user’s current subscription.
After a user purchases an item, you should grant them the proper entitlements (access to the item or content they’ve just purchased). Then, use the Digital Goods API to acknowledge the purchase. Acknowledging a purchase lets Google Play know that you’ve received and processed the purchase appropriately.
The Digital Goods API requires a purchase to be acknowledged with a
PurchaseType of either
"repeatable". This is something that you determine client-side and is not something you set when you create your in-app products and subscriptions in the Play Console. It is recommended that you keep track of each item’s purchase type in your back-end server. If you also fetch your list of item IDs from the back-end server, you can store the item ID and purchase type as a key-value database.
|in-app product||onetime||When a user should only buy a product once and will own it forever (non-consumable item), or when a user can only own one instance of it at a time (needs to be consumed before they can purchase another).|
|repeatable||When a user can buy and own multiples of a product (consumable item).|
|subscription||onetime||Subscriptions are always acknowledged as ‘onetime’ because a user should only have at most one instance of each subscription.|
acknowledge() with the
purchaseToken string that was returned earlier by the payment response in the
data member, along with the appropriate purchase type.
When you acknowledge a purchase with the
onetime purchase type, this lets Google Play know that the user now owns the item and should not be allowed to purchase it again. If this is an item that the user will only need to purchase once and will own forever (e.g. a game character skin), then the item is not consumable.
Alternatively, the item may be something that you limit a user to one of at a time. Then the user will need to use or consume the item before they can purchase another one. To let Google Play know that the user has consumed the item, you should call the
acknowledge() method with the
"repeatable" purchase type. Google Play will then make the item available for the user to purchase again.
The last key user flow is to check for existing entitlements (in-app products that haven’t been consumed yet and on-going subscriptions). These existing entitlements will be from previous Google Play purchases on any device made in-app or on the Play Store, or from a redeemed promo-code.
This is also a good place to check the purchase status and acknowledge any purchases that were previously made but did not properly get acknowledged. It is recommended that purchases get acknowledged as soon as possible so the user’s entitlements are up-to-date and properly reflected in the app.
listPurchases() will return a list of
PurchaseDetails that has more information about the purchases.
To protect your app from potential bad actors, you should not rely only on the client side to get purchases. Learn more about how to verify purchases on your back-end server before granting entitlements.
These user flows and code snippets are a basic implementation to demonstrate how to use the DIgital Goods API and Payment Request API in your PWA to implement Play Billing. You should utilize the APIs as it makes sense in your app’s context and use cases. For an example of an end-to-end implementation, check out our open-source sample.
Then, take a look at how to implement crucial Play Billing components in your back-end server to keep your app secure and always updated with your user’s entitlements.