如何规范编写函数?请求修正Firebase云函数FCM令牌获取代码
解决FCM发送时"Registration token(s) provided to sendToDevice() must be a non-empty string..."错误
你的代码存在语法和逻辑层面的多处错误,直接导致FCM令牌获取失败,以下是修正后的完整代码:
const functions = require("firebase-functions"); const admin = require('firebase-admin'); admin.initializeApp(); // 现代Firebase版本无需手动传入config,SDK会自动完成初始化 exports.orderCompleteTrigger = functions.firestore.document('Orders/{orderId}').onWrite(async (change, context) => { // 订单删除时直接终止函数,避免无效触发 if (!change.after.exists) return null; const orderId = context.params.orderId; const orderData = change.after.data(); // 从当前订单文档中直接提取fcmToken(假设令牌存储在订单文档的fcmToken字段中) const fcmToken = orderData.fcmToken; // 提前校验令牌有效性 if (!fcmToken || typeof fcmToken !== 'string' || fcmToken.trim() === '') { console.log('无效或空的FCM令牌:', fcmToken); return null; } // 构造纯静态的FCM通知payload const payload = { notification: { title: "订单已完成", body: "感谢您的惠顾,期待再次为您服务!" } }; try { // 发送FCM通知 const response = await admin.messaging().sendToDevice(fcmToken, payload); console.log('通知发送成功:', response); // 可选:处理发送失败的无效令牌 const invalidTokens = []; response.results.forEach((result) => { const error = result.error; if (error) { console.error('令牌发送失败:', fcmToken, error); // 标记无效令牌,后续可从数据库移除 if (error.code === 'messaging/invalid-registration-token' || error.code === 'messaging/registration-token-not-registered') { invalidTokens.push(fcmToken); } } }); // 批量移除数据库中的无效令牌 if (invalidTokens.length > 0) { await change.after.ref.update({ fcmToken: admin.firestore.FieldValue.delete() }); } return null; } catch (error) { console.error('发送通知时发生异常:', error); return null; } });
关键修正点说明:
- 移除错误嵌套逻辑:你之前将Firestore异步查询直接写在
payload.notification对象中,这是严重的语法错误——payload必须是纯静态的通知内容,异步操作需独立于payload存在。 - 高效获取令牌:无需重新查询订单文档,直接通过
change.after.data()获取当前订单的最新数据,既避免路径错误,又提升执行效率。 - 前置令牌校验:在发送通知前先检查令牌是否为非空字符串,从根源避免FCM的空令牌报错。
- 简化异步流程:使用
async/await替代嵌套的then/catch,代码可读性更强,同时确保异步操作能完整执行。 - 规范Admin初始化:现代Firebase版本中,
admin.initializeApp()无需传入额外参数,SDK会自动读取环境配置完成初始化。 - 完善错误处理:捕获发送通知时的异常,并添加无效令牌的处理逻辑,提升代码健壮性。
额外注意事项:
- 确认
Orders集合中的文档确实包含fcmToken字段,且字段值为有效的FCM设备令牌字符串。 - 云函数必须返回Promise或具体值,否则可能导致函数提前终止,异步操作无法完成。
- 若需向多个设备发送通知,只需将
fcmToken替换为令牌数组即可,sendToDevice支持传入数组参数。
内容的提问来源于stack exchange,提问作者Nafees
相关产品推荐
相关产品推荐

