从 Firebase 函数调用 Google Play Developer API [英] Call Google Play Developer API from Firebase Functions

本文介绍了从 Firebase 函数调用 Google Play Developer API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对用户的应用内购买和订阅进行服务器端验证,如 推荐,我想为此使用 Firebase 函数.基本上,它必须是一个 HTTP 触发器函数,它接收购买令牌,调用 Play Developer API 来验证购买,然后对结果执行一些操作.

I am trying to develop a server-side validation of my users' in-app purchases and subscriptions as recommended, and I want to use Firebase Functions for that. Basically it has to be an HTTP trigger function that receives a purchase token, calls the Play Developer API to verify the purchase, and then does something with the result.

但是,调用许多 Google API(包括 Play DeveloperAPI) 需要非平凡的授权.以下是我对所需设置的理解:

However, calling many of the Google APIs (including Play Developer API) requires non-trivial authorization. Here's how I understand the required setup:

  1. 必须有一个启用了 Google Play Developer API v2 的 GCP 项目.
  2. 它应该是一个单独的项目,因为在 Google Play 管理中心中只能有一个链接到 Play 商店.
  3. 我的 Firebase Functions 项目必须以某种方式对该其他项目进行身份验证.我认为在这种服务器到服务器场景中使用服务帐户最合适.
  4. 最后,我的 Firebase 函数代码必须以某种方式获取身份验证令牌(希望是 JWT?),并最终进行 API 调用以获取订阅状态.

问题在于,绝对不存在人类可读的文档或指南.鉴于 Firebase 中的入口流量包含在免费计划中(因此我认为他们鼓励使用 Firebase Functions 的 Google API),这一事实非常令人失望.我设法在这里和那里找到了一些信息,但对 Google API 的经验太少(其中大部分只需要使用 api 密钥),我需要帮助将它们组合在一起.

The problem is that absolutely no human-readable documentation or guidance on that is existent. Given that ingress traffic in Firebase is included in the free plan (so I assume they encourage using Google APIs from Firebase Functions), that fact is pretty disappointing. I've managed to find some bits of info here and there, but having too little experience with Google APIs (most of which required simply using an api key), I need help with putting it together.

这是我目前发现的:

  1. 我有一个 GCP 项目链接到 Play 商店并启用了 API.但出于某种原因,尝试在 API 资源管理器中对其进行测试会导致错误用于调用 Google Play 开发者 API 的项目 ID 尚未在 Google Play 开发者控制台中链接".
  2. 我创建了一个服务帐户并导出了一个 JSON 密钥,其中包含生成 JWT 的密钥.
  3. 我还在 Play 管理中心中为该服务帐号设置了读取权限.
  4. 我找到了一个用于 Google API 的 Node.JS 客户端库,它是在 alpha 中,并且文档非常稀疏(例如,没有关于如何使用 JWT 进行身份验证的明显文档,也没有关于如何调用 android 发布者 API 的示例).目前我正在为此苦苦挣扎.不幸的是,我不太习惯阅读 JS 库代码,尤其是当编辑器不提供跳转到突出显示函数源的可能性时.
  1. I got a GCP project linked to the Play Store and with the API enabled. For some reason though, trying to test it in APIs Explorer results in an error "The project id used to call the Google Play Developer API has not been linked in the Google Play Developer Console".
  2. I made a Service Account and exported a JSON key, which contains the key to produce a JWT.
  3. I also set up read permissions for that Service Account in Play Console.
  4. I found a Node.JS client library for Google APIs, which is in alpha and has very sparse documentation (e.g. there's no obvious documentation on how to authenticate with JWT, and no samples on how to call the android publisher API). At the moment I'm struggling with that. Unfortunately I'm not super-comfortable with reading JS library code, especially when the editor doesn't provide the possibility to jump to highlighted functions' sources.

我很惊讶没有人询问或记录这一点,因为验证来自 Firebase Functions 的应用内购买似乎是一项常见任务.之前有没有人成功完成过,或者 Firebase 团队会介入回答?

I'm pretty surprised this hasn't been asked or documented, because verifying in-app purchases from Firebase Functions seems like a common task. Has anyone successfully done it before, or maybe the Firebase team will step in to answer?

推荐答案

我自己想出来的.我也抛弃了重量级的客户端库,只是手动编码了那几个请求.

I figured it out myself. I also ditched the heavyweight client library and just coded those few requests manually.

注意事项:

  • 这同样适用于任何 Node.js 服务器环境.您仍然需要单独的服务帐户的密钥文件来创建 JWT 和调用 API 的两个步骤,Firebase 也不例外.
  • 这同样适用于其他需要身份验证的 API - 不同之处仅在于 JWT 的 scope 字段.
  • 一些 API 不需要您交换用于访问令牌的 JWT - 您可以创建 JWT 并直接在 Authentication: Bearer 中提供它,而无需往返 OAuth 后端.
  • The same applies to any Node.js server environment. You still need the key file of a separate service account to mint a JWT and the two steps to call the API, and Firebase is no different.
  • The same applies to other APIs that require authentication as well — differing only in scope field of the JWT.
  • There are a few APIs that don't need you to exchange the JWT for an access token — you can mint a JWT and provide it directly in Authentication: Bearer, without a round trip to OAuth backend.

获得带有关联到 Play 商店的服务帐户的私钥的 JSON 文件后,调用 API 的代码是这样的(根据您的需要进行调整).注意:我使用 request-promise 作为执行 http.request 的更好方法.

After you've got the JSON file with the private key for a Service Account that's linked to Play Store, the code to call the API is like this (adjust to your needs). Note: I used request-promise as a nicer way to do http.request.

const functions = require('firebase-functions');
const jwt = require('jsonwebtoken');
const keyData = require('./key.json');         // Path to your JSON key file
const request = require('request-promise');

/** 
 * Exchanges the private key file for a temporary access token,
 * which is valid for 1 hour and can be reused for multiple requests
 */
function getAccessToken(keyData) {
  // Create a JSON Web Token for the Service Account linked to Play Store
  const token = jwt.sign(
    { scope: 'https://www.googleapis.com/auth/androidpublisher' },
    keyData.private_key,
    {
      algorithm: 'RS256',
      expiresIn: '1h',
      issuer: keyData.client_email,
      subject: keyData.client_email,
      audience: 'https://www.googleapis.com/oauth2/v4/token'
    }
  );

  // Make a request to Google APIs OAuth backend to exchange it for an access token
  // Returns a promise
  return request.post({
    uri: 'https://www.googleapis.com/oauth2/v4/token',
    form: {
      'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
      'assertion': token
    },
    transform: body => JSON.parse(body).access_token
  });
}

/**
 * Makes a GET request to given URL with the access token
 */
function makeApiRequest(url, accessToken) {
  return request.get({
    url: url,
    auth: {
      bearer: accessToken
    },
    transform: body => JSON.parse(body)
  });
}

// Our test function
exports.testApi = functions.https.onRequest((req, res) => {
  // TODO: process the request, extract parameters, authenticate the user etc

  // The API url to call - edit this
  const url = `https://www.googleapis.com/androidpublisher/v2/applications/${packageName}/purchases/subscriptions/${subscriptionId}/tokens/${token}`;

  getAccessToken(keyData)
    .then(token => {
      return makeApiRequest(url, token);
    })
    .then(response => {
      // TODO: process the response, e.g. validate the purchase, set access claims to the user etc.
      res.send(response);
      return;
    })
    .catch(err => {
      res.status(500).send(err);
    });
});

这些是我遵循的文档.

这篇关于从 Firebase 函数调用 Google Play Developer API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆