I wrote a cloud function using Cloud Functions for Firebase that sends notifications to certain topics of Firebase Messaging. The final parts of the function define the payload to be sent, then sends it:
// javascript code in cloud functions
const payload = {
'notification': {
'title': `${toTitleCase(name)} just logged an event`,
'body': `${events[eventType]} for ${toTitleCase(petName)}`,
'data': {
'personSent': userSent
}
}
};
console.log(payload);
admin.messaging().sendToTopic(pet_Id, payload);
However, I'm getting the error log in my Firebase console:
Error: Messaging payload contains an invalid value for the "notification.data" property. Values must be strings.
When I logout the payload I confirmed it is all strings:
{ notification:
{ title: 'Turtle Dude just logged an event',
body: 'Walk for Beer',
data: { personSent: 'mfsP8U0qDdQL4rrrbXp6K0YsF423' } } }
However, when I send the same payload from my iPhone app (which I'm trying to avoid since that means I have to store the messaging private key on the client side) I am able to attach the extra data I want to send just fine:
// Swift code in iPhone app
let body: [String: Any] = ["to": "/topics/\(currentPet)",
"priority" : "high",
"notification" : [
"body" : "\(events[eventType]) for \(petsName.localizedCapitalized)",
"title" : "\(myName.localizedCapitalized) just logged an event",
"data" : ["personSent": myId]
]
]
How can I accomplish adding additional data in my cloud function like I do in my Swift code?
As others explained in the comments, the data object should go inside payload,
NOT inside notification.
Try the following code:
// javascript code in cloud functions
const payload = {
'notification': {
'title': `${toTitleCase(name)} just logged an event`,
'body': `${events[eventType]} for ${toTitleCase(petName)}`,
},
// NOTE: The 'data' object is inside payload, not inside notification
'data': {
'personSent': userSent
}
};
console.log(payload);
admin.messaging().sendToTopic(pet_Id, payload);
Along with Diego's answer, I would like to point out a crucial detail for anyone who visits this message in the future...
"Make sure to PARSE ANY ObjectId's to String when assigning it to a value for any key inside DATA"
.
This has pretty much been the most unfigurable problem while dealing with FCM. And was the prime factor in solving my problem.
Whoever might experience this error by now. Using node V14.7.0 on Windows and firebase-admin version ^9.6.0 seem to work perfectly, I had no issue. However, when deploying it on Bitnami, the error was thrown. To solve it, I had to parse the object someObject properties to be assigned to 'data' to string:
//someObject.property_throwing the error should be parsed to string
data: someObject
Related
I am using getServerSideProps to fetch data from my firebase database into my Next.js application.
My code snippet looks like this:
export async function getServerSideProps(context) {
const session = await getSession(context);
const products = await fetch("https://database-73695.firebaseio.com/").then(
(res) => res.json()
);
return {
props: {
products,
session
},
};
}
The problem is that I get error message saying the following: "FetchError: invalid json response body at https://database-73695.firebaseio.com/ reason: Unexpected token F in JSON at position 0"
I have seen that some people report this error when the data fetched is actually text and not an object. I tried changing the response from res.json to res.text, but then I'm told that "text is undefined".
Does anybody have any idea of what could be happening?
UPDATE:
By testing different fetching methods, I have seen the error:
Firebase error. Please ensure that you have the URL of your Firebase Realtime Database instance configured correctly.
All fetching code (with or without getServerSideProps) work when used with other APIs.
My database URL comes from Firestore, and is formated as follows:
https://PROJECT-ID.firebaseio.com
It is located in us-central, which I know is important for the URL.
Something else that might be worth noting: the database has already a collection called "users" tied to Stripe transactions, which works.
Any ideas?
Thank you for your time.
->try adding headers:
headers:
{
Accept: 'application/json, text/plain, /'
'User-Agent': '*',
},
->try checking if data is not been fetch from the back-end
I want to set up an one-time PayPal payment. I am calling <script data-page-type="checkout" src="https://www.paypal.com/sdk/js?client-id={my client id}¤cy=CZK&commit=true&intent=capture&debug=true"></script> from HTML to get the button to show.
I then set it up in the client-side javascript like this
createOrder: function(data, actions) {
return fetch('/.netlify/functions/transactionProcessor?orderAction=create', {
method: 'post',
}).then(function(functionResponse) {
console.log("order created");
return functionResponse.json();
}).then(function(functionResponseJson) {
return functionResponseJson.id;
});
},
When the user clicks the button, createOrder is called. CreateOrder then calls this server-side code
async function createOrder(client) {
// Call PayPal to set up a transaction.
const request = new paypal.orders.OrdersCreateRequest();
request.prefer('return=minimal');
request.requestBody({
intent: 'CAPTURE',
purchase_units: [{
amount: {
currency_code: 'CZK',
value: '69.99'
}
}]
});
const order = await client.execute(request);
console.log('order successfuly created');
// Return a successful serverResponse to the client with the order ID.
return { statusCode: 200, body: JSON.stringify({ serverResponse: order, id:
order.result.id }) }
}
That returns absolutely fine. The client-side code then handles it by returning it in it's createOrder method - and here the error occurs.
RESOURCE_NOT_FOUND (https://justpaste.it/resource_not_found_paypal_err)
INVALID_RESOURCE_ID (https://justpaste.it/invalid_resource_id_err)
I have absolutely no idea why it happens and I've been trying to fix it for days already. It WORKS IN SANDBOX.
You should not be doing a REST API capture request from the client side. This API call to PayPal should only be executed from a server.
As for why it is erroring with an invalid profile ID in live but not sandbox, it's possible you neglected to update the clientID+secret in said client side code. However, as mentioned, the secret (and the auth token you get with it) should never be used from the client side. It is for server-side API calls only.
Solved. I was accidentally using sandbox environment on the server. The logic was process.env.SANDBOX ? sandboxEnv : liveEnv, but the process.env variable doesn't work for some reason (Netlify + Netlify dev). I replaced it with local const sandbox = false.
Can't believe I spent so much time on this. I'd never find this if I didn't fiddle with it so stupidly much.
I am using Strapi and can't get the email route to work in development. When I hit the /email route in postman, it returns internal service error. In the terminal I get the following error AssertionError [ERR_ASSERTION]: Cannot wrap non-Error object.
I have been following the docs here https://strapi.io/documentation/3.0.0-beta.x/migration-guide/migration-guide-alpha.26-to-beta.html#migrating-plugins as well as referencing an article here
What's odd is that when I followed the docs to set up the built in strapi email plugin in another project, everything worked fine. In the new project I'm working on, I more or less copied that code from my previous project and put it in the new project. But in the new project the /email route doesn't seem to work.
Here is the code that I'm using in extensions/email/controllers/Email.js
module.exports = {
send: async (ctx) => {
// Retrieve provider configuration.
const config = await strapi
.store({
environment: strapi.config.environment,
type: 'plugin',
name: 'email'
})
.get({ key: 'provider' });
// Verify if the file email is enable.
if (config.enabled === false) {
strapi.log.error('Email is disabled');
return ctx.badRequest(
null,
ctx.request.admin ? [ { messages: [ { id: 'Email.status.disabled' } ] } ] : 'Emailis disabled'
);
}
// Something is wrong
if (ctx.status === 400) {
return;
}
let options = ctx.request.body;
await strapi.plugins.email.services.email.send(options, config);
await strapi.plugins['email'].services.email.send({
to: ctx.request.body.to,
subject: 'Test message',
text: 'Test Text'
});
}
};
If anyone needs anymore information, or needs me to clarify something, please let me know. Thanks!
Put a try and catch in the email send service, you will be able to get the actual error behind this, as in my case when I was using SendGrid as the mail provider I did the same approach and found this in the error body
status:403,
[
{
message: 'The from address does not match a verified Sender Identity. Mail cannot be sent until this error is resolved. Visit https://sendgrid.com/docs/for-developers/sending-email/sender-identity/ to see the Sender Identity requirements',
field: 'from',
help: null
}
]
This got fixed after putting a verified email in the default_from key which i generated from the SendGrid dashboard panel.
I am currently building out an AJAX registration endpoint for Django to allow for FIDO2 authentication (physical hardware key login). This is from following the example/documentation from Yubico's official fido2 python library.
The only dependencies are cbor.js and js-cookie. Everything server-side is working for now, however, I keep getting this JavaScript error while invoking the navigator.credentials.create method
TypeError: Failed to execute 'create' on
'CredentialsContainer': The provided value is not of
type '(ArrayBuffer or ArrayBufferView)'
The code:
var csrftoken = Cookies.get('csrftoken');
fetch('/register/begin', {
method: 'POST',
headers: {
'X-CSRFToken': csrftoken
}
}).then(function(response) {
if(response.ok) {
return response.arrayBuffer();
}
throw new Error('Error getting registration data!');
}).then(CBOR.decode).then(function(options) {
console.log(options)
//This line is not working
return navigator.credentials.create(options);
//More code... complete registration...
I can't figure this out. Do you know whats wrong? Thanks!
I had the same problem, and the cause was that some of the pieces of data sent from the server in the response from /register/begin must be formatted as byte strings rather than unicode strings. In particular, I've found that the user_id and the credential ids have to be byte strings - assuming that you are also following Yubico's example in the server, implemented in python 3.
Also of note is that in this case I've found Firefox's error messages much more helpful than chome's.
I was having this issue as well. I ended up using the TextEncoder class to encode the challenge and the user id...
const enc = new TextEncoder();
const createCredentialOptions: CredentialCreationOptions = {
publicKey: {
rp: rp,
challenge: enc.encode(challenge),
user: {
id: enc.encode(user.id),
name: user.name,
displayName: user.displayName
},
pubKeyCredParams: pubKeyCredParams,
...
Even if this issue has been raised many times over the past year, it's not yet correctly solved ... especially when using the latest googleapis lib ! Google doc is not useful as many deprecated methods are still mentioned and no javascript examples are given...
using people.get() ( after a list() ) I can get a view on how it should be ( I guess)
{
"resourceName":"people/c3451490284670017263",
"etag":"%EgcBAggJNyUuGgwBAgMEBQYHCAkKCwwiDHVtR0Y5OHZVMnhJPQ==",
"locales":[{"metadata":{"primary":true,"source":{"type":"CONTACT","id":"2fe628208b77deef"}},"value":"en"}],
"emailAddresses":[{"metadata":{"primary":true,"source":{"type":"CONTACT","id":"2fe628208b77deef"}},"value":"john.doe#example.com"]
}
so I tried to create a new People this way :
return google.people('v1').people.createContact({
auth: jwtClient,
resourceName: 'people/me',
locales: ['en'],
genders: ['female'],
names: [{givenName: 'Jenny', familyName: 'Doe'}],
emailAddresses: ['jenny.doe#example.com']
})
but NO WAY... I am always getting errors :
Invalid JSON payload received. Unknown name \"genders\": Cannot bind query parameter. Field 'genders' could not be found in request message.
Invalid JSON payload received. Unknown name \"locales\": Cannot bind query parameter. Field 'locales' could not be found in request message.
Invalid JSON payload received. Unknown name \"names[familyName]\": Cannot bind query parameter. Field 'names[familyName]' could not be found in request message.
Invalid JSON payload received. Unknown name \"emailAddresses\": Cannot bind query parameter. Field 'emailAddresses' could not be found in request message.
Invalid JSON payload received. Unknown name \"names[givenName]\": Cannot bind query parameter. Field 'names[givenName]' could not be found in request message.
Invalid JSON payload received. Unknown name \"resourceName\":Cannot bind query parameter. Field 'resourceName' could not be found in request message.
Is any example existing on the web ?
feedback welcome ... ( even from a Google man... LOL )
After double-checking (maybe triple...) the documentation , I read the following statement
Usage
Specifying request body
The body of the request is specified in the requestBody parameter object of the request. The body is specified as a JavaScript object with key/value pairs. For example, this sample creates a watcher that posts notifications to a Google Cloud Pub/Sub topic when emails are sent to a gmail account:
const res = await gmail.users.watch({
userId: 'me',
requestBody: {
// Replace with `projects/${PROJECT_ID}/topics/${TOPIC_NAME}`
topicName: `projects/el-gato/topics/gmail`
}
});
console.log(res.data);
so I wrote :
return google.people('v1').people.createContact({
auth: jwtClient,
parent: 'people/me',
requestBody: {
locales: [{ value: 'en' }],
genders: [{ value: 'female' }],
names: [{ givenName: 'Jenny', familyName: 'Doe' }],
emailAddresses: [{ value: 'jenny.doe#example.com' }]
}
})
And the request is executed without any error ... I can see the new contact in mt Google account app Contacts..