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

Flutter聊天App:如何用Node.js编写Firebase Functions实现指定设备FCM推送

从Firestore获取FCM Token并推送通知的Firebase Functions实现(Node.js)

一、基础准备

  • 确保本地已安装firebase-tools:npm install -g firebase-tools
  • 初始化Functions项目:执行firebase init functions,选择JavaScript作为开发语言(TypeScript版本可自行调整语法)
  • Functions目录下默认已集成firebase-admin,无需额外安装

二、完整代码示例

以下提供两种常见场景的实现代码,可根据你的聊天业务需求选择:

场景1:HTTP触发(用于快速测试推送功能)

通过HTTP请求指定目标用户手机号和通知内容,直接触发推送:

const functions = require("firebase-functions");
const admin = require("firebase-admin");

// 初始化Firebase Admin SDK
admin.initializeApp();

// HTTP触发的推送函数
exports.sendNotificationToUser = functions.https.onRequest(async (req, res) => {
  // 从请求参数中获取目标手机号、通知标题和内容
  const targetPhone = req.query.phone;
  const title = req.query.title || "新消息提醒";
  const body = req.query.body || "您收到一条新消息";

  if (!targetPhone) {
    return res.status(400).send("请传入目标用户手机号(phone参数)");
  }

  try {
    // 从Firestore读取目标用户的FCM Token
    const tokenDoc = await admin.firestore().collection("userToken").doc(targetPhone).get();
    
    if (!tokenDoc.exists) {
      return res.status(404).send("未找到该用户的FCM Token");
    }

    const fcmToken = tokenDoc.data().token;

    // 构造FCM通知结构
    const message = {
      token: fcmToken,
      notification: {
        title: title,
        body: body,
      },
      // 可选:添加自定义数据,Flutter端可解析这些字段做后续逻辑
      data: {
        type: "chat",
        source: "system"
      }
    };

    // 发送通知
    const result = await admin.messaging().send(message);
    res.status(200).send(`通知发送成功:${result}`);
  } catch (error) {
    functions.logger.error("推送失败", error);
    res.status(500).send(`推送失败:${error.message}`);
  }
});

场景2:Firestore触发(聊天消息新增时自动推送)

如果聊天消息存储在Firestore的messages集合,可监听新消息文档的创建事件,自动推送给接收方:

const functions = require("firebase-functions");
const admin = require("firebase-admin");

admin.initializeApp();

// 监听messages集合的新增文档,触发推送
exports.sendChatNotification = functions.firestore.document("messages/{messageId}").onCreate(async (snap, context) => {
  const messageData = snap.data();
  // 假设消息结构包含receiverPhone(接收方手机号)、senderName(发送方昵称)、content(消息内容)
  const receiverPhone = messageData.receiverPhone;
  const senderName = messageData.senderName;
  const content = messageData.content;

  if (!receiverPhone) {
    functions.logger.warn("消息未携带接收方手机号,跳过推送");
    return;
  }

  try {
    // 获取接收方的FCM Token
    const tokenDoc = await admin.firestore().collection("userToken").doc(receiverPhone).get();
    
    if (!tokenDoc.exists) {
      functions.logger.warn(`未找到用户${receiverPhone}的FCM Token`);
      return;
    }

    const fcmToken = tokenDoc.data().token;

    // 构造聊天专属通知
    const notificationMessage = {
      token: fcmToken,
      notification: {
        title: `${senderName}发来消息`,
        body: content.length > 20 ? `${content.substring(0,20)}...` : content,
      },
      data: {
        type: "chat",
        messageId: context.params.messageId,
        senderPhone: messageData.senderPhone
      },
      // 适配Android/iOS的通知点击行为
      android: {
        notification: {
          clickAction: "FLUTTER_NOTIFICATION_CLICK"
        }
      },
      apns: {
        payload: {
          aps: {
            "content-available": 1
          }
        }
      }
    };

    await admin.messaging().send(notificationMessage);
    functions.logger.info(`已向用户${receiverPhone}推送聊天通知`);
  } catch (error) {
    functions.logger.error(`推送失败:${error.message}`);
  }
});

三、部署与测试

  1. 部署函数:在Functions目录下执行firebase deploy --only functions
  2. 测试HTTP函数:部署完成后复制函数URL,在浏览器/Postman中访问,示例:
    https://<项目区域>-<项目ID>.cloudfunctions.net/sendNotificationToUser?phone=138xxxxxxx&title=测试通知&body=这是一条测试消息
  3. 测试Firestore触发函数:向messages集合添加符合结构的文档,通过firebase functions:log查看函数运行日志,同时检查设备是否收到通知

四、注意事项

  • 确保Firestore的userToken集合权限配置正确,Functions默认服务账号拥有读取权限
  • 处理Token失效:推送时若收到InvalidRegistration错误,建议删除该失效Token,等待Flutter端重新获取并更新
  • 批量推送需求:如需向多个用户推送,可使用admin.messaging().sendMulticast()替代send()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:15:49