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

Firebase触发式Cloud Function无法获取用户UID的问题求解

问题分析与解决方案

报错原因

Firestore 的 context.auth 仅在用户通过带身份验证的客户端 SDK 写入数据时才会携带用户信息。你的 subscriptions 文档是通过后端 Admin SDK 创建的,这种服务端写入场景下,触发器的 context.auth 为 undefined,因此读取 context.auth.uid 会抛出类型错误。


解决步骤

1. 在创建订阅文档时存储用户 ID

修改后端 POST 接口,确保写入 subscriptions 文档时,同时存储用户的 UID。需要确保支付系统回传的 decodedJson 中包含用户 ID(前端发起支付请求时,需将当前用户 UID 传递给支付系统,由支付系统带回)。

修改后的后端代码:

app.post("/subscription", (req, res) => {
  const {data, signature} = req.body;
  const decodedJson = JSON.parse(Buffer.from(data, "base64"));
  // 从支付回传数据中提取用户ID(字段名需和支付系统约定)
  const subscriberId = decodedJson.subscriberId; 

  return admin
      .firestore()
      .collection("subscriptions")
      .doc(decodedJson.order_id)
      .set({
        subscriptionDate: admin.firestore.FieldValue.serverTimestamp(),
        subscriberId: subscriberId, // 新增存储用户ID
        data: data, // 存储支付回传的原始数据,供触发器使用
        signature: signature // 存储签名,供触发器使用
      })
      .then(() => {
        return res.status(200).send("Subscription created");
      })
      .catch((error) => {
        throw new Error(error);
      });
});

2. 修改触发器从文档中获取用户 ID

触发器不再依赖 context.auth.uid,改为从新增的订阅文档快照中读取预存的 subscriberId,同时补充缺失的参数来源并完善批量操作逻辑。

修改后的触发器代码:

exports.checkPaymentStatus = functions.firestore
    .document("subscriptions/{subscriptionId}")
    .onCreate(async (snap, context) => {
      const subscriptionData = snap.data();
      // 从文档中获取所需参数
      const dataParam = subscriptionData.data;
      const signature = subscriptionData.signature;
      const subscriberId = subscriptionData.subscriberId;

      try {
        const response = await axios.post("https://paymentsystem.com/api/1/get-status", {
          data: dataParam,
          signature: signature,
        });

        if (response.data.status === "success") {
          const batch = admin.firestore().batch();

          // 标记订阅支付成功(可选)
          batch.update(snap.ref, { paymentStatus: "success" });

          // 更新用户的Pro状态
          batch.update(admin.firestore().collection("users").doc(subscriberId), {
            isPro: true,
            subscribedDate: admin.firestore.FieldValue.serverTimestamp(),
          });

          // 提交批量更新操作
          await batch.commit();
        } else {
          // 标记支付失败状态(可选)
          await snap.ref.update({ paymentStatus: "failed" });
        }
      } catch (error) {
        console.error("Error occurred:", error);
        // 标记错误状态(可选)
        await snap.ref.update({ 
          paymentStatus: "error", 
          errorMessage: error.message 
        });
      }
    });

额外注意事项

  • 需和支付系统约定回传数据格式,确保包含用户 UID 字段。
  • 使用 async/await 替代嵌套 then/catch,提升代码可读性和可维护性。
  • 批量操作必须调用 batch.commit() 才能生效,原代码遗漏了此步骤。
  • 新增的 paymentStatus 字段可用于后续排查支付状态问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 06:11:17