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

Node.js通过Firebase向iOS发推送通知遇INVALID_ARGUMENT错误求助

iOS设备FCM推送报错BadDeviceToken的排查与解决

问题场景

我尝试通过Firebase从Node.js向iOS设备发送推送通知,操作流程如下:

  1. iOS端调用await messaging().getAPNSToken();获取APNS Token
  2. 将Token发送到后端,通过以下函数转换为FCM Token:
export const convertAPNSToFCMToken = async token => {
  const fcmMessage = {
    application: 'com.xxxx.xxxx',
    sandbox: false,
    apns_tokens: [token]
  }

  const options = {
    headers: {
      Authorization: `Bearer ${accessToken}`,
      access_token_auth: true
    }
  }

  try {
    const { data } = await axios.post('https://iid.googleapis.com/iid/v1:batchImport', fcmMessage, options)
    return data.results[0].registration_token
  } catch (error) {
    winston.error('Unable to send message to Firebase')
    winston.error(error)
  }
}
  1. 使用转换后的FCM Token调用发送通知方法:
const sendFCMMessage = async ({ accessToken = '', fcmToken = '', title = '', body = '' }) => {
  try {
    const fcmMessage = JSON.stringify({
      message: {
        data: {},
        notification: {
          title: title,
          body: body
        },
        token: fcmToken
      }
    })

    const options = {
      hostname: 'fcm.googleapis.com',
      path: `/v1/projects/${process.env.GOOGLE_SERVICE_ACCOUNT_PROJECT_ID}/messages:send`,
      method: 'POST',
      headers: {
        Authorization: `Bearer ${accessToken}`
      }
    }

    const request = https.request(options, resp => {
      resp.setEncoding('utf8')
      resp.on('data', data => {
        winston.info('Message sent to Firebase for delivery, response:')
        winston.info(data)
      })
    })

    request.on('error', err => {
      winston.error('Unable to send message to Firebase')
      winston.error(err)
    })

    request.write(fcmMessage)
    request.end()
  } catch (e) {
    winston.error(e.message)
    return Promise.reject(e)
  }
}

但收到如下错误响应:

{
  "error": {
    "code": 400,
    "message": "Request contains an invalid argument.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
        "errorCode": "INVALID_ARGUMENT"
      },
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.ApnsError",
        "statusCode": 400,
        "reason": "BadDeviceToken"
      }
    ]
  }
}

备注:已在Firebase控制台配置好所有必要的认证信息。


排查与解决步骤

1. 核对APNS环境与Token匹配

BadDeviceToken最常见的原因是环境不匹配:

  • 如果你的iOS设备使用的是测试包(Xcode调试、AdHoc),convertAPNSToFCMToken函数中的sandbox参数必须设为true;生产包才用false。
  • 验证APNS Token格式:确保iOS端返回的是64位十六进制字符串,没有被截断或修改。

2. 检查FCM Token转换参数

  • 确认application字段的Bundle ID与Firebase控制台注册的iOS应用完全一致,大小写敏感。
  • 验证accessToken权限:转换Token所用的access token需包含firebase.messaging权限,建议使用Firebase服务账号生成的token,而非临时用户token。

3. 简化推送请求(推荐使用Firebase Admin SDK)

手动构造HTTP请求容易出现格式或权限问题,改用Firebase Admin SDK可自动处理Token转换和请求格式:

步骤1:安装依赖

npm install firebase-admin

步骤2:初始化Admin SDK

const admin = require('firebase-admin');
const serviceAccount = require('./path/to/your-service-account-key.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

步骤3:直接发送推送(无需手动转换Token)

const sendPushNotification = async (apnsToken, title, body) => {
  const message = {
    apns: {
      payload: {
        aps: {
          alert: {
            title: title,
            body: body,
          },
          sound: 'default'
        },
      },
      headers: {
        'apns-push-type': 'alert',
        'apns-expiration': '0',
        'apns-priority': '5',
      },
    },
    token: apnsToken,
  };

  try {
    const response = await admin.messaging().send(message);
    console.log('推送发送成功:', response);
    return response;
  } catch (error) {
    console.error('推送发送失败:', error);
    throw error;
  }
};

4. 设备端与证书校验

  • 确认iOS设备已开启应用的推送权限(设置→通知→对应应用)。
  • 检查Firebase控制台的APNs认证信息:证书/密钥是否对应正确环境(开发/生产),且未过期。

内容的提问来源于stack exchange,提问作者Pila

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 10:32:03