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

基于Node.js的Flutter多商家应用FCM通知功能实现咨询

实现Flutter+Node.js多商家应用的管理员消息推送通知方案

一、核心选型:Firebase Cloud Messaging(FCM)

FCM是跨平台推送的首选方案,支持Flutter前端和Node.js后端快速集成,无需自建推送服务器,自带离线缓存、设备Token管理等功能,完全适配你的需求场景。

二、Node.js后端实现

1. 集成FCM Admin SDK

首先安装依赖包:

npm install firebase-admin

用Firebase控制台生成的服务账号密钥初始化SDK(建议放在项目配置目录,不要提交到版本控制):

const admin = require('firebase-admin');
const serviceAccount = require('./path/to/service-account-key.json');

// 全局初始化,项目启动时执行一次
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});

2. 存储用户FCM Token

Flutter端用户登录后,会将设备的FCM Token上传到后端,你需要在用户表中新增fcm_token字段,同时保留premium_status字段(标记是否为付费用户)用于后续校验。

3. 发送消息时触发推送

在管理员发送聊天消息的接口中,添加推送逻辑:

  • 校验当前操作者是super_admin(通过登录态验证,比如JWT token解析)
  • 查询接收用户的Premium状态和FCM Token
  • 调用FCM API发送通知,携带聊天会话ID用于前端跳转

示例代码:

const UserModel = require('./models/User');
const ChatMessageModel = require('./models/ChatMessage');

// 封装推送函数
async function sendAdminChatNotification(userId, messageContent, chatId) {
  // 校验用户是否为活跃Premium用户
  const user = await UserModel.findById(userId);
  if (!user || user.premium_status !== 'active') return;

  const fcmMessage = {
    notification: {
      title: '管理员消息',
      body: messageContent
    },
    token: user.fcm_token,
    data: {
      type: 'admin_chat',
      chat_id: chatId // 用于前端跳转至对应聊天页面
    }
  };

  try {
    await admin.messaging().send(fcmMessage);
    console.log(`通知已发送至用户 ${userId}`);
  } catch (err) {
    console.error(`推送失败:${err.message}`);
    // 可选:记录失败日志,后续重试或清理无效Token
    if (err.code === 'messaging/invalid-registration-token') {
      await UserModel.findByIdAndUpdate(userId, { fcm_token: null });
    }
  }
}

// 管理员发送消息接口
app.post('/api/admin/send-chat', async (req, res) => {
  const { receiver_id, content } = req.body;
  const adminId = req.user.id; // 从JWT解析获取当前管理员ID

  // 1. 保存聊天消息到数据库
  const chatMessage = await ChatMessageModel.create({
    sender: adminId,
    receiver: receiver_id,
    content,
    type: 'admin_message'
  });

  // 2. 触发推送通知
  await sendAdminChatNotification(receiver_id, content, chatMessage._id.toString());

  res.status(200).json({ success: true, message: '消息发送成功' });
});

4. 处理无效Token

FCM会返回messaging/invalid-registration-token错误,此时需要将用户表中对应的Token置空,避免后续重复推送失败。

三、Flutter前端实现

1. 集成FCM与本地通知插件

添加依赖到pubspec.yaml:

dependencies:
  firebase_messaging: ^14.6.1
  flutter_local_notifications: ^16.1.0
  http: ^1.1.0

配置Android和iOS的FCM凭证(GoogleService-Info.plist、google-services.json),按官方配置流程完成基础设置即可。

2. 获取并上传FCM Token

用户登录成功后,获取设备Token并上传到后端:

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:http/http.dart' as http;

Future<void> uploadFcmToken(String userId) async {
  String? token = await FirebaseMessaging.instance.getToken();
  if (token == null) return;

  final response = await http.post(
    Uri.parse('https://your-api-domain.com/api/user/update-fcm-token'),
    body: {'user_id': userId, 'fcm_token': token},
  );

  if (response.statusCode != 200) {
    // 处理上传失败,比如重试逻辑
    print('FCM Token上传失败');
  }
}

3. 处理通知接收与跳转

初始化通知监听,处理前台、后台及杀死状态下的通知:

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter/material.dart';
import 'dart:convert';

final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();

void initNotificationListeners(BuildContext context) async {
  // 初始化本地通知配置
  const AndroidInitializationSettings androidInit = AndroidInitializationSettings('@mipmap/ic_launcher');
  const IOSInitializationSettings iosInit = IOSInitializationSettings();
  const InitializationSettings initSettings = InitializationSettings(android: androidInit, iOS: iosInit);
  
  await _notificationsPlugin.initialize(
    initSettings,
    onSelectNotification: (String? payload) async {
      // 点击通知跳转聊天页面
      if (payload != null) {
        final data = jsonDecode(payload);
        if (data['type'] == 'admin_chat') {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (_) => ChatScreen(chatId: data['chat_id'])),
          );
        }
      }
    },
  );

  // 前台接收通知
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    final notification = message.notification;
    final android = message.notification?.android;

    if (notification != null && android != null) {
      _notificationsPlugin.show(
        notification.hashCode,
        notification.title,
        notification.body,
        NotificationDetails(
          android: AndroidNotificationDetails(
            'admin_chat_channel',
            '管理员消息频道',
            importance: Importance.max,
            priority: Priority.high,
            icon: android.smallIcon,
          ),
        ),
        payload: jsonEncode(message.data),
      );
    }
  });

  // 后台点击通知
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    final data = message.data;
    if (data['type'] == 'admin_chat') {
      Navigator.push(
        context,
        MaterialPageRoute(builder: (_) => ChatScreen(chatId: data['chat_id'])),
      );
    }
  });

  // 杀死状态下点击通知(需配置Firebase后台消息处理)
  RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();
  if (initialMessage != null) {
    final data = initialMessage.data;
    if (data['type'] == 'admin_chat') {
      Navigator.push(
        context,
        MaterialPageRoute(builder: (_) => ChatScreen(chatId: data['chat_id'])),
      );
    }
  }
}

4. 申请通知权限

在App启动时申请iOS和Android 13+的通知权限:

Future<void> requestNotificationPermission() async {
  NotificationSettings settings = await FirebaseMessaging.instance.requestPermission(
    alert: true,
    badge: true,
    sound: true,
  );

  if (settings.authorizationStatus != AuthorizationStatus.authorized) {
    // 提示用户开启通知权限
    print('用户未授权通知权限');
  }
}

四、权限校验强化

  • 后端接口必须校验super_admin身份:通过JWT token解析角色字段,非管理员直接拒绝请求。
  • 推送前严格校验用户Premium状态:仅给premium_status为active的用户发送通知。
  • Flutter端进入聊天页面时二次校验:如果用户Premium已过期,跳转至付费订阅页面。

五、优化建议

  • 批量推送:若需给多个Premium用户发消息,使用FCM的sendMulticast接口,减少请求开销。
  • 推送记录:在数据库中新增notification_logs表,记录推送状态、用户ID、消息内容,方便管理员追溯。
  • 自定义通知频道:针对不同类型的通知(如系统公告、管理员消息)创建不同的Android通知频道,用户可自主设置通知优先级。
  • 离线消息同步:用户上线后,前端主动拉取未读的管理员消息,补充推送可能遗漏的内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:14:51