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

Firebase Cloud Functions推送通知报错:注册令牌无效问题排查

问题分析与修复方案

你的代码存在几个关键错误,直接导致了推送token无效的报错,下面逐一说明并给出修复方案:


1. 笔误:afterData 错误引用了 before 的数据

你把更新后的数据来源写成了change?.before?.data(),这会导致beforeData和afterData完全相同,后续的beforeData?.receiverId != afterData?.receiverId判断永远不成立;如果是文档新增场景,beforeData还会是null,彻底打乱逻辑。

修复:
从change.after获取更新后的数据:

const afterData = change?.after?.data();

2. 字符串模板使用错误

你用双引号"包裹了模板字符串,导致变量无法被解析,"users/${afterData?.receiverId}"会被当作字面量路径(即文档路径是users/${afterData?.receiverId},而非实际用户ID对应的路径),最终查询不到目标用户文档,token自然为undefined。

修复:
用反引号`包裹模板字符串,同样要修正推送通知的body字段:

// 用户文档路径
const docRef = admin.firestore().doc(`users/${afterData?.receiverId}`);
// 通知内容
body: `${afterData?.senderName} has sent you a message!`,

3. 缺失文档存在性检查与异步操作处理

即使你确认所有用户都有token,也需要先检查文档是否存在,避免因路径错误导致docSnap.data()返回null;同时sendToDevice是异步操作,必须用await等待完成,并添加错误捕获防止函数异常退出。

修复:
在获取用户文档后增加检查逻辑,并用try/catch处理推送操作:

if (!docSnap.exists) {
  console.log(`用户文档 ${afterData?.receiverId} 不存在`);
  return;
}

const userToken = docSnap.data()?.token;
if (!userToken) {
  console.log(`用户 ${afterData?.receiverId} 未设置推送token`);
  return;
}

try {
  await admin.messaging().sendToDevice(userToken, payload);
  console.log("推送通知发送成功");
} catch (error) {
  console.error("推送通知发送失败:", error);
}

修正后的完整代码

export const messageListener = functions.firestore
    .document("stingrayMessageListener/stingrayMessageListener")
    .onWrite(async (change) => {
      const beforeData = change?.before?.data();
      const afterData = change?.after?.data();
      
      // 确保更新后的数据存在
      if (!afterData) return;
      
      if (beforeData?.receiverId !== afterData?.receiverId) {
        const docRef = admin.firestore().doc(`users/${afterData.receiverId}`);
        const docSnap = await docRef.get();
        
        if (!docSnap.exists) {
          console.log(`用户文档 ${afterData.receiverId} 不存在`);
          return;
        }
        
        const userToken = docSnap.data()?.token;
        if (!userToken) {
          console.log(`用户 ${afterData.receiverId} 未设置推送token`);
          return;
        }

        const payload = {
          notification: {
            title: "New message!",
            body: `${afterData.senderName} has sent you a message!`,
          },
          data: {
            body: "message",
          },
        };

        try {
          await admin.messaging().sendToDevice(userToken, payload);
          console.log("推送通知发送成功");
        } catch (error) {
          console.error("推送通知发送失败:", error);
        }
      }
    });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 18:34:01