从FCM向iOS设备发送2-layer-json-payload时出现问题

时间:2018-09-25 02:50:07

标签: ios firebase apple-push-notifications firebase-cloud-messaging

我从FCM服务器发送推送通知时遇到问题。以前,我们为此目的使用APNS,我的服务器和客户端会像这样创建有效负载。而且效果很好。

const aws = require('aws-sdk')
const async = require('async')
const fs = require('fs')

const bucket = 'mybucket'
const s3Src = 'mys3src'
const local = '/tmp/'
aws.config.region = 'us-west-2'
const s3 = new aws.S3()

exports.handler = (event, context, callback) => {
    const outputImage = 'hello_world.png'

    async.waterfall([
            function download(next) {
                let downloaded = 0,
                    errorMessages = []

                for (let i = 0; i < event['images'].length; i++) {
                    let key = `${s3Src}/${event['images'][i]['prefix']}/${event['images'][i]['image']}`,
                        localImage = `${local}${event['images'][i]['image']}`

                    getBucketObject(bucket, key, localImage).then(() => {
                        downloaded++

                        if (downloaded === event['images'].length) {
                            if (errorMessages.length > 0) {
                                next(errorMessages.join(' '))
                            } else {
                                console.log('All downloaded')
                                next(null)
                            }
                        }
                    }).catch(error => {
                        downloaded++
                        errorMessages.push(`${error} - ${localImage}`)

                        if (downloaded === event['images'].length) {
                            next(errorMessages.join(' '))
                        }
                    })
                }
            }
        ], err => {
            if (err) {
                console.error(err)
                callback(null, {
                    "statusCode": 400,
                    "body": JSON.stringify(err),
                    "isBase64Encoded": false
                })
            } else {
                console.log('event image created!')
                callback(null, {
                    "statusCode": 200,
                    "body": JSON.stringify(`<img src="${local}${outputImage}" />`),
                    "isBase64Encoded": false
                })
            }
        }
    )
}

function getBucketObject(bucket, key, dest) {
    return new Promise((resolve, reject) => {
        let ws = fs.createWriteStream(dest)

        ws.once('error', (err) => {
            return reject(err)
        })

        ws.once('finish', () => {
            return resolve(dest)
        })

        let s3Stream = s3.getObject({
            Bucket: bucket,
            Key: key
        }).createReadStream()

        s3Stream.pause() // Under load this will prevent first few bytes from being lost

        s3Stream.on('error', (err) => {
            return reject(err)
        })

        s3Stream.pipe(ws)
        s3Stream.resume()
    })
}

现在,我们转向使用FCM替代APNS,正如您所知,FCM服务器将接收到该消息,将其转换为APNS格式,然后将其发送给APNS服务器,APNS服务器会将转换后的消息发送给客户端。但是首先,我必须遵循这样的有效负载格式。

{
  "data": {
    "image": "https://premierleague-static-files.s3.amazonaws.com/premierleague/photo/2018/09/24/0e228e97-1644-4fcf-bc18-d7223d8f398f/DreamTeamGW6.png",
    "link":"https://stackoverflow.com/"
  },
  "aps": {
    "alert": "This is me",
    "sound": "default",
    "mutable-content": 1
  },
  "contentId": "123456"
}

我不希望从FCM转换为APNS的消息。

{
  "notification": {
    "body": "This is me",
    "badge": 1,
    "sound": "default",
    "mutable-content": 1
  },
  "delay_while_idle": false,
  "data": {
    "data": {
      "image": "https://premierleague-static-files.s3.amazonaws.com/premierleague/photo/2018/09/24/0e228e97-1644-4fcf-bc18-d7223d8f398f/DreamTeamGW6.png",
      "link":"https://stackoverflow.com/"
    },
    "contentId": "123456"
  },
  "time_to_live": 10
}

如您所见,“ data”键的值不是以前的JSONObject,而是一个字符串。我的问题是:如何使FCM服务器理解主“数据”中的子“数据”对象是JSONObject,而不是将消息转换为APNS的有效负载时的字符串?

谢谢!

1 个答案:

答案 0 :(得分:1)

在FCM有效载荷(reference for the FCM payload parameters here)中:

  • badge应该是字符串
  • mutable_content应该在notification之外
  • delay_while_idle is deprecated
  • data消息只能保存键值对。您正在传递一个(data)JSON对象,该对象无法正常工作。

我想想到的最快方法是将data JSON对象的内容放在外面(即与contentId相同的级别,然后像这样格式化FCM有效负载:

{
  "mutable-content": 1
  "notification": {
    "body": "This is me",
    "badge": 1,
    "sound": "default"
  },
  "data": {
      "image": "https://premierleague-static-files.s3.amazonaws.com/premierleague/photo/2018/09/24/0e228e97-1644-4fcf-bc18-d7223d8f398f/DreamTeamGW6.png",
      "link":"https://stackoverflow.com/",
      "contentId": "123456"
  },
  "time_to_live": 10
}

但是根据您的客户端代码,这可能不起作用,但是我希望您能理解。干杯!