avatarRoss Bulat

Summary

This article explains the process of validating Google Play in-app purchases server-side using the google-play-billing-validator package in a Node.js environment.

Abstract

In-app purchase validation is a critical task for ensuring the integrity of purchase tokens and transaction records. The google-play-billing-validator package can be used in a Node.js environment to validate receipts server-side. Before using the package, some setup is required on the Google Play side to gain API access to in-app purchase history. This involves creating a service account with access to Google Play developer services and enabling financial data permissions. The package can be installed using NPM or yarn, and the private key and client email from the private key file are required to authenticate API calls. The package provides two methods for validation: verifyINAPP for one-time purchases and verifySub for subscriptions. Both methods require the product ID and purchase token as arguments. The response data structures for successful and failed validations are also discussed.

Opinions

  • In-app purchase validation is important for maintaining the integrity of purchase tokens and transaction records.
  • The google-play-billing-validator package is a useful tool for validating receipts server-side in a Node.js environment.
  • Setting up API access to in-app purchase history on the Google Play side is a necessary prerequisite for using the package.
  • The package provides clear and concise methods for validating one-time purchases and subscriptions.
  • The response data structures for successful and failed validations are well-documented and easy to understand.
  • Logging error messages is important for tracking breakages in the validation setup.
  • The article provides useful links to further reading on in-app purchases and subscriptions.

Google Play In App Purchase Validation in Node.js

How to validate in-app purchases server side for Google Play apps

Introduction

In-app purchase validation is a critical task that every app supporting purchases and subscription should implement as a means to prove the integrity of purchase tokens and transaction records. Validation can be used to validate a newly created transaction or validate a subscription to check it is still active.

An in-app purchase is initiated on a user’s device; the user authenticates a purchase which is then processed on Google servers, and a successful response should be sent back to the user’s device.

It is with this successful response that a purchaseToken is provided — a unique string that acts as a receipt of the purchase. In order to validate a purchase with Google Billing at any time in the future, the purchaseToken must be supplied to such API calls, that will be discussed further down.

Needless to say, the purchaseToken should be securely persisted in your database and associated with a particular user of your app, otherwise it would not be possible to validate any purchases made by that user.

This article will explain the setup process of validating Google Play in-app purchases. It is split into two parts:

  • Part 1: Walking through the process of setting up the necessary credentials on Google Cloud Platform and Google Play Console for in-app purchase receipt validation. This entails a Service Account with access to Google Play developer services to access in-app purchase history, that exists under the financial data umbrella of permissions.
  • Part 2 will demonstrate how to integrate the google-play-billing-validator package in a Node.js environment in order to validate receipts server side on your server at any time. Both a purchaseToken and productId need to be provided, along with your App ID, to successfully validate an in-app purchase or subscription.

Note that google-play-billing-validator (or other means of validation) should also be used in the initial transaction processing stage after a purchaseToken is generated and sent to your endpoint that processes successful in-app purchases. This initial validation can be achieved with the code we’ll discuss further down.

This piece focuses on the validating purchases after they have been made. If you are looking for detailed instructions on how to set up in-app purchases and subscriptions for React Native, check out my published piece: In App Purchases and Subscriptions in React Native: 2021 Walkthrough.

Before delving into Node.js, some setup is required on the Google Play side in order to gain API access to your app’s in-app purchase history. Let’s cover this setup process next.

Gaining API Access to In App Purchases

The prerequisites of setting up API Access for your in-app purchases are:

  • Access to the Google Play Console where your apps are hosted. Signing up to Google Play requires a one-off fee of $25.
  • A Google Cloud Platform account, that could either be on a free trial or fully activated account.

Setting up a GCP project and service account

This section will summarise the important steps for our in-app purchase validation requirements. Google provide instructions for this initial setup here; a page worth visiting for new users.

From your Google Play Console, find the API Access option under the Setup menu. Alternatively, search for API Access in the search bar.

If you are accessing the API Access page for the first time you will need to accept some terms and conditions as well as create a project on Google Cloud Platform. Click Create new project to do just that — the project will automatically be generated and linked to your Google Play Console.

So what just happened with this automated project generation? Google set up a pre-configured project with all the necessary roles enabled for Google Play access (as well as access to the majority of their cloud services).

If you visit the Roles menu option from Google Cloud Platform you can see quite an exhaustive list of roles, that created service accounts under the project can inherit from:

The Roles page for a Google Cloud Platform project

In any case, with the GCP project now created you are able to add a service account that will act as the identity accessing in-app purchase data when making API calls.

Back in Google Play Console, the following dashboard is now presented on the API Access page:

Finding API Access settings in Google Play Console

Under the Service Accounts section, click Create new service account. This opens a modal that provides instructions on how to set up the service account from your Google Cloud Platform console:

Instructions for creating a new service account

A service account can be thought of as an identity that can be configured to have access to various APIs in the Google ecosystem. Service accounts are Google’s solution for access control.

Once a service account is created, the private key and email address associated with the service account can be used to make API requests to the granted services.

Follow the instructions presented in the above modal and ensure that you download your private key file; a JSON file containing credentials needed to make API requests when using google-play-billing-validator.

We will be interested in the private_key and client_email fields within this file.

Once your service account is created we can verify that it has been successfully linked to Google Play. Not only will the account be under Service accounts in API Access, but also in Users and permissions, that can be found in the Google Play Console main menu:

Users and permissions from Google Play Console

Clicking the blue arrow next to the service account and opening the Account permissions tab will reveal the account permissions the service account has been granted (you can also toggle the permissions from here).

Notice that the account has full access to the financial data items, giving the service account access to IAP history, subscriptions and order management:

Financial data permissions switched on, ready for IAP validation

Here is where things begin to make sense in regards to in-app purchases; the service account is now configured and we can start communicating with the data.

Integrating Google Play Billing Validator

yarn add google-play-billing-validator

The version installed at the time of writing was 2.1.3.

Firstly, import the package along with your private key file for authenticating with the API service.

// import validator and private key
const GoogleReceiptVerify = require('google-play-billing-validator')
const ServiceAccount = require('./service-account-key')

Do not commit your private key file to source control, SSH into your server to securely embed the file.

Instantiate a new GoogleReceiptVerify object from the package, feeding in your private_key and client_email fields from your private key file as an argument:

// instantiate google receipt verify
var googleReceiptVerify = new GoogleReceiptVerify({
  email: ServiceAccount.client_email,
  key: ServiceAccount.private_key
});

From here we can either call the googleReceiptVerify.verifyINAPP method to validate a one-time purchase, or googleReceiptVerify.verifySub to validate a subscription. Both API calls require the Product ID as well as the purchase token that was generated at the time of the initial purchase.

The following code provides a solution for the verifySub call, that sources the expiry timestamp from the response payload:

The validation process is relatively simple, only requiring one API call. Note that both verifyINAPP or verifySub are asynchronous functions, so ensure that you await their resolution in an async function.

API Response Data Structures

Depending on whether you use verifyINAPP or verifySub, a different data structure is returned in a payload field in your response object.

Take note of the following structures for your own implementation:

  • verifyINAPP will return a ProductPurchase object that is referenced in Google’s developer API reference here.
  • verifySub will return a SubscriptionPurchase object that is referenced in Google’s developer API reference here.

Notice that SubscriptionPurchase offers more verbose data such as introductory pricing, expiry timestamp, cancellation metadata and promo code meta data.

Concretely, all the data related to a particular purchase or subscription is returned in either the ProductPurchase or SubscriptionPurchase results that you can use to execute further processing for your app’s database, whether that be updating a user record, processing analytics, or updating a subscription status if the validation fails.

Failed Validation Data Structure

If a purchaseToken fails to validate an errorMessage will be returned along with an isSuccessful boolean of false:

// sample failed validation response
{
  "isSuccessful": false,
  "errorMessage": "The purchase token does not match the product ID."
}

There are a number of reasons that a validation could fail with a corresponding error message:

  • Invalid product ID: The purchase token does not match the product ID.
  • Invalid purchase token: The purchase token was not found.
  • Invalid package name: No application was found for the given package name.
  • Invalid service account email: Not a valid email or user ID.
  • Invalid private key: Invalid JWT Signature.
  • Insufficient service account permissions: The current user has insufficient permissions to perform the requested operation.

This error message structure ensures that you can drill down any issue that validation attempts may discover over time as your app infrastructure is maintained.

Expired service accounts (if an expiry time is set up), changes in product IDs, and updates of service account permissions are all actions that could result in unintentional breakages in your validation setup. Log your error messages to keep track of breakages in your setup.

In Summary

Validating in-app purchases is a two step process that firstly requires API Access of Google’s developer APIs. This entails setting up a service account within a Google Cloud Platform Project that is generated for you automatically.

A private key file is provided with a newly created service account which is then required to authenticate API calls from Our Node.js script.

Within a Node.js environment, the google-play-billing-validator package can be used to validate purchaseTokens with minimal code. A successful response’s payload object is consistent with Google’s API reference, with all the associated data of the IAP being provided.

Further reading on in-app purchases and subscriptions

For more walkthrough on implementing in-app purchases with React Native and Node.js, for both iOS and Android, check my previously published articles on the subject.

Nodejs
Software Engineering
JavaScript
Android App Development
Programming
Recommended from ReadMedium