FCM双向消息故障:客户应用发送时提示NotRegistered错误求助
我之前也碰到过类似的FCM跨应用消息发送问题,结合你的情况,给你梳理几个实用的排查方向,应该能帮你定位问题:
先确认目标Token的有效性
NotRegistered错误最核心的原因就是目标Token已经失效,哪怕你之前确认过正确,也可能因为这些情况导致失效:客户端/管理员端App卸载重装、设备清除了App数据、FCM服务在设备上异常重启、甚至系统版本更新影响了FCM服务。
建议让对应端的App实时调用FCM的Token获取接口(比如Android上的FirebaseMessaging.getInstance().getToken()),拿到最新的Token替换掉当前使用的注册ID,再测试发送。另外一定要注意:客户端的Token是com.take.customer包名生成的,管理员端的是com.take.admin的,别搞混了。验证FCM密钥的类型和权限
你们共用的FCM密钥必须是服务器密钥,而不是客户端API密钥——客户端API密钥有发送限制,根本没法用来发起消息推送请求。你可以去Firebase控制台的「项目设置」→「云消息传递」里找到服务器密钥,确认用的是这个。
另外还要检查服务器密钥是否设置了IP白名单,如果有,那客户端回发消息的请求来源IP不在白名单里的话,也可能间接导致Token校验失败(虽然通常这个场景会返回Unauthorized,但也不排除特殊情况)。检查消息发送的请求配置
先确认你发送消息的目标是正确的:如果是客户端给管理员端发,那目标Token必须是管理员端App生成的有效Token;反过来同理。
同时要确保发送请求的格式完全正确:- 请求地址必须是
https://fcm.googleapis.com/fcm/send - 请求头必须包含
Authorization: key=你的服务器密钥和Content-Type: application/json - 请求体里的
to字段要准确填写目标Token,别出现拼写错误或者多余字符。
- 请求地址必须是
核对两个App的Firebase配置文件
虽然两个App都加入了同一Firebase项目,但要确认各自的配置文件是对应包名的:Android的google-services.json里的package_name必须分别匹配com.take.customer和com.take.admin;iOS的GoogleService-Info.plist里的BUNDLE_ID也要对应。如果配置文件搞混了,生成的Token其实不属于当前项目,自然会被判定为NotRegistered。借助日志定位细节
你可以去Firebase控制台的「云消息传递」→「报告」里查看消息发送的详细日志,里面会有更具体的错误上下文。另外在App里添加FCM的日志监听:比如Android上重写FirebaseMessagingService的onNewToken和onMessageReceived方法,打印Token生成和消息接收的日志,看看有没有异常情况。用简单请求做测试
你可以用Postman或者curl直接发起一个最简测试请求,排除App代码的干扰:curl -X POST "https://fcm.googleapis.com/fcm/send" \ -H "Authorization: key=你的服务器密钥" \ -H "Content-Type: application/json" \ -d '{ "to": "目标Token", "notification": { "title": "测试消息", "body": "这是一条FCM测试消息" } }'如果这个请求也返回NotRegistered,那问题肯定出在Token或者密钥上;如果请求成功,那说明你的客户端发送代码有问题,比如请求头拼接错误、请求体格式不对等。
内容的提问来源于stack exchange,提问作者SpeedRacer

