FCM推送NotRegistered错误排查:HTTPS子域名环境测试异常
解决FCM重新启用通知权限后仍返回NotRegistered的问题
这是旧版本Firebase JS里很常见的场景,我来给你拆解问题根源和解决方案:
问题核心
当用户手动禁用通知权限时,Firebase会把当前的FCM令牌标记为无效(这就是你调用fcm/send返回NotRegistered的原因,符合预期)。但用户重新开启权限后,浏览器会生成全新的推送订阅对象,对应的FCM令牌也会跟着改变。如果你的应用没主动重新获取这个新令牌并同步到服务器,后续推送还是用旧令牌调用接口,自然会继续报错。
针对Firebase JS 4.10.1的解决方案
因为你用的是4.10.1这个旧版本,方法和新版略有差异,下面是具体实现步骤和代码:
1. 监听通知权限变化
通过浏览器的notificationpermissionchange事件实时监听权限状态,一旦权限从denied切换到granted,立刻触发令牌刷新逻辑。
2. 页面加载主动检查权限
用户重新开启权限后刷新页面,我们需要在页面加载完成后主动检查权限状态,如果是granted,就立即获取最新令牌。
3. 刷新并同步FCM令牌
先删除旧令牌(如果存在),再获取新令牌,最后把新令牌同步到服务器,替换掉旧的令牌记录。
完整代码示例
// 初始化Firebase配置(替换成你的实际配置) var firebaseConfig = { apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", databaseURL: "YOUR_DATABASE_URL", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE_BUCKET", messagingSenderId: "YOUR_MESSAGING_SENDER_ID" }; firebase.initializeApp(firebaseConfig); const messaging = firebase.messaging(); // HTTPS环境下必须设置VAPID公钥 messaging.usePublicVapidKey("YOUR_VAPID_PUBLIC_KEY"); // 监听权限变化事件 navigator.permissions.query({ name: 'notifications' }).then(permissionStatus => { permissionStatus.onchange = function() { console.log('通知权限状态更新为:', this.state); if (this.state === 'granted') { refreshFCMToken(); } }; }); // 页面加载时检查权限并刷新令牌 window.addEventListener('load', () => { if (Notification.permission === 'granted') { refreshFCMToken(); } }); // 刷新FCM令牌的核心函数 function refreshFCMToken() { // 4.10.1版本删除令牌需要传入旧令牌作为参数 messaging.getToken().then(oldToken => { if (oldToken) { console.log('删除旧令牌:', oldToken); return messaging.deleteToken(oldToken); } return Promise.resolve(); }).then(() => { // 获取新令牌 return messaging.getToken(); }).then(newToken => { if (newToken) { console.log('获取到新令牌:', newToken); // 将新令牌发送到你的服务器,更新用户对应的令牌记录 fetch('/api/update-fcm-token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token: newToken, userId: "当前用户唯一标识" // 替换成你的用户ID逻辑 }) }).then(res => { res.ok ? console.log('令牌更新成功') : console.error('令牌更新失败'); }); } }).catch(err => { console.error('处理FCM令牌时出错:', err); }); }
关键注意事项
- 服务器端同步:一定要确保服务器正确处理令牌更新,比如用用户ID关联令牌,每次收到新令牌就覆盖旧的,避免旧令牌残留。
- 旧版本兼容性:Firebase JS 4.10.1的
deleteToken方法必须传入旧令牌,和新版写法不同,别直接照搬新版代码。 - 测试验证:每次权限变化后,先检查服务器上的令牌是否为最新,再调用
fcm/send接口测试,确保推送正常。
内容的提问来源于stack exchange,提问作者balaphp
相关产品推荐
相关产品推荐

