getting error "Error occured Invalid payload provided. No JSON object could be decoded"
i am using below code for webhook
exports.paymentHandler = async (req, res) => {
const rawBody = req.rawBody;
const signature = req.headers['x-cc-webhook-signature'];
console.log("rawbody ",rawBody)
try {
const event = Webhook.verifyEventBody(rawBody, signature, webhookSecret);
functions.logger.info(event);
if (event.type === 'charge:pending') {
// TODO
// user paid, but transaction not confirm on blockchain yet
console.log("pending payment");
}
if (event.type === 'charge:confirmed') {
// TODO
// all good, charge confirmed
console.log("charge confirme");
}
if (event.type === 'charge:failed') {
// TODO
// charge failed or expired
console.log("charge failed");
}
res.send(`success ${event.id}`);
} catch (error) {
console.log(error);
res.status(400).send("failure");
}
};
what could be the possible reason?
For Node.js app to get rawBody from Coinbase use this code.
//server file
//app.use(bodyParser.json())
app.use(bodyParser.json({
verify: (req, res, buf) => {
req.rawBody = buf
}
}))
Now the raw body is available on req.rawBody and the JSON parsed data is available on req.body.
Usage:
const payloadRaw = req.rawBody
Related
Using Node.js and Stripe. Stripe connects to the endpoint on my localhost but throws the error when it gets to stripe.webhooks.ConstructEvent. I can see req.body and the stripe signature in console.log.
Code:
**require('dotenv').config()
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)
module.exports = {
stripe: async(req, res) => {
console.log('req.body: ', req.body)
const sig = req.headers["stripe-signature"];
console.log('req.headers: ', req.headers)
let event;
try {
event = stripe.webhooks.ConstructEvent(
req.body,
sig,
process.env.STRIPE_WEBHOOKS_SECRET
)
return res.status(420).send("ok")
} catch (err) {
console.error(err)
return res.status(400).send(err.message)
}
}
}**
Should be stripe.webhooks.constructEvent. See: https://stripe.com/docs/webhooks/quickstart.
Everything appears to be working in the console for GET: CRCToken, the webhook is registered, account is authorized, etc.
But POST is not returning anything from Twitter regardless of what I do - favorite, tweet, DM.
Am I approaching this the right way or should I be using something like Twitter-Autohook in my firebase function instead?
exports.twitterMessage = functions.https.onRequest((req, res) => {
switch (req.method) {
case 'GET':
getTwitter(req, res);
break;
case 'POST':
postTwitter(req, res);
break;
default:
res.status(410).json({ message: "Unsupported Request Method" });
break;
}
});
function createCrcResponseToken(crcToken) {
const hmac = crypto.createHmac("sha256", myToken).update(crcToken).digest("base64");
return `sha256=${hmac}`;
}
function getTwitter(req, res) {
const crcToken = req.query.crc_token;
if (crcToken) {
console.log("CRC: " + crcToken)
res.status(200).send({
response_token: createCrcResponseToken(crcToken)
});
} else {
console.error("crc_token missing from request.");
response.sendStatus(400);
}
}
function postTwitter(req, res) {
console.log("received event", req.body);
res.sendStatus(200);
}
I'm setting up a stripe webhook to check if the payment intent was successful or not. But while doing so, I'm getting this error Cannot set headers after they are sent to the client in stripe, what am I doing wrong in the route?
import express from 'express';
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: "2020-08-27" });
const router = express.Router();
router.post(
"/webhook",
express.raw({ type: "*/*" }),
async (request, response) => {
const sig = request.headers["stripe-signature"];
let event;
try {
event = stripe.webhooks.constructEvent(
request.body,
sig,
process.env.STRIPE_WEBHOOK_SECRET_KEY
);
console.log("type", event);
} catch (err) {
// console.log("type2", err);
response.status(400).send(`Webhook Error: ${err.message}`);
}
response.json({ received: true });
}
);
export default router;
There's a section here https://stripe.com/docs/identity/handle-verification-outcomes that skips the body parsing if the url points to the webhook service
app.use((req, res, next) => {
if (req.originalUrl === '/webhook') {
next();
} else {
bodyParser.json()(req, res, next);
}
});
That could be the issue: webhook expects you not to execute express.raw() if you're going to give him the request.body to analyse
You are trying to send a json response with response.json() after the error handling sends the 400 response with response.status(400).send() -- you can't do that.
You need to either move your response.json() to the end of the try block or have the catch block return (as #abhishek noted) to stop the execution.
In the catch block you are not returning.
catch (err) {
// console.log("type2", err);
return response.status(400).send(`Webhook Error: ${err.message}`);
}
i developed a chatbot with nodejs and deployed it to heroku. but the webhook is not working properly since its gets an error saying sender PSID is not defined. what should I do? I need help from experts.. I haven't used wit.ai in my project but only node.js. and here i haven't posted post backs handlings as its too long!
my controllers.js as below.. (messages are in Sinhalese language)
import dotenv from 'dotenv';
dotenv.config();
import request from 'request';
const PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
const MY_VERIFY_TOKEN = process.env.MY_VERIFY_TOKEN;
let test = (req, res) => {
return res.send("hello again")
}
let getWebhook = (req, res) => {
// Your verify token. Should be a random string.
let VERIFY_TOKEN = MY_VERIFY_TOKEN
// Parse the query params
let mode = req.query['hub.mode'];
let token = req.query['hub.verify_token'];
let challenge = req.query['hub.challenge'];
// Checks if a token and mode is in the query string of the request
if (mode && token) {
// Checks the mode and token sent is correct
if (mode === 'subscribe' && token === VERIFY_TOKEN) {
// Responds with the challenge token from the request
console.log('WEBHOOK_VERIFIED');
res.status(200).send(challenge);
} else {
// Responds with '403 Forbidden' if verify tokens do not match
res.sendStatus(403);
}
}
}
let postWebhook = (req, res) => {
let body = req.body;
// Parse the request body from the POST
// Check the webhook event is from a Page subscription
if (body.object === 'page') {
// Iterate over each entry - there may be multiple if batched
body.entry.forEach(function (entry) {
// Gets the body of the webhook event
let webhook_event = entry.messaging[0];
console.log(webhook_event);
// Get the sender PSID
let sender_psid = webhook_event.sender.id;
console.log('Sender PSID: ' + sender_psid);
});
// Return a '200 OK' response to all events
res.status(200).send('EVENT_RECEIVED');
} else {
// Return a '404 Not Found' if event is not from a page subscription
res.sendStatus(404);
}
}
// Handles messages events
function handleMessage(sender_psid, received_message) {
let response;
// Checks if the message contains text
if (received_message.text) {
// Create the payload for a basic text message, which
// will be added to the body of our request to the Send API
response = {
"text": `ආයුබෝවන්! ඔබ මේ සම්බන්ද වන්නේ chatbot IN සේවාව වෙතයි.!ඔබට මේ පිළිබද වැඩිදුර දැනගැනීමට අවශ්යද?`,
"quick_replies":[
{
"content_type":"text",
"title":"Yes",
"payload":"<POSTBACK_PAYLOAD>",
},{
"content_type":"text",
"title":"No",
"payload":"<POSTBACK_PAYLOAD>",
}
]
}
}
}
// Send the response message
callSendAPI(sender_psid, response);
// Sends response messages via the Send API
function callSendAPI(sender_psid, response) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
}
// Send the HTTP request to the Messenger Platform
request({
"uri": "https://graph.facebook.com/v11.0/me/messages",
"qs": { "access_token": PAGE_ACCESS_TOKEN },
"method": "POST",
"json": request_body
}, (err, res, body) => {
if (!err) {
console.log('message sent!')
} else {
console.error("Unable to send message:" + err);
}
});
}
module.exports = {
test: test,
getWebhook: getWebhook,
postWebhook: postWebhook
}
Thanks!
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I have created a nodejs express application using Express Generator.
In its route index.js I'm trying to make a rest api call using default HTTP module in the standard library https://nodejs.org/api/http.html#http_http_get_options_callback (I do not want to install external dependencies)and that would provide the values for title and welcome text in the view. Below is the code for index.js.
var express = require('express');
var router = express.Router();
const http = require('http');
/* GET home page. */
router.get('/', function(req, res, next) {
let titletext = '';
let wtext = '';
http.get('http://localhost:5000/api/values', (apires) => {
const { statusCode } = apires;
const contentType = apires.headers['content-type'];
let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
// Consume response data to free up memory
apires.resume();
return;
}
apires.setEncoding('utf8');
let rawData = '';
apires.on('data', (chunk) => { rawData += chunk; });
apires.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
console.log(parsedData);
titletext=parsedData[1];
wtext=parsedData[0];
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
res.render('index', { title: titletext, data:wtext });
});
module.exports = router;
But it does not seem to be working and titletext and wtest were coming as empty strings. So, I added three breakpoints. One just after the get call, second after get call response comes and the last on the page response render call(res.render) at the very end.
Now when I run, I find that the get call breakpoint gets called,then the page response render call breakpoint gets called and finally the get call response breakpoint gets called, the data comes from the rest api but by then the page render call is already over and so the data from api call does not reach the view.
Any ideas how to solve this is sincerely appreciated
Http request call is async, so if you put res.render at the end of GET handler, it will render empty data before request returns response.
Following the document, you should parse response's body and render page from end event handler, like:
router.get('/', function(req, res, next) {
let titletext = '';
let wtext = '';
http.get('http://localhost:5000/api/values', (apires) => {
const { statusCode } = apires;
const contentType = apires.headers['content-type'];
let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
// Consume response data to free up memory
apires.resume();
return;
}
apires.setEncoding('utf8');
let rawData = '';
apires.on('data', (chunk) => { rawData += chunk; });
apires.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
console.log(parsedData);
titletext=parsedData[1];
wtext=parsedData[0];
// Render page here
res.render('index', { title: titletext, data:wtext });
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
// Not here
});