FCM返回成功但未收到通知,客户端权限请求与Token上传问题
这种FCM返回成功但收不到通知的坑我踩过好多次,咱们一步步拆解排查:
1. 先查服务器发送的FCM Payload格式
FCM分两种核心消息类型:通知消息(系统自动帮你弹出通知)和数据消息(必须客户端自己写代码处理展示)。如果你的服务器只传了data字段,浏览器是不会自动弹出通知的!
正确的通知类Payload应该包含notification字段,示例如下:
{ "to": "客户端获取的Token", "notification": { "title": "测试推送标题", "body": "这是一条FCM测试通知" }, "data": { // 这里放你的自定义业务数据(可选) } }
如果服务器只发送data类型消息,你必须在客户端手动编写通知展示逻辑,系统不会帮你做这件事。
2. 客户端缺少消息监听逻辑
你的代码只处理了权限申请和Token获取,但完全没写监听FCM消息的代码啊!得补上这两块:
前台消息监听(页面处于打开状态时)
当页面在前台时,需要用onMessage监听消息并手动创建通知:
messaging.onMessage((payload) => { console.log('收到前台FCM消息:', payload); // 手动触发浏览器通知 const notificationTitle = payload.notification?.title || '新通知'; const notificationOptions = { body: payload.notification?.body || '您有一条新消息', icon: '/path-to-your-icon.png' // 替换成你的通知图标路径 }; new Notification(notificationTitle, notificationOptions); });
后台消息监听(页面在后台/关闭时)
这种情况需要依赖Service Worker,你得在项目根目录创建firebase-messaging-sw.js文件,配置如下:
// firebase-messaging-sw.js importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js'); importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js'); // 初始化Firebase,替换成你的项目配置 firebase.initializeApp({ apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE_BUCKET", messagingSenderId: "YOUR_MESSAGING_SENDER_ID", appId: "YOUR_APP_ID" }); const messaging = firebase.messaging(); // 监听后台消息 messaging.setBackgroundMessageHandler(function(payload) { console.log('[Service Worker] 收到后台FCM消息:', payload); const notificationTitle = payload.notification.title; const notificationOptions = { body: payload.notification.body, icon: '/path-to-your-icon.png' }; return self.registration.showNotification(notificationTitle, notificationOptions); });
别忘了在主代码里注册Service Worker,不然后台消息根本收不到!
3. 验证客户端通知权限和设备设置
虽然你调用了messaging.requestPermission(),但还是要确认:
- 浏览器设置中,当前网站的通知权限确实是允许状态(可以在浏览器的「设置→隐私和安全→网站设置→通知」里检查)
- 设备没有开启免打扰模式,浏览器没有被系统限制后台运行权限(比如Chrome的「网站可以在后台运行」要打开)
4. 检查Token的有效性和更新机制
Token可能会因为浏览器清除缓存、用户重装应用等情况失效,你得监听Token刷新事件,及时同步给服务器:
messaging.onTokenRefresh(() => { messaging.getToken().then((refreshedToken) => { console.log('FCM Token已刷新:', refreshedToken); // 发送新Token到服务器更新 fetch('/api/update-token', { method: 'post', body: JSON.stringify({ token: refreshedToken }), headers: { 'Content-Type': 'application/json' } }); }).catch((err) => { console.log('获取刷新Token失败:', err); }); });
5. 确认FCM发送的环境配置
如果你的项目区分了测试环境和生产环境,要确保服务器发送消息时用的是对应环境的Firebase配置文件(比如service-account.json),别把测试环境的Token发到生产环境,或者反过来。
内容的提问来源于stack exchange,提问作者Gopid
相关产品推荐
相关产品推荐

