firebasegoogle-cloud-functionsin-app-purchase

Google Purchase API call succeeded on local but fail on Firebase Functions


I want to verify Google IAP receipts using Firebase Functions, but the code that works successfully in local testing is throwing errors when deployed to Functions.

Why is this happening when it's exactly the same code?

My code:

local code: test.ts (test is passed and log showed on console.)

import { beforeEach, describe, expect, it } from "@jest/globals";
import { logger } from "firebase-functions/v1";
import { GoogleAuth } from "google-auth-library";
import { google } from "googleapis";

describe("test group", () => {
  it("test", async () => {
    const mockAsyncFunc = async () => {
      const auth = new GoogleAuth({
        credentials: {
          client_email: "for-purchase-check@my_project.iam.gserviceaccount.com",
          private_key:
            "-----BEGIN PRIVATE KEY-----....-----END PRIVATE KEY-----\n",
          project_id: "my_project",
        },
        scopes: ["https://www.googleapis.com/auth/androidpublisher"],
      });

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

      const response = await androidPublisher.purchases.products.get({
        packageName: "com.my.domain",
        productId: "goods0",
        token:
          "....",
      });

      logger.info("result:", response.data);

      console.log("data: " + response.data);
      console.log("autoRenewing: " + response.data.orderId);
      console.log("kind: " + response.data.kind);
      console.log("status: " + response.statusText);

      return {
        success: true,
        data: "data",
      };
    };

    const result = await mockAsyncFunc();

    expect(result).toEqual({
      success: true,
      data: expect.any(String),
    });
  });
});

My code on Functions: index.ts

import { GoogleAuth } from "google-auth-library";
import { google } from "googleapis";
...

  const auth = new GoogleAuth({
    credentials: {
      client_email: "for-purchase-check@my_project.iam.gserviceaccount.com",
      private_key:
        "-----BEGIN PRIVATE KEY-----....-----END PRIVATE KEY-----\n",
      project_id: "my_project",
    },
    scopes: ["https://www.googleapis.com/auth/androidpublisher"],
  });

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

  const response = await androidPublisher.purchases.products.get({
    packageName: "com.my.domain",
    productId: "goods0",
    token:
      "...",
  });

...

I test on local by npm test, the result:

data: [object Object]
autoRenewing: GPA.0000-0000-0000-00000 // I replaced numbers to 0
kind: androidpublisher#productPurchase
status: OK

But I got error on Functions of Firebase:

Error: The purchase token is no longer valid.
    at Gaxios._request (/workspace/node_modules/gaxios/build/src/gaxios.js:142:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async JWT.requestAsync (/workspace/node_modules/google-auth-library/build/src/auth/oauth2client.js:429:18)
    at async /workspace/lib/index.js:89:22
    at async /workspace/lib/wrapper.js:27:24

Should I provide any else informations?

Any help would be greatly appreciated.


Solution

  • I make a mistake.

    My lib folder already existed a index.js file that path is: project_root/lib/index.js and the main in package.json is "lib/index.js", but my TypeScript file path is project_root/src/index.ts so I always deployed same/old file to my Firebase, Oh my God...

    So I changed "main": "lib/index.js" -> "main": "lib/src/index.js" to fix this issue.