Stripe Webhook error 400 with netlify functions - javascript

I have set up payments with stripe using Netlify function by following this article https://www.netlify.com/blog/2020/04/22/automate-order-fulfillment-w/stripe-webhooks-netlify-functions/ and in my Stripe dashboard I get error saying that:
Webhook Error: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing
Now I am not sure if the user gets confirmation email, Sendgrid does not show any activity, however it has not shown any when I was testing this flow previously, and although I received confirmation email. Unfortunately back then I pressed resend by my webhook activity details in Stripe dashboard, and I am not sure if I should be resending those or do they go through. Would anyone be able to tell me what is wrong with my code?
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
const sgMail = require("#sendgrid/mail");
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
exports.handler = async ({ body, headers }) => {
try {
const stripeEvent = stripe.webhooks.constructEvent(
body,
headers["stripe-signature"],
process.env.STRIPE_WEBHOOK_SECRET
);
if (stripeEvent.type === "charge.succeeded") {
const emailTo = stripeEvent.data.object.billing_details.email;
const msg = {
to: emailTo,
from: process.env.FROM_EMAIL_ADDRESS,
subject: `Thanks!`,
html: `elox`,
};
await sgMail.send(msg);
}
return {
statusCode: 200,
body: JSON.stringify({ received: true }),
};
} catch (err) {
console.log(`Stripe webhook failed with ${err}`);
return {
statusCode: 400,
body: `Webhook Error: ${err.message}`,
};
}
};
Thanks!

I got the same issue.
Locally with the stripes-cli everything works fine.
It seems that the lambda didn't hand over the raw body to the stripes.webhook.constructEvent.
Therefore my solution was to change the method signature to the following and use the event.body object.
exports.handler = async(event, context ) => {
try {
const stripeEvent = stripe.webhooks.constructEvent(
event.body,
event.headers['stripe-signature'],
endpointSecret
);....

Related

after deploy, fcm alert function is not working... java.lang.IllegalArgumentException: Exactly one of token, topic or condition must be specified

I made alert service using FCM, it works fine in my local server. but after I deployed my server in ec2, trying alert function on ec2 app gives me this error :
[ient-SecureIO-1] o.a.t.websocket.pojo.PojoEndpointBase : No error handling configured for [springboot.utils.WebsocketClientEndpoint] and the following error occurred
java.lang.IllegalArgumentException: Exactly one of token, topic or condition must be specified
Reading the error message, i guess that there's no token in my server.
In notification.js, I'm trying to get token and request POST to '/register'
const firebaseModule = (function () {
async function init() {
// Your web app's Firebase configuration
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/firebase-messaging-sw.js')
.then(registration => {
var firebaseConfig = {
configuration Information
};
// Initialize Firebase
console.log("firebase Initialization");
firebase.initializeApp(firebaseConfig);
// Show Notification Dialog
const messaging = firebase.messaging();
messaging.requestPermission()
.then(function() {
console.log("Permission granted to get token");
return messaging.getToken();
})
.then(async function(token) {
console.log("Token: ", token);
await fetch('/register', { method: 'post', body: token })
messaging.onMessage(payload => {
const title = payload.notification.title
const options = {
body : payload.notification.body
}
navigator.serviceWorker.ready.then(registration => {
registration.showNotification(title, options);
})
})
})
.catch(function(err) {
console.log("Error Occured : " +err );
})
})
})
}
}
And by debugging it by console.log(), I found out that code is stopped before "if ('serviceWorker' in navigator) {"
So I need to make it proceed. But to be honest, it's been a while since i made this function, and I don't know almost anything about Javascript. I don't even know what navigator means(I googled it, but couldn't find clear answer) I'm having trouble figuring out what is wrong and how can I fix it. Can someone help me??

Google Cloud Function Not Returning Error Message

I have the following code in a google cloud function. When the user account is created it returns status 200 and the name of the registered user which I can access from the return of the successful promise. All works as expected. However, when there is an error creating the new user the status changes to 400 but no matter what on the client side I get an error of "Error: invalid-argument". I want to pass the error message from the google cloud function. When I check the cloud function logs, I can see the error code and error message.
What I tried: I did try to use the throw new functions.https.HttpsError() but I get a CORS error message.
Any advice on getting the cloud function to pass the error message properly?
const { initializeApp, applicationDefault, cert } = require('firebase-admin/app');
const { getFirestore, Timestamp, FieldValue } = require('firebase-admin/firestore');
const { getAuth } = require('firebase-admin/auth')
const functions = require('firebase-functions')
const app = initializeApp();
const db = getFirestore();
exports.registerUser = (req, res) => {
let registerDetails = req.body.data;
res.set('Access-Control-Allow-Origin', '*');
if (req.method === 'OPTIONS') {
// Send response to OPTIONS requests
res.set('Access-Control-Allow-Methods', 'GET');
res.set('Access-Control-Allow-Headers', 'Content-Type');
res.set('Access-Control-Max-Age', '3600');
res.status(204).send('');
} else {
console.log(registerDetails)
if(registerDetails.FirstName === undefined || registerDetails.FirstName === ""){
res.status(400).json({data: 'Invalid Request'})
} else {
console.log(registerDetails);
getAuth()
.createUser({
email: registerDetails.Email,
emailVerified: false,
password: registerDetails.Password,
displayName: registerDetails.DisplayName,
disabled: false,
})
.then((userRecord) => {
// See the UserRecord reference doc for the contents of userRecord.
let message = 'Registered user '+registerDetails.DisplayName+".";
res.status(200).json({data: message});
console.log('Successfully created new user:', userRecord.uid);
},(error)=>{
res.status(400).json({code:error.errorInfo.code,message:error.errorInfo.message})
console.log('Error creating new user:', error);
})
}
}
};
To anyone who views this post, the solution is that I was confusing HTTP and HTTPS Callable functions, which have different syntax.
See this post:
Google Cloud Function Cors Error Only When Error is Thrown

AstraDB failed GET request

I have been working on a TikTok clone app. So I created my database with Astra DB and set up two functions inside a function folder to test out if my posts are working. I am using netlify dev to test out the applications. But when I redirect http://localhost:8888/.netlify/functions/addData
I get this failed get request error
Request from ::1: GET /.netlify/functions/addData
Error: Request Failed: [object Object]
Stack Trace: Request failed with status code 401
at axiosRequest (D:\tiktokclone\node_modules\#astrajs\rest\src\rest.js:126:11)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async AstraClient._request (D:\tiktokclone\node_modules\#astrajs\rest\src\rest.js:199:22)
at async AstraClient.put (D:\tiktokclone\node_modules\#astrajs\rest\src\rest.js:263:12)
at async AstraCollection._put (D:\tiktokclone\node_modules\#astrajs\collections\src\collections.js:69:22)
at async Object.exports.handler (D:\tiktokclone\functions\addData.js:17:9)
Response with status 500 in 231 ms.
I quite don't understand what causes this. All the credentials inside my .env folder were correct.Here is the code I used to make the request
const { createClient } = require("#astrajs/collections");
const collection = "posts";
exports.handler = async function (event, context, callback) {
const astraClient = await createClient({
astraDatabaseId: process.env.ASTRA_DB_ID,
astraDatabaseRegion: process.env.ASTRA_DB_REGION,
applicationToken: process.env.ASTRA_DB_APPLICATION_TOKEN,
});
console.log(astraClient)
console.log(collection)
console.log('Hello')
const posts = astraClient
.namespace(process.env.ASTRA_DB_KEYSPACE)
.collection(collection);
try {
await posts.create("a post", {
title: "my first post",
});
return {
statusCode: 200,
};
} catch (e) {
console.error(e);
return {
statusCode: 500,
body: JSON.stringify(e),
};
}
};
I found a fix. For some reason, I was trying to call the API using an application token and it was giving me the 401 error. When I used username and password it worked.
const astraClient = await createClient({
astraDatabaseId: process.env.ASTRA_DB_ID,
astraDatabaseRegion: process.env.ASTRA_DB_REGION,
username: process.env.ASTRA_DB_USERNAME,
password: process.env.ASTRA_DB_PASSWORD,
});
username is the client ID and password is the client secret. This error happened because of a slight confusion with the REST API and the Document API. Astra DB uses application token for authenticating document API while REST API uses client ID and Password.

React.js App SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

After deploy react.js application on server I am getting error in contact form as in title. On localhost the form worked without any errors. The problem occurs just after clicking the sumbit button on the form. Then you can see the error in the console. Do any of you see any error in the code below? Where can I look for a solution to this error?
Live version of the contact page
Contact page
ContactForm.js
const ContactForm = () => {
const [status, setStatus] = useState("Submit");
const handleSubmit = async (e) => {
e.preventDefault();
setStatus("Sending...");
const { name, email, subject, business, datetime, launch, message } = e.target.elements;
let details = {
name: name.value,
email: email.value,
subject: subject.value,
business: business.value,
datetime: datetime.value,
launch: launch.value,
message: message.value,
};
let response = await fetch("https://delightart.co/send", {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(details),
});
setStatus("Submit");
let result = await response.json();
alert(result.status);
};
That's because the response body of fetch is not in JSON format, so when you
use response.json(), it threw the error. So you need make sure whether response is a JSON, either you can use it without calling response.json() or use JSON.stringify() in the backend service to turn the data into JSON format before sending it.
You can check Response apis in MDN https://developer.mozilla.org/en-US/docs/Web/API/Response.
And response.json() inherits from body.json(), so you can check it for more details. https://developer.mozilla.org/en-US/docs/Web/API/Body/json

Receiving [Error: Internal] in RN app when triggering a Cloud Function

I have a Google Cloud Function which I am calling from my RN app but it is returning
[Error: Internal]
I have set the permission to Unauthenticated users so anyone can call it - for testing purposes only. When I set to Authenticated users permission, it throws another error [Error: Unauthenticated] eventhough I am authenticated and I can get the currentUser id in my app.
Tried searching for this error but it didnt send me to any possible solutions so decided to post here and hopefully recieve responses that will help me fix it.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.createUser = functions.region('europe-west1').https.onCall(async (data, context) => {
try {
//Checking that the user calling the Cloud Function is authenticated
if (!context.auth) {
throw new UnauthenticatedError('The user is not authenticated. Only authenticated Admin users can create new users.');
}
const newUser = {
email: data.email,
emailVerified: false,
password: data.password,
disabled: false
}
const role = data.role;
const userRecord = await admin
.auth()
.createUser(newUser);
const userId = userRecord.uid;
const claims = {};
claims[role] = true;
await admin.auth().setCustomUserClaims(userId, claims);
return { result: 'The new user has been successfully created.' };
} catch (error) {
if (error.type === 'UnauthenticatedError') {
throw new functions.https.HttpsError('unauthenticated', error.message);
} else if (error.type === 'NotAnAdminError' || error.type === 'InvalidRoleError') {
throw new functions.https.HttpsError('failed-precondition', error.message);
} else {
throw new functions.https.HttpsError('internal', error.message);
}
}
});
in my RN app I am calling it like this:
var user = {
role: role
}
const defaultApp = firebase.app();
const functionsForRegion = defaultApp.functions('europe-west1');
const createUser = await functionsForRegion.httpsCallable('createUser');
createUser(user)
.then((resp) => {
//Display success
});
console.log(resp.data.result);
})
.catch((error) => {
console.log("Error on register patient: ", error)
});
I think the way I am calling it in my RN app is correct because I have tested it with a testFunction and I returned a simple string. So, I believe the problem is somewhere in the function itself.
EDIT: I just tested by simply calling the function and returning the context and it always returns Internal error:
exports.registerNewPatient = functions.region('europe-west3').https.onCall((data, context) => {
return context; //this is returned as INTERNAL error.
}
I just cant get to understand whats going on here, why does it return Internal error when I am authenticated as a user and it should return the authenticated user data, isn't that right?
Try some console.log(context) ; console.log(data) statements in your registerNewPatient function and take a look at the logs. What do they say?
Some other things to consider might include that in your client code you use europe-west1 while your function code has europe-west3. Try to have those line up and see if it works? From my experience, if a specified function isn't found to exist, the client receives an INTERNAL error.

Categories

Resources