Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service account authentication for firebase function access Google APIs (for in-app purchase info) failing

We are preparing a firebase trigger to handle android's real-time developer notifications, and we have to use Google Play Developer API to understand the details for user subscriptions. Thus we linked firebase service account in Google Play Console and also granted necessary access.

We used google's nodejs library for googleapis (github link) and wrote a piece of code like this:

return google.auth.getClient({
  keyFile: path.join(__dirname, './service-account.json'),
  scope: 'https://www.googleapis.com/auth/androidpublisher'
}) .then((client) => {
  const androidpublisher = google.androidpublisher({
    version: 'v3',
    auth: client
  });
  const params = {
    packageName: ANDROID_PACKAGE_NAME,
    subscriptionId: ANDROID_SUBSCRIPTIONID,
    token: token
  };
  return androidpublisher.purchases.subscriptions.get(params)
  .then(res => {
    console.log(`The response is ${res.data}`);
    return null;
  })
  .catch(error => {
    console.error(error);
  });
});

But it returns us an error states: 'Invalid Credentials', which I am a bit lost for this. I have tested using curl that API with the authorization token and it shows 401 error response as well.

I am not sure whether my flow above is correct, can anyone provide me any suggestions?

like image 224
Yuyun Zhou Avatar asked Aug 23 '18 09:08

Yuyun Zhou


1 Answers

With JWT from google-auth-library. Google sample

const googleapis = require('googleapis');
const { JWT } = require('google-auth-library');
const serviceAccount = require('./serviceAccountKey.json');

const getAuthorizedClient = () => new JWT({
    email: serviceAccount.client_email,
    key: serviceAccount.private_key,
    scopes: ['https://www.googleapis.com/auth/androidpublisher']
});

const getAndroidpublisher = () => googleapis.google.androidpublisher({
    version: 'v3',
    auth: getAuthorizedClient()
});

const requestProductValidation = data => new Promise((resolve, reject) => {
    getAndroidpublisher().purchases["products"].get(data, (err, response) => {
        if (err) {
            console.log(`The API returned an error: ${err}`);
            resolve({status: "Error"});
        } else {
            const isValid = response && response.data && response.data.purchaseState === 0;
            resolve({status: isValid ? "OK" : "Error"});
        }
    });
});

exports.purchaseValidationAndroid = functions.https.onCall((data, context) => {
    return requestProductValidation(data);
});

data contains productId, token and packageName

like image 113
evgen shein Avatar answered Nov 02 '22 19:11

evgen shein