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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:12:40