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}`); } });
三、部署与测试
- 部署函数:在Functions目录下执行
firebase deploy --only functions - 测试HTTP函数:部署完成后复制函数URL,在浏览器/Postman中访问,示例:
https://<项目区域>-<项目ID>.cloudfunctions.net/sendNotificationToUser?phone=138xxxxxxx&title=测试通知&body=这是一条测试消息 - 测试Firestore触发函数:向
messages集合添加符合结构的文档,通过firebase functions:log查看函数运行日志,同时检查设备是否收到通知
四、注意事项
- 确保Firestore的
userToken集合权限配置正确,Functions默认服务账号拥有读取权限 - 处理Token失效:推送时若收到
InvalidRegistration错误,建议删除该失效Token,等待Flutter端重新获取并更新 - 批量推送需求:如需向多个用户推送,可使用
admin.messaging().sendMulticast()替代send()
内容的提问来源于stack exchange,提问作者alsayed abdelbaqey
相关产品推荐
相关产品推荐

