Flutter调用Cloud Function发送FCM通知时Token未定义问题求助
问题描述
在Flutter应用中,当用户添加单词时,需给关联伙伴发送新单词通知。Flutter端打印partnerFcmToken显示正常,但调用Cloud Function时始终返回“Token未定义”,Cloud Function日志提示“Partner FCM token is invalid or empty”,怀疑是请求参数传递方式有误,附上两端代码寻求解决。
Flutter端代码
String? partnerFcmToken = userSnap['partner_fcm_token'] as String?; if (partnerFcmToken != null && partnerFcmToken.isNotEmpty) { print("Envoie notif fait."); print(partnerFcmToken); // Call the cloud function to send the notification final response = await FirebaseFunctions.instance .httpsCallable('sendNotificationToPartnerPhoneV2') .call({ 'token_partner': partnerFcmToken, 'lang1': lang1, // Include lang1 in the request 'lang2': lang2, // Include lang2 in the request }); if (response.data['success']) { print("Notification sent successfully!"); } else { print("Failed to send notification: ${response.data['error']}"); } }
Cloud Function端原代码
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); // eslint-disable-next-line max-len exports.sendNotificationToPartnerPhoneV2 = functions.https.onCall(async (request) => { console.log("Starting sendNotificationToPartnerPhoneV2 function"); // Retrieve the FCM token from the request const partnerFcmToken = request.token_partner; // Validate the FCM token if (typeof partnerFcmToken !== "string" || partnerFcmToken.trim() === "") { console.error("Invalid partner FCM token:", partnerFcmToken); return {success: false, error: "Partner FCM token is invalid or empty."}; } // Prepare the notification message const message = { notification: { title: "Your partner added a new word!", // eslint-disable-next-line max-len body: `${request.lang1} / ${request.lang2}`, // Use template literals for message body }, token: partnerFcmToken, }; // Log the message to be sent console.log("Message to be sent:", JSON.stringify(message, null, 2)); try { // Send the notification await admin.messaging().send(message); console.log("Notification sent successfully."); return {success: true}; } catch (error) { console.error("Error sending notification:", error); return {success: false, error: error.message}; } });
解决方案
问题出在Cloud Function的参数处理逻辑:functions.https.onCall的函数签名与onRequest不同,它的第一个参数是客户端传递的数据对象,而非HTTP请求对象。原代码错误地将参数命名为request并直接取值,导致无法正确获取Flutter端传递的参数。
修正后的Cloud Function代码
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.sendNotificationToPartnerPhoneV2 = functions.https.onCall(async (data, context) => { console.log("Starting sendNotificationToPartnerPhoneV2 function"); // 从客户端传递的data对象中提取参数 const partnerFcmToken = data.token_partner; const lang1 = data.lang1; const lang2 = data.lang2; // 验证FCM Token有效性 if (typeof partnerFcmToken !== "string" || partnerFcmToken.trim() === "") { console.error("Invalid partner FCM token:", partnerFcmToken); return {success: false, error: "Partner FCM token is invalid or empty."}; } // 构建通知消息 const message = { notification: { title: "Your partner added a new word!", body: `${lang1} / ${lang2}`, }, token: partnerFcmToken, }; console.log("Message to be sent:", JSON.stringify(message, null, 2)); try { await admin.messaging().send(message); console.log("Notification sent successfully."); return {success: true}; } catch (error) { console.error("Error sending notification:", error); return {success: false, error: error.message}; } });
关键修正点
- 将函数参数从
(request)改为(data, context):data对应Flutter端call()方法传递的Map对象,context包含调用者的认证信息等上下文数据 - 从
data对象中获取token_partner、lang1、lang2参数,而非错误地从request中取值 - 单独提取语言参数,提升代码可读性
内容的提问来源于stack exchange,提问作者Martin Guillon
相关产品推荐
相关产品推荐

