I'm trying to send multiple notifications using the messaging.sendAll() function of the Firebase Admin SDK.
The way in which I write the messages to send is this:
const messages = [];
const token2 = user2Data.notificationToken;
messages.push({
notification: {
title: `title`,
body: "this is the body!",
icon: "default",
sound: "customNotificationSound.wav",
content_available: "true",
},
data: {
notificationType: "notif2",
uid1: toUser,
uid2: fromUser,
},
token: token2,
});
const token1 = user1Data.notificationToken;
messages.push({
notification: {
title: `title`,
body: "this is the body!",
icon: "default",
sound: "customNotificationSound.wav",
content_available: "true",
},
data: {
notificationType: "notif1",
uid1: toUser,
uid2: fromUser,
},
token: token1,
});
return admin.messaging().sendAll(messages).then((promMes) => {
console.log("messages are sent");
console.log(promMes);
});
I don't know why but the messages to the different devices have not been sent.
I know that because of the promise I receive after I call the method sendAll(). In fact the error I get in the log is this:
textPayload: " { success: false, error: [FirebaseMessagingError] },"
I suppose that the problem hides behind how I construct the message payload but I wouldn't know how to fix it.
Related
I'm having issues creating a subscription with stripe using a lambda function, this code runs fine locally but it is returning "internal server error" when posting to lambda, there are no logs in cloudwatch.
code for lambda function is below
exports.handler = async (event, context, callback) => {
// GET ITEMS
const { productId, customerId, currency = "gbp" } = JSON.parse(event.body);
let paymentMethods;
try {
paymentMethods = await stripe.paymentMethods.list({
customer: customerId,
type: 'card',
});
} catch (e) {
return {
statusCode: 200, // http status code
body: JSON.stringify({
"error" : true,
"msg" : "error retrieving payment method",
"data" : null
})
};
}
console.log(paymentMethods)
// Setup subscription
try {
const subscription = await stripe.subscriptions.create({
customer: customerId,
default_payment_method: paymentMethods.data[0].id,
items: [
{price: productId},
],
});
console.log(subscription)
// SUCCESS
return {
statusCode: 200, // http status code
body: JSON.stringify({
"data" : "success",
"error" : false,
"msg" : null
})
};
// ERROR
} catch (e) {
console.log(e);
return {
statusCode: 200, // http status code
body: JSON.stringify({
"error" : true,
"msg" : "error",
"data" : null
})
};
}
};
I can see the log for the payment methods but the log for the subscription is never shown, this does, however, create the subscription correctly in the stripe portal against that customer but no response is found from aws just a 500 internal server error.
any help would be greatly appreciated.
turns out I had my lambda function set to a 3-second timeout! as soon as I increased it the function worked fine, hopefully, this might help someone out with the same issue.
I have a very simple lambda function that publishes a message to a topic like so:
const AWS = require('aws-sdk');
const sns = new AWS.SNS()
const TOPIC_ARN = "arn:aws:sns:us-east-1:<topic ARN>";
const TARGET_ARN = "arn:aws:sns:us-east-1:<target ARN>";
exports.handler = async (event) => {
return sns.publish({
Message: JSON.stringify({
"default": "any value",
"GCM": "{ \"notification\": { \"body\": \"message body\", \"title\": \"message title \", \"sound\":\"default\" } , \"data\" : {\"key\" : \"value\", \"key2\" : \"value\" } }"
}),
TargetArn: TARGET_ARN,
// TopicArn: TOPIC_ARN, also tried this same result
})
.promise()
.then(() => ({statusCode: 204, body: ''}))
.catch(err => {
console.log(err);
return {statusCode: 500, body: 'sns-error'};
});
};
The function executes without issue and I can see a success event in my cloud watch logs.
The problem is that the Notification is never received by the device.
I know that the ARN is correct because I can go to the SNS console and publish the same message to the device and it is received.
I can also spin up a nodejs application on my local machine and publish the same message to the ARN and it is received, no problem.
I also configured Delivery Status Logging on the Platform Application and I can see a success response like so from the lambda function:
{
"notification": {
"messageMD5Sum": "<sting of numbers>",
"messageId": "<sting of numbers>",
"timestamp": "2021-07-23 15:35:02.167"
},
"delivery": {
"deliveryId": "<sting of text>",
"destination": "<ARN>",
"providerResponse": "{\"multicast_id\":<sting of numbers>,\"success\":1,\"failure\":0,\"canonical_ids\":0,\"results\":[{\"message_id\":\"0:<sting of text>\"}]}",
"dwellTimeMs": 28,
"attempts": 1,
"token": <correct device token>,
"statusCode": 200
},
"status": "SUCCESS"
}
Why is the lambda function the only method where the SNS notification is not being received by the device?
SOLUTION
const AWS = require('aws-sdk');
const sns = new AWS.SNS()
const TOPIC_ARN = "arn:aws:sns:us-east-1:<topic ARN>";
const TARGET_ARN = "arn:aws:sns:us-east-1:<target ARN>";
exports.handler = async (event) => {
return sns.publish({
Message: JSON.stringify({
"default": "any value",
"GCM": "{ \"notification\": { \"body\": \"message body\", \"title\": \"message title \", \"sound\":\"default\" } , \"data\" : {\"key\" : \"value\", \"key2\" : \"value\" } }"
}),
MessageStructure: 'json', //this solved the problem
TargetArn: TARGET_ARN,
})
.promise()
.then(() => ({statusCode: 204, body: ''}))
.catch(err => {
console.log(err);
return {statusCode: 500, body: 'sns-error'};
});
};
Adding MessageStructure: 'json' solved the problem.
Thanks for all suggestions.
Edited original question to include answer:
Adding MessageStructure: 'json' solved the problem.
Thanks for all suggestions.
I am trying to send push notification via firebase:
await admin.messaging().sendAll({
token: 'some token',
data: {val1: '1', val2: '2'},
time_to_live: 300,
});
I am getting next error:
{"message":"Send push notification failed, Invalid JSON payload
received. Unknown name "time_to_live" at 'message': Cannot find
field.","level":"error"}
In firebase for time_to_live the key is ttl, also I use this request body for sending push notifications in android apps:
const body = {
notification: {
title: 'xxxx',
body: "xxxxxxxx"
},
data: {
notification_message: "xxxxxx"
},
token: 'xxxxxx',
android: {
ttl: 3600,
notification: { icon: 'xxxxx', color: '#b2b2b2' }
}
}
await admin.messaging().send(body)
Use ttl key in case of time_to_live.
i have one use case in which I need to send custom data along with push notification in Google Assistant using ActionOnSDK , how can I send it anyone has any clue?
let notification = {
userNotification: {
title: 'A new tip is added',
},
target: {
userId: 'abcd1234-EFGH_789',
intent: 'tell_latest_tip',
// Expects a IETF BCP-47 language code (i.e. en-US)
locale: 'en-US'
},
};
request.post('https://actions.googleapis.com/v2/conversations:send', {
'auth': {
'bearer': tokens.access_token,
},
'json': true,
'body': {
'customPushMessage': notification
}
};
I'm trying to post data to an Items API, for instance:
"data": {
"title": "stack",
"notes": "asdsad",
"time": "19:02",
"meridian": "PM",
"type": "Education",
"_id": "5a2f02d3bba3640337bc92c9",
"days": {
"Monday": true,
"Tuesday": false,
"Wednesday": false,
"Thursday": false,
"Friday": false,
"Saturday": false,
"Sunday": false
}
}
However, when using HttpClient to post the data
this.http.post("http://localhost:3000/api/items",
JSON.stringify(item))
.subscribe(
(val) => {
console.log("POST call successful value returned in body",
val);
},
response => {
console.log("POST call in error", response);
},
() => {
console.log("The POST observable is now completed.");
});
I always get the Bad Request 400 response from the Items Controller in the API.
exports.createItem = async function(req, res, next){
// Req.Body contains the form submit values.
console.log(req);
console.log(req.body);
var item = {
id: req.body.id,
title: req.body.title,
days: req.body.days,
notes: req.body.notes,
time: req.body.time,
meridian: req.body.meridian,
type: req.body.type,
completed: req.body.completed,
}
try{
// Calling the Service function with the new object from the Request Body
var createdItem = await ItemService.createItem(item)
return res.status(201).json({status: 201, data: createdItem, message: "Succesfully Created Item"})
} catch(e){
console.log(e);
//Return an Error Response Message with Code and the Error Message.
return res.status(400).json({status: 400, message: "Item Creation was Unsuccesfull"})
}
}
I have already set up BodyParser in my app.js as so
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
In the express console, the output is as follows
_startTime: 2017-12-11T22:35:18.204Z,
_remoteAddress: '::1',
body: {},
secret: undefined,
cookies: {},
signedCookies: {},
route:
Route {
path: '/',
stack: [ [Object], [Object] ],
methods: { post: true } } }
{}
As you can see the body is empty and this is preventing an item from being created. I have gone ahead and tested this using Postman and when sending url encoded form data and raw JSON data the posts are successful and return 200. However, I can never get the application's request to work.
Any help is appreciated as I have been struggling with this for several hours now.
this.http.post("http://localhost:3000/api/items",
JSON.stringify(item) -----> convert JSON object to string
).subscribe(...);
Based on your server side code, I believe that it expects JSON object other than a JSON string, therefore remove JSON.stringify(item)) from your client side, the body of your POST should be JSON object.