Validate Google Play purchases

This guide shows you how to set up and validate Google Play purchases and subscriptions with Nakama.

Before you begin #

Make sure you have:

  • A Google Play Console account
  • Access to Google Cloud Console for creating service accounts
  • An Android app configured for in-app purchases in Google Play Console

Configure Google Play credentials #

To validate receipts against the Play Store, you’ll need the client_email and private_key from a Google Cloud Service Account that has been granted access to your app in the Google Play Console.

Step 1

Create a Google Cloud Service Account #

  1. Go to the Google Cloud Console.
  2. Select your project (or create a new one).
  3. Navigate to IAM & Admin > Service Accounts.
  4. Click Create Service Account.
  5. Enter a name (e.g., “Nakama IAP Validator”) and description.
  6. Click Create and Continue.
  7. Click Done.

Create Service Account
Create Service Account

Step 2

Create a JSON key #

  1. Back on the Service Accounts page, make a note of your newly created service account’s email. You’ll need it later.
  2. Click on the service account in the list.
  3. Navigate to the Keys tab.
  4. Click Add Key > Create new key.
  5. Select JSON as the key type.
  6. Click Create - a JSON file will be downloaded to your computer.

The JSON file contains the client_email and private_key that Nakama needs. Keep this file secure.

Create JSON Key
Create JSON Key

Step 3

Enable the Google Play Developer API #

  1. Navigate to the Google Play Developer API page in Google Cloud Console.
  2. Click Enable.
Step 4

Grant Service Account access in Google Play Console #

  1. Open the Google Play Console.

  2. Navigate to Users and permissions.

  3. Click Invite new users.

  4. Enter the email address of the service account you created earlier.

  5. Under App permissions (or Account permissions), grant these permissions:.

    • View app information and download bulk reports (read only)
    • View financial data, orders, and cancellation survey responses
    • Manage orders and subscriptions
  6. Click Invite user to save the permissions

It may take up to 24 hours for the service account permissions to fully propagate through Google’s systems
Step 5

Configure Nakama #

From the JSON key file you downloaded, extract the client_email and private_key values and configure them in Nakama:

1
2
3
4
iap:
  google:
    client_email: "nakama-iap-validator@your-project.iam.gserviceaccount.com"
    private_key: "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBg...your-key-here...\n-----END PRIVATE KEY-----\n"

Troubleshooting #

If validation fails with permission errors:

  • Verify the service account has been granted the correct permissions in Google Play Console.
  • Wait 24 hours after granting permissions for changes to propagate.
  • Ensure the client_email and private_key exactly match the values in your JSON key file.
  • Check that you’re using the correct Google Play Console account that owns the app.

Validate a purchase #

To validate a Google Play purchase, you’ll send the purchase data returned by the Google Play Billing library to Nakama’s validation endpoint. Nakama verifies the purchase with Google’s servers and returns the validated purchase details.

The Google receipt expected is the string returned by Purchase.getOriginalJson(). See the official Google Developer docs for more details.

Refer to the function reference page for the provided runtime purchase validation functions.

Validate a subscription #

Subscription validation for Google Play works similarly to purchase validation, returning subscription-specific information like expiry time, active status, and auto-renew preferences.

Refer to the function reference page for the provided runtime subscription validation functions.

Handle refunds and subscription changes #

Google Play supports real-time developer notifications to monitor IAP state changes in real-time. Nakama can receive these notifications to track subscription renewals, expirations, cancellations, and refunds automatically.

Set up notification callbacks #

To activate the callback URL, set the notifications_endpoint_id configuration, which creates the following endpoint path: /v2/console/google/subscriptions/<notifications_endpoint_id>.

Configure this URL in the Google Play Console as a Cloud Pub/Sub topic that pushes to this endpoint.

Automatic state updates #

Once you’ve configured the callback URL, Nakama automatically updates the state of any purchase or subscription that was previously validated through the validation APIs above. This keeps subscription expiry times, active status, and other metadata synchronized with Google Play.

Notifications only work for purchases and subscriptions that you’ve already validated through Nakama’s client APIs. If Google sends a notification for a purchase Nakama hasn’t seen before, it’ll be ignored.

Notification types #

Nakama normalizes Google’s notifications into 5 simplified types:

TypeDescription
SUBSCRIBEDInitial subscription purchase or resubscription
RENEWEDSubscription successfully auto-renewed
EXPIREDSubscription expired and will not renew
CANCELLEDSubscription cancelled by user or Google Play
REFUNDEDPurchase or subscription refunded

These normalized types match those used for Apple, making it easier to handle notifications consistently across platforms.

Implement notification hooks #

You can register custom code to respond to notifications for purchases and subscriptions. The hooks fire after Nakama has automatically updated the purchase/subscription state in the database.

Use these hooks to implement your own business logic when IAP states change—like revoking player access when a subscription expires, sending analytics events, or triggering in-game rewards for renewals.

Purchase notifications #

Register a hook to handle purchase refunds. The purchase parameter contains the validated purchase data. See Response contents for available fields.

Subscription notifications #

Register a hook to handle all subscription state changes. The subscription parameter contains the validated subscription data - see Response contents for available fields.

See also #