TECH

Play Store in-app purchase verification on the server | One-time (managed) product

In this article, we'll dive into how to verify one-time (managed) products on your server after an in-app purchase is completed on your Android app. W

Hitesh Verma Jun 5, 2024 · 5 min. read

In this article, we'll dive into how to verify one-time (managed) products on your server after an in-app purchase is completed on your Android app. We'll use TypeScript on a Node.js server, but the logic can be adapted to any backend framework.

Photo by <a href="https://unsplash.com/@cardmapr" target="_blank">CardMapr.nl</a> on <a href="https://unsplash.com" target="_blank">Unsplash</a>
Photo by CardMapr.nl on Unsplash

1. Add the service account key

Save the service account key with Android Publisher permission in your project folder. If you don't know how to get this service account key, then read this article.

2. Store Product Information

Ensure that all product IDs set up on the Play Store, along with their associated prices, are saved in your database.

3. Setup the API

Create a POST API endpoint /play_store/managed_products/verify

4. Add Authorization

Implement authorization checks for this API to secure it. For simplicity, we will skip this step here.

5. Validate the Request

Ensure the request body contains the following parameters:
a. packageName: The application ID of your Android app.
b. productId: The ID of the product for which the payment was made.
c. purchaseToken: The token received after successful payment.

6. Install googleapis package

npm i googleapis

7. Create the Controller Class with verify method

import { google } from "googleapis";

export class PaymentsController {
  /**
   * Verify play store managed product in-app purchase
   */
  async playStoreManagedProductVerify(req: any, res: any): Promise<void> {
    const {packageName, productId, purchaseToken} = req.body;

    const auth = new google.auth.GoogleAuth({
      keyFile: "path/to/service/account/key/json",
      scopes: ["https://www.googleapis.com/auth/androidpublisher"],
    });

    const androidPublisher = google.androidpublisher({
      auth,
      version: "v3",
      params: { sandbox: true },
    });

    const res = await androidPublisher.purchases.products.get({
      packageName: packageName,
      productId: productId,
      token: purchaseToken,
    });

    if (res.data.purchaseState === 0) {
      console.log(res.data);
      // TODO: Handle the verification response
      res.send({message: "Payment verified successfully"});
    } else {
      res.status(400).send({message: "Failed to verify the payment"});
    }
  }
}

8. Handling the Verification Response

You will receive a response like this after verification.

{
  purchaseTimeMillis: '1715878598633',
  purchaseState: 0,
  consumptionState: 1,
  developerPayload: '',
  orderId: 'GPA.3389-9282-7070-74559',
  purchaseType: 0,
  acknowledgementState: 1,
  kind: 'androidpublisher#productPurchase',
  regionCode: 'IN'
}

Upon receiving a successful response from Google Play:

a. Check for Duplicate Orders: Verify if the order ID already exists in your database.
If it does, respond with an error message: "This payment was already captured".
If not, proceed to save the transaction.

b. Update User Wallet: Retrieve the product's price using product id from your database, subtract the Play Store fee and any other applicable fees, and then increment the user's wallet balance accordingly.

c. Save Transaction Details: Store userId, purchaseTimeMillis, orderId , productId, amount, fees, etc. in your transactions table.

Conclusion

By following these steps, you can ensure secure and accurate verification of in-app purchases on your server. This process helps maintain the integrity of your financial transactions and ensures that users receive their purchased items or credits promptly.

Feel free to adapt this guide to fit your specific requirements and backend framework. Happy coding!

Read next

Customized Calendar in Flutter

Hey, have you ever wanted a date-picker in your app but not in a dialog box? And you tried all the dart packages out there but cannot change their UIs

Hitesh Verma May 28, 2023 · 9 min read

Flutter: Custom Cupertino Date Picker

Hitesh Verma in TECH
May 28, 2023 · 6 min read

Simplifying Google Play Console & Cloud Project Setup for In-App Purchases

Hitesh Verma in TECH
May 21, 2024 · 5 min read

Flutter | Highlight searched text in results

Hitesh Verma in TECH
May 12, 2023 · 4 min read