FCM HTTP v1 API偶发403错误(SenderId mismatch)排查求助
排查FCM HTTP v1 API偶尔出现403(SenderId mismatch)问题的建议
已迁移至FCM HTTP v1 API,大部分消息发送正常,但每日少量消息返回403错误,错误信息明确为SenderId mismatch,配置、服务状态、认证令牌均正常,发送代码如下:
try (CloseableHttpClient client = HttpClientBuilder.create().build()) { String urlFinal = FCM_URL.replace("nomeprojeto", Projetos.getProjetoId(keyStore)); HttpPost post = new HttpPost(urlFinal); // Set headers post.setHeader("Content-type", "application/json"); post.setHeader("Authorization", "Bearer " + getAccessToken(keyStore)); // Json generation Root mensagem = new Root(); mensagem.message.notification = msg.notification; mensagem.message.token = msg.token; mensagem.message.data = msg.data; String json = new ObjectMapper().writeValueAsString(mensagem); //System.out.println(json); post.setEntity(new StringEntity(json, "UTF-8")); // Call http HttpResponse response = client.execute(post); int statusCode = response.getStatusLine().getStatusCode(); // Validate response. if (statusCode == 200) { pushBean.log(msg, keyStore); System.out.println("push processado - " + new Date()); return; } if (statusCode == 404) { // documentação indica para não retentar no 400 e 404 String error = statusCode + " - Token FCM não encontrado: " + msg.token; pushBean.logErro(msg, keyStore, error + msg.token); return; } if (statusCode == 403) { // documentação indica para não retentar no 403 String error = "403 - Token FCM não aceito: " + msg.token; pushBean.logErro(msg, keyStore, error + msg.token); return; } if (statusCode != 200) { String error = "Erro ao efetuar envio do FCM, código do retorno = %d"; error = String.format(error, statusCode); FCMException ex = new FCMException(error); throw ex; } }
返回的403错误JSON:
{ "error": { "code": 403, "message": "SenderId mismatch", "status": "PERMISSION_DENIED", "details": [ { "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError", "errorCode": "SENDER_ID_MISMATCH" } ] } }
排查建议
- 核对令牌所属SenderId:出错的令牌大概率是从其他Firebase项目注册生成的,和当前发送请求用的项目SenderId不匹配。可以解析令牌提取SenderId信息验证,或者检查客户端注册时用的是当前项目的配置文件(google-services.json/GoogleService-Info.plist)。
- 清理跨项目无效令牌:维护令牌存储时,定期清理来自其他项目的令牌;或者客户端注册成功后,把令牌和对应项目标识绑定,发送时确保用对应项目的认证信息发送。
- 检查多项目发送逻辑:如果服务需要给多个Firebase项目发消息,确认
Projetos.getProjetoId(keyStore)和getAccessToken(keyStore)是否和当前令牌所属项目匹配,别搞混项目标识和认证令牌。 - 同步令牌生命周期:用户切换应用环境(比如从测试项目切到生产项目)后,旧令牌没更新也会导致不匹配。客户端要监听令牌刷新事件,及时把最新令牌同步到服务端。
- 细化错误日志:出现403时,额外记录当前用的项目ID(
Projetos.getProjetoId的返回值),对比令牌对应的SenderId,确认是否真的不匹配,方便定位问题。
内容的提问来源于stack exchange,提问作者Fernando Franzini
相关产品推荐
相关产品推荐

