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

如何仅按日和月触发Firebase云函数发送生日通知?

解决Firebase Cloud Function生日当天发送通知的问题

你的核心问题是原代码匹配的是完整年月日,但生日只需要匹配日和月,另外原函数是HTTP触发需要手动调用,我们应该改成定时触发(每天自动运行一次)。下面分两种方案解决:

方案一:预存日月字段(推荐,查询效率更高)

在用户文档中新增一个字段,比如birthDayMonth,格式为DDMM(比如10月5日就是0510)。这样每次查询时直接匹配当前日期的DDMM即可,避免全表扫描,适合用户量较大的场景。

代码实现

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const moment = require('moment');

admin.initializeApp();

// 每天凌晨0点触发(时区可根据需求调整,比如Asia/Shanghai)
exports.sendBirthdayNotifications = functions.pubsub.schedule('0 0 * * *')
  .timeZone('Asia/Shanghai')
  .onRun(async (context) => {
    try {
      // 获取当前日期的DDMM格式
      const todayDDMM = moment().format('DDMM');

      // 查询birthDayMonth匹配今天的用户
      const querySnapshot = await admin.firestore()
        .collection('userCollection')
        .where('birthDayMonth', '==', todayDDMM)
        .get();

      if (querySnapshot.empty) {
        console.log('今天没有过生日的用户');
        return null;
      }

      // 批量发送通知
      const notificationPromises = [];
      querySnapshot.forEach(doc => {
        const tokenId = doc.data().tokenId;
        if (!tokenId) return; // 跳过没有设备Token的用户

        const notificationContent = {
          notification: {
            title: '生日快乐!',
            body: '祝你今天开开心心,事事顺遂🥳',
            icon: 'default',
            sound: 'default'
          }
        };

        notificationPromises.push(
          admin.messaging().sendToDevice(tokenId, notificationContent)
            .catch(err => console.error(`发送通知失败给用户${doc.id}:`, err))
        );
      });

      await Promise.all(notificationPromises);
      console.log(`成功发送${notificationPromises.length}条生日通知`);
      return null;
    } catch (error) {
      console.error('函数执行出错:', error);
      return null;
    }
  });

方案二:实时过滤日月(适合小数据量)

如果不想修改用户文档结构,可以查询所有用户,然后在代码中过滤出日和月与今天匹配的用户。注意:如果用户量很大,这种方法会有性能问题,因为需要全表读取。

代码实现

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const moment = require('moment');

admin.initializeApp();

exports.sendBirthdayNotifications = functions.pubsub.schedule('0 0 * * *')
  .timeZone('Asia/Shanghai')
  .onRun(async (context) => {
    try {
      const today = moment();
      const todayDay = today.date();
      const todayMonth = today.month() + 1; // moment的month是0-11,所以加1转为实际月份

      // 获取所有用户
      const querySnapshot = await admin.firestore()
        .collection('userCollection')
        .get();

      if (querySnapshot.empty) {
        console.log('没有用户数据');
        return null;
      }

      const notificationPromises = [];
      querySnapshot.forEach(doc => {
        const userData = doc.data();
        const birthDate = userData.birthDate;
        const tokenId = userData.tokenId;

        if (!birthDate || !tokenId) return;

        // 将Firestore Timestamp转换为moment对象
        const birthMoment = moment(birthDate.toDate());
        const birthDay = birthMoment.date();
        const birthMonth = birthMoment.month() + 1;

        // 匹配日和月
        if (birthDay === todayDay && birthMonth === todayMonth) {
          const notificationContent = {
            notification: {
              title: '生日快乐!',
              body: '祝你今天开开心心,事事顺遂🥳',
              icon: 'default',
              sound: 'default'
            }
          };

          notificationPromises.push(
            admin.messaging().sendToDevice(tokenId, notificationContent)
              .catch(err => console.error(`发送通知失败给用户${doc.id}:`, err))
          );
        }
      });

      await Promise.all(notificationPromises);
      console.log(`成功发送${notificationPromises.length}条生日通知`);
      return null;
    } catch (error) {
      console.error('函数执行出错:', error);
      return null;
    }
  });

关键注意事项

  • 时区设置:一定要设置正确的时区(比如Asia/Shanghai),否则定时触发的时间会和预期不符。
  • 设备Token有效性:发送通知前要检查tokenId是否存在,并且可以通过sendToDevice返回的结果定期清理无效Token。
  • 依赖安装:确保在函数目录下安装所需依赖:
    npm install moment firebase-admin firebase-functions
    
  • 部署函数:使用Firebase CLI部署:
    firebase deploy --only functions:sendBirthdayNotifications
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:17:47