基于Flutter的Firebase Cloud Messaging订阅到期精准推送问题咨询
实现用户独立订阅到期推送方案
基于你已经完成的FCM基础配置,以下是实现用户独立订阅到期提醒的具体方案:
一、用户订阅数据存储设计
首先需要建立用户订阅信息的存储,推荐使用Firebase Firestore(和FCM生态无缝整合),每个用户的订阅文档需包含以下核心字段:
user_id:关联Firebase Auth的用户唯一IDexpire_at:订阅到期时间(用Timestamp格式存储,方便时间查询)fcm_token:用户设备的FCM推送令牌reminder_sent:布尔值,标记是否已推送到期提醒(避免重复推送)
Flutter端同步订阅数据的示例代码:
// 假设用户已完成登录,获取当前用户ID final userId = FirebaseAuth.instance.currentUser?.uid; if (userId != null) { // 获取当前设备的FCM令牌 final fcmToken = await FirebaseMessaging.instance.getToken(); if (fcmToken != null) { // 写入/更新用户订阅信息 await FirebaseFirestore.instance.collection('user_subscriptions').doc(userId).set({ 'expire_at': Timestamp.fromDate(DateTime.now().add(const Duration(days: 30))), // 示例:30天订阅 'fcm_token': fcmToken, 'reminder_sent': false, }, SetOptions(merge: true)); } }
二、到期检测与推送触发逻辑
使用Firebase云函数(Cloud Functions)配合定时触发器,自动扫描并推送提醒,无需依赖客户端逻辑:
- 创建定时触发的云函数,比如每天运行一次(或根据需求调整频率,比如每10分钟)
- 在函数中查询符合条件的用户:订阅到期时间在当前时间范围内(比如接下来24小时内,或精准到期时间前后5分钟)、且未推送过提醒
- 生成FCM推送消息,批量推送给目标用户,同时更新
reminder_sent字段为true
云函数示例(Node.js):
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); // 每天运行一次,检查即将到期的订阅 exports.sendSubscriptionExpiryReminders = functions.pubsub.schedule('every 24 hours').timeZone('Asia/Shanghai').onRun(async (context) => { const now = new Date(); // 查询未来24小时内到期且未推送提醒的用户 const expiryThreshold = new Date(now.getTime() + 24 * 60 * 60 * 1000); const snapshot = await admin.firestore() .collection('user_subscriptions') .where('expire_at', '<=', expiryThreshold) .where('reminder_sent', '==', false) .get(); const pushMessages = []; const updatePromises = []; snapshot.forEach(doc => { const subscriptionData = doc.data(); // 构造FCM推送消息 pushMessages.push({ token: subscriptionData.fcm_token, notification: { title: '订阅到期提醒', body: 'Hello, your subscription is expired!', }, // 可选:添加自定义数据,方便客户端处理 data: { type: 'subscription_expiry', userId: doc.id } }); // 标记为已推送 updatePromises.push(doc.ref.update({ reminder_sent: true })); }); // 批量更新状态和推送消息 if (pushMessages.length > 0) { await Promise.all([ admin.messaging().sendAll(pushMessages), ...updatePromises ]); functions.logger.info(`成功推送${pushMessages.length}条订阅到期提醒`); } return null; });
三、确保精准推送的核心逻辑
要避免误推或重复推送,需严格执行以下几点:
- 唯一绑定:每个订阅文档与用户ID、FCM令牌一一对应,确保推送目标准确
- 状态标记:
reminder_sent字段必须在推送后立即更新,防止同一用户被多次推送 - 精准查询:通过Firestore的时间范围查询筛选目标用户,只针对符合条件的用户生成推送任务
- 令牌有效性:推送后若收到FCM返回的令牌失效错误,需从数据库中移除该令牌,避免后续无效推送
四、Flutter端的消息接收与处理
确保APP在前台、后台甚至杀死状态下都能收到推送:
- 配置本地通知插件(比如
flutter_local_notifications),处理前台消息展示 - 监听FCM令牌刷新事件,及时同步到数据库,避免令牌失效导致推送失败
示例代码:
// 监听前台FCM消息 FirebaseMessaging.onMessage.listen((RemoteMessage message) { final notification = message.notification; if (notification != null) { // 展示本地通知 flutterLocalNotificationsPlugin.show( notification.hashCode, notification.title, notification.body, const NotificationDetails( android: AndroidNotificationDetails( 'subscription_notification_channel', '订阅通知', channelDescription: '用于推送订阅到期提醒', importance: Importance.max, priority: Priority.high, ), ), ); } }); // 监听FCM令牌刷新,同步到数据库 FirebaseMessaging.instance.onTokenRefresh.listen((newToken) { final userId = FirebaseAuth.instance.currentUser?.uid; if (userId != null) { FirebaseFirestore.instance.collection('user_subscriptions').doc(userId).update({ 'fcm_token': newToken, }); } });
内容的提问来源于stack exchange,提问作者Cristiano Z
相关产品推荐
相关产品推荐

