带云功能的FCM中的注册令牌错误

时间:2018-12-04 06:48:19

标签: javascript firebase-cloud-messaging google-cloud-functions firebase-admin

我已将以下JavaScript部署到Firebase Cloud Function中,但是即使我知道在指定的路径下保存了令牌,我仍会不断出现以下错误。

这个想法是在将新消息写入数据库时​​触发向设备的通知,然后它获取注册令牌,然后将其用于尝试向用户发送通知。

enter image description here

  

错误:提供给sendToDevice()的注册令牌必须是非空字符串或非空数组。

JS函数:

exports.notifyNewMessage = functions.database.ref('/messages/{pushId}/{message}').onCreate((snap, context) => {
  const message = snap.val();
  const fromId = message['fromId'];
  const toId = message['toId'];
  const messageTxt = message ['message'];
  const imageUrl = message ['imageUrl'];


  return admin.database().ref('/fcmtokens/' + toId + '/registration-tokens').once('value').then((userTok) => {

    const registrationTokens = userTok.val()

    console.log(registrationTokens);

    return admin.database().ref('/users' + fromId).once('value').then((userDoc) => {

      const senderName = userDoc.firstName //get('firstName')

      const notificationBody = (imageUrl === "") ? "You received a new image message." : messageTxt

        //build media messages notification
        const payload = {
            notification: {
              title: senderName + " sent you a message",
              body: messageTxt
            },
            data: {
              SENDER_NAME: senderName,
              SENDER_ID: fromId

            }//end data
        }//end payload

        //send message
        return admin.messaging().sendToDevice(registrationTokens, payload).then( response => {
          const stillRegisteredTokens = registrationTokens

          response.results.forEach((result, index) => {
                    const error = result.error
                    if (error) {
                        const failedRegistrationToken = registrationTokens[index]
                        console.error('blah', failedRegistrationToken, error)
                        if (error.code === 'messaging/invalid-registration-token'
                            || error.code === 'messaging/registration-token-not-registered') {
                                const failedIndex = stillRegisteredTokens.indexOf(failedRegistrationToken)
                                if (failedIndex > -1) {
                                    stillRegisteredTokens.splice(failedIndex, 1)
                                }
                            }
                    }
                })//end forEach

                return admin.database().ref("fcmtokens/" + recipientId).update({
                    registrationTokens: stillRegisteredTokens
                })//end update

        })//end sendToDevice


    })//end return-then

  })//end return-then

});

这是我的fcmtokens数据库结构节点:

"fcmtokens" : {
    "dBQdpR7l1WT2utKVxdX2" : {
      "registration-tokens" : {
        "c4PSCAUAg5s:Yw95DyVxwElE88LwX7" : true
      }
    }
  }

问题更新: 我上面函数的更新数据库部分是为所有活动令牌创建一个名为registrationTokens的单独分支。我想改写并更新registration-tokens下的当前令牌?

return admin.database().ref("fcmtokens/" + recipientId).update({
                        registrationTokens: stillRegisteredTokens
                    })//end update

该图片显示了正在创建的新registrationTokens分支。

enter image description here

1 个答案:

答案 0 :(得分:0)

给出您的数据结构,此代码:

admin.database().ref('/fcmtokens/' + toId + '/registration-tokens').once('value').then((userTok) => {
  const registrationTokens = userTok.val()

registrationTokens的领先优势:

{
  "c4PSCAUAg5s:Yw95DyVxwElE88LwX7" : true
}

然后您通过以下方式致电sendToDevice

return admin.messaging().sendToDevice(registrationTokens, payload).then( response => {

但是,如果您查看reference documentation for `sendToDevice,它会显示:

  

注册令牌

     

字符串数组

     

向其发送消息的设备的注册令牌的数组。

很显然,您的registrationTokens不是数组,而只是对象。

要将其转换为数组,请使用Object.keys()

  const registrationTokens = Object.keys(userTok.val())