Twitter Account Activity API in Firebase Function - node.js

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);
}

Related

Cannot set headers after they are sent to the client in stripe

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}`);
}

commerce coinbase wbhook payload error nodejs

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

Why I can not get correct response from api?

I can't get a good answer from my api , for example I try to read "true" or "false" from api to give the authorization for user , but I got just undefined data.
the methods both work prefectly from sending data to verify the user .
I have this api method inside server :
router.get("/sickers/user/login/:mail/:pass", (req, res) => {
//var values = JSON.parse(req.body);
var pass = req.params.pass;
var email = req.params.mail;
//console.log(values);
if (pass !== null || pass !== "") {
try {
con.connect();
con.query("SELECT Password FROM `sickers` WHERE Email='" + email + "'", function(err, rows, field) {
if (err) {
console.log(err);
res.send("an error detected try later");
} else {
try {
if (pass == rows[0].Password) {
res.json({ "result": "true" })
} else {
res.json({ "result": "false" })
}
} catch {
res.json({ "result": "false" })
}
}
});
} catch (e) {
res.send("no data found");
console.log("obj not found");
}
}
con.end();
});
and this call api inside my react app :
submithandler(e) {
e.preventDefault();
const url = 'http://localhost:8000/api/sickers/user/login/'+this.state.email+'/'+this.state.password+'';
const res = fetch(url);
const data = res;
this.setState({result:data});
alert(this.state.result);
}
thanks.
Account for the async nature of the functions you are using. It might look something like this:
const url = 'http://localhost:8000/api/sickers/user/login/'+this.state.email+'/'+this.state.password+'';
// Use .then to call a function AFTER the fetch has completed
fetch(url).then(result => result.json()).then((response) => {
// Use the setState callback to check updated values AFTER they have been updated
this.setState({result: response}, () => {
alert(this.state.result);
});
});
Docs on fetch
Docs on setState

Async await issue in nodejs

I am trying to send messages to mobile numbers using message bird API, i have completed the coding part but its not sending the messages, even i can see i have sent messages and being delivered in my message bird profile. I came to know that this issue can be due to not using async and await. Here is my code,
api.get('/sendmessage', function (req, res) {
var id = req.headers.authorization;
if (req.session.id) {
var userid = req.session.user[0].id;
var username = userInfo.find({ id: userid }, function (err, user) {
if (err) { res.send("New Error: " + err); }
else {
if (!_.isEmpty(user)) {
var contact = user[0].contact;
var messagebird = require('messagebird')('ACCESS_KEY_API'); // Api for testing
var params = {
'originator': 'MessageBird',
'recipients': [
contact
],
'body': 'Hello, world!'
};
messagebird.messages.create(params, function (err, response) {
if (err) {
return console.log("Error sent to Console: " + err);
}
else {
console.log(response);
return res.send(response);
}
});
}
else {
res.send("No Results");
}
}
});
}
});

What can be a better way to handle sending response from controller in nodejs project?

rooms.js -> controller class for rooms endpoint
router.get('/:roomid/fight/verify', function(req, res) {
roomModel.authenticateUserForFight(req.params.roomid, req.query.otp, res);
});
roomModel -> model class for rooms
//authenticate user based on otp provided on client side
exports.authenticateUserForFight = function(roomid, otp, res) {
db.query('select * from room where roomid=?', [roomid], function(error, rows) {
if (rows.length == 0) {
console.log("otp does not exist in db for room:" + roomid);
} else if (rows.length == 1) {
var otpInDb = rows[0].otp.toString();
if (otp == otpInDb) {
console.log("User is authorised");
res.status(200);
res.send("User is authorised");
} else {
console.log("User is unauthorised");
res.status(401);
res.send("User not authorised");
}
}
});
}
This piece of code works fine but is there a better way to send response to client instead of passing res object to model class and setting the status and response message there ? The reason i am passing the res object is because doing res.status and res.send in controller is giving issues as the db call is asynchronous. Suggest some better practices to handle these kind of situtations.
You are right. You should not pass the res object. Its a debugging nightmare if there is more than one place from where the function can exit. Its far better that the subsequent functions return the value and the controller responds to the status.
You can simply create a callback method which will be called once the async db query is completed. Something like this
router.get('/:roomid/fight/verify', function(req, res) {
const callback = (status, message) => {
res.status = status
res.send(message);
}
roomModel.authenticateUserForFight(req.params.roomid, req.query.otp, callback);
});
and the main function can just call this function
//authenticate user based on otp provided on client side
exports.authenticateUserForFight = function(roomid, otp, callback) {
db.query('select * from room where roomid=?', [roomid], function(error, rows) {
if (rows.length == 0) {
console.log("otp does not exist in db for room:" + roomid);
} else if (rows.length == 1) {
var otpInDb = rows[0].otp.toString();
if (otp == otpInDb) {
console.log("User is authorised");
callback(200, 'user authorized');
} else {
console.log("User is unauthorised");
callback(401, 'user not authorized');
}
}
});
}
this is the updated code
if (otp == otpInDb) {
console.log("User is authorised");
res.json({
status:200,
message:"user authorized"
})
} else {
res.json({
status:401,
message:"user not authorized"
})
}
It is always better to send your response in envelope. and I can see you are using String like queries. Use orm wrapper like sequelize to prevent SQL injection attacks

Resources