You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

借助Firebase Function校验Google Play订阅:跨谷歌服务认证咨询

我来帮你梳理下在Firebase Functions里对接谷歌服务(这里默认是指Google Play订阅验证相关服务)做用户订阅状态判断的认证流程,都是实际项目里验证过的实用步骤:

核心认证思路:服务账号实现服务器到服务器的无交互认证

因为Firebase Functions是后端环境,没法走用户端OAuth授权那一套,最安全可靠的方式是用谷歌服务账号完成两个服务间的身份校验。

1. 创建并配置谷歌服务账号

  • 打开谷歌云控制台,找到你绑定Firebase的项目,进入「IAM与管理员」→「服务账号」页面
  • 新建一个服务账号,给它分配精准的权限:如果是验证Google Play订阅,就给它添加「Google Play Developer API Client」权限,或者更细粒度的「查看应用订阅数据」权限,遵循权限最小化原则
  • 下载该服务账号的JSON密钥文件,记住:这个文件绝对不能上传到代码仓库、公开存储或者客户端代码里,属于敏感信息

2. 在Firebase Functions中配置密钥

有两种安全的配置方式,推荐第二种:

  • 方式一:用Firebase环境变量存储
    在本地终端运行命令:
    firebase functions:config:set google.service_account="$(cat path/to/your/service-account-key.json)"
    
    部署后,函数里可以通过functions.config().google.service_account获取密钥内容
  • 方式二:关联GCP服务账号(更安全)
    如果你的Firebase Functions部署在GCP上,直接在GCP控制台给目标函数关联刚才创建的服务账号,不用手动管理密钥文件,GCP会自动处理认证

3. 在Functions代码中实现认证+订阅验证逻辑

以验证Google Play订阅为例,先安装依赖:

npm install googleapis

然后写云函数代码:

const functions = require("firebase-functions");
const { google } = require("googleapis");

// 初始化谷歌认证客户端
async function getAuthClient() {
  const serviceAccount = JSON.parse(functions.config().google.service_account);
  // 订阅验证需要的权限 scope
  return google.auth.fromJSON(serviceAccount).createScoped([
    "https://www.googleapis.com/auth/androidpublisher"
  ]);
}

// 供客户端调用的订阅验证函数
exports.checkUserSubscription = functions.https.onCall(async (data, context) => {
  // 第一步:先验证请求来自已登录的Firebase用户
  if (!context.auth) {
    throw new functions.https.HttpsError("unauthenticated", "请先登录账号");
  }

  const { packageName, subscriptionId, purchaseToken } = data;
  if (!packageName || !subscriptionId || !purchaseToken) {
    throw new functions.https.HttpsError("invalid-argument", "缺少必要参数");
  }

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

    // 调用Google Play API查询订阅状态
    const response = await androidPublisher.purchases.subscriptions.get({
      packageName,
      subscriptionId,
      token: purchaseToken
    });

    // 判断订阅是否有效:过期时间晚于当前时间即为活跃状态
    const isActive = response.data.expiryTimeMillis > Date.now();
    return { isActive, subscriptionDetails: response.data };
  } catch (error) {
    functions.logger.error("订阅验证失败", error);
    throw new functions.https.HttpsError("internal", "订阅验证出错,请稍后重试");
  }
});

4. 几个关键注意事项

  • 用户身份绑定:一定要验证客户端传入的purchaseToken属于当前context.auth.uid对应的用户,防止恶意用户用他人的token查询订阅状态
  • 配额优化:Google Play API有调用配额限制,对于频繁查询的订阅,可以缓存验证结果(比如存到Firebase Firestore),减少API调用次数
  • 错误处理:要捕获API返回的各种错误(比如token无效、权限不足、API配额耗尽等),给客户端返回清晰的错误提示

内容的提问来源于stack exchange,提问作者Alguru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:42:42