Twilio: Invalid parameter with Node.js - node.js

I'm trying to use the verify API with twilio. Here is what i have
dotenv.config();
import twilio from "twilio";
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const client = twilio(accountSid, authToken);
try {
let { to } = req.body;
to = String(to).startsWith("+") ? to : "+" + to;
to = String(to).trim().replace(/\s/, ""); // no spaces
console.log(accountSid, to);
const response = await client.verify
.services(accountSid as string)
.verifications.create({
to,
channel: "call", // sms, call, or email
});
return res.status(200).json(response);
} catch (error) {
console.log(error);
}
I'm getting the following error:
{
error: Invalid parameter,
status: 400,
code: 60200,
moreInfo: 'https://www.twilio.com/docs/errors/60200',
details: undefined
}
Here is what my to looks like "+2661890...". What maybe possibly the problem?

I was using the wrong SERVICE_SID i used ACCOUNT_SID instead of SERVICE_SID. I changed my code to:
...
const { sid } = await client.verify.services.create({
friendlyName: "Verification Service",
});
const response = await client.verify.services(sid).verifications.create({
to,
channel: "call", // sms, call, or email
});

Related

Stripe webook signature verification failed using express

Hey stack overflow so I am using webooks with stripe. For some reason I am getting the error "Stripe webook signature verification failed". Here is my source code below. Any ideas on how I can get it working? I know it has something to do with the bodyparser. But I am not able to figure out a workaround to get the stripe webhooks working.
Error Message:
Webhook signature verification failed. 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
require("dotenv").config();
const express = require("express");
var cors = require('cors')
const axios = require("axios");
const bodyParser = require("body-parser");
const Stripe = require('stripe');
const stripe = Stripe('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
const invoiceDescription = require('./constants');
const endpointSecret = "whsec_w5Qipi3Wz0fm8sSCHcJIHwWfobS0kfYe";
const { TOKEN, SERVER_URL, BOTTOKEN } = process.env;
const TELEGRAM_API = `https://api.telegram.org/bot${TOKEN}`;
const URI = `/webhook/${TOKEN}`;
const WEBHOOK_URL = SERVER_URL + URI;
const app = express();
app.use(cors());
app.use(bodyParser.json());
const init = async () => {
const res = await axios.get(`${TELEGRAM_API}/setWebhook?url=${WEBHOOK_URL}`);
console.log(res.data);
};
app.post('/webhook', express.raw({type: 'application/json'}), (request, response) => {
let event = request.body;
// Only verify the event if you have an endpoint secret defined.
// Otherwise use the basic event deserialized with JSON.parse
if (endpointSecret) {
// Get the signature sent by Stripe
console.log(request.headers)
const signature = request.headers['stripe-signature'];
try {
event = stripe.webhooks.constructEvent(
request.body,
signature,
endpointSecret
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`, err.message);
return response.sendStatus(400);
}
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log(`PaymentIntent for ${paymentIntent.amount} was successful!`);
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
console.log('payment intent is', paymentIntent)
break;
case 'payment_method.attached':
const paymentMethod = event.data.object;
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
console.log('payment method is', paymentMethod)
break;
default:
// Unexpected event type
console.log(`Unhandled event type ${event.type}.`);
}
// Return a 200 response to acknowledge receipt of the event
response.send();
});
app.post(URI, async (req, res) => {
let text = "", chatId = "", userObjectForTable = {};
if(req.body.message?.chat?.id && req.body.message?.text && req.body.message?.text === "Start"){
chatId = req.body.message.chat.id;
text = invoiceDescription;
const message = await axios.post(`${TELEGRAM_API}/sendMessage`, {
chat_id: chatId,
text: text,
reply_markup: {
inline_keyboard: [[{
text: 'Pay $65.00',
web_app: {url: 'https://buy.stripe.com/test_14kbKj3Gd0AGeRi7ss' }
}]]
}
});
}
return res.send();
});
app.listen(process.env.PORT || 5050, async () => {
console.log("🚀 app running on port", process.env.PORT || 5050);
await init();
});

SlackBot repeat the event without control

I am trying to create a bot in Slack called "Chochon", the problem is that when I receive the event "app_mention", chochon responds more than once several times in a row, instead of sending 1 message and stopping until they mention it again.
This is my code, chochon function:
socketModeClient.on('app_mention', async ({ event }) => {
try {
console.log(event);
let userBox = await Chochon.users.info({ user: event.user });
let userProfile = userBox.user.profile;
console.log(cli.green(`Event received : [ ${event.type} ] from [ ${userProfile.display_name} ]`));
// Respond to the event
Chochon.chat.postMessage({
channel: event.channel,
text: `Hello <#${event.user}>, I'm Chochon!, I'm a bot that can help you to manage your team.`
});
} catch (error) {
console.error(error);
}
});
The slack client:
Full code:
// Dependencies :
const dotenv = require('dotenv').config();
const path = require('path');
const cli = require('cli-color');
// Web client [CLI]
const { WebClient } = require('#slack/web-api');
const Chochon = new WebClient(process.env.SLACK_BOT_TOKEN.trim());
// Socket IO
const { SocketModeClient } = require('#slack/socket-mode');
const appToken = process.env.SLACK_APP_TOKEN;
const socketModeClient = new SocketModeClient({ appToken });
socketModeClient.start();
// Internal functions
//const eventManager = require(path.resolve(__dirname, './utils/events/manager'));
socketModeClient.on('app_mention', async ({ event }) => {
try {
console.log(event);
let userBox = await Chochon.users.info({ user: event.user });
let userProfile = userBox.user.profile;
console.log(cli.green(`Event received : [ ${event.type} ] from [ ${userProfile.display_name} ]`));
// Respond to the event
Chochon.chat.postMessage({
channel: event.channel,
text: `Hello <#${event.user}>, I'm Chochon!, I'm a bot that can help you to manage your team.`
});
} catch (error) {
console.error(error);
}
});
socketModeClient.on('slash_commands', async ({ body, ack }) => {
if (body.command === "/ping") {
console.log(cli.green(`Event received : [ ${body.command} ]`));
await ack({"text": "I got it, pong!"});
}
});

Error sending notification through firebase function flutter

I am trying to send push notification to the user whenever the new event is added into the firestore of the firebase.
Whenever I do so it returns me the error saying Error sending notification
node.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().functions);
var newData;
exports.messageTrigger = functions.firestore.document('Messages/{messageId}').onCreate(async(snapshot, context)=> {
if(snapshot.empty){
console.log('No Devices');
return;
}
var tokens = ['mobile-token'];
newData = snapshot.data();
var payload = {
notification : {title: 'Push Title', body: 'Push body', sound: 'default'},
data: {click_action: 'FLUTTER_NOTIFICATION_CLICK', message: newData.message},
};
try{
const response = await admin.messaging.sendToDevice(tokens, payload);
console.log('Notification sent successfully');
} catch (err) {
console.log('Error sending notifications');
}
});
I am passing the mobile token in place of mobile-token
SOLUTION
Changing admin.messaging.sendToDevice() to
const response = await admin.messaging().sendToDevice(tokens, payload)
As admin.messaging.sendToDevice() is not a method

How to deal with the different type of errors that returns from the cloud function?

I have written the cloud functions which sends the response either with the statuscode 200 or 400 but sometimes I am getting this error
Function execution took 219 ms, finished with status: 'connection error'
Error: function crashed out of request scope Function invocation was interrupted.
So the problem is I need to know send this error message with some statuscode as the response of the cloud function.
const functions = require('firebase-functions');
const dialogflow = require('dialogflow');
const admin = require('firebase-admin');
const Firestore = require('#google-cloud/firestore');
const firestore = new Firestore();
admin.initializeApp();
var db = admin.firestore();
const {WebhookClient} = require('dialogflow-fulfillment');
var UID = new Object();
exports.fulfillmenttext = functions.https.onRequest((req,res) =>{
const answer1 = req.body.Text;
const uid = answer1.substring(0,28);
const answer = answer1.substring(28);
const sessionId = uid;
var count,questvalue;
const promise = db.collection("***").doc('***').collection("**").doc("uid").get();
promise.then(doc => {
snapshot.forEach(function(doc) {
if (doc.exists) {
count = doc.data().count;
if(count == 1){
var updatequest = title[questvalue];
res.status(200).send({"question":updatequest,"question_number":questvalue});
return;
}
else{
runSample();
}
}
else {
console.log("No such document!");
}
});
}).catch(function(error) {
console.log("Error getting document:", error);
});
async function runSample() {
const languageCode = 'en-US';
const projectId = 'xxxxxxx';
const credentials = {
client_email: 'xxxxxxx',
private_key:
'xxxxxxx',
};
//Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient({
projectId,
credentials,
});
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
//session: context1,
session: sessionPath,
queryInput: {
text: {
text: answer,
languageCode,
},
},
};
const responses = await sessionClient.detectIntent(request);
const result = responses[0].queryResult;
let action = result.action;
if (result.intent) {
const question = result.fulfillmentText;
console.log("question is",question);
const actionHandlers = {
'early': () => {
console.log('earlyaction1', action);
let name1 = JSON.stringify(result.parameters.fields.Name.stringValue);
name1 = name1.toString().replace(/"/g,"");
var data1 = {
Name: name1
};
var setDoc1 = admin.firestore().collection('**').doc('uid').collection("***").doc('uid').collection('**').doc('**').update(data1);
},
};
if (action === 'early') {
console.log('1');
actionHandlers[action]();
}
res.status(200).send({"question":result.fulfillmentText,"action":action,"question_number":title.indexOf(question)});
} else {
console.log(` No intent matched.`);
res.status(400).send({"action":"empty"});
}
}
});
That message is telling you that you have some async code that was still running after the function terminated normally by sending a response to the client. That bit of async code crashed. Since the function already terminated by sending a response, there's nothing you can do to send another response. There can only be one response per function invocation.
What you'll have to do is review your code and make sure you're 1) handling promises correctly and 2) not intentionally trying to leave any work going after sending the response, since Cloud Functions does not support that.

Firebase Node.JS Admin SDK send verification email

I am using the sdk to create a user and a db entry for the user which all works perfectly. Upon creation of the database entry I call a function to sendEmailVerification() but I am guessing this is a client side function as it returns null when being called.
What is the process to send the verify email directly from the admin sdk (if even possible). Currently what I do is send some JSON back to the client to say if the verification email sent successfully or not. But calling the function does not work so it doesn't get that far. Here is my function within node.
function verifiyEmail(email, res) {
var user = admin.auth().currentUser;
user.sendEmailVerification().then(function() {
// Email sent.
var jsonResponse = {
status: 'success',
alertText: '1',
email: email
}
res.send(jsonResponse);
}, function(error) {
// An error happened.
var jsonResponse = {
status: 'success',
alertText: '0',
email: email
}
res.send(jsonResponse);
});
}
UPDATE
I am guessing this isn't possible so I generate a custom token in node and send that back to the client. I then use the token I get back to try and sign the user in by calling the below however the signInWithCustomToken() fuction doesnt get called. Heres my code am I missing something. Seems like a lot of work just to send out the verification email!
function signInUserWithToken(token) {
firebase.auth().signInWithCustomToken(token).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode);
console.log(errorMessage);
verifiyEmail();
});
}
UPDATE 2
I scraped the token idea. All i do now is use the onAuthStateChanged() function and handle the email verification there in the client implementation. Its not perfect as this method gets called several times. However adding a flag seems to do the trick. Like the below.
function authListenerContractor() {
// Listening for auth state changes.
$('#not-verified').css('display','none');
var flag = true;
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is verified.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
console.log("Email Verified?: " + emailVerified);
if(emailVerified) {
window.location.href = "http://www.my-redirect-url.com";
} else {
if (flag == true) {
$('#not-verified').css('display','inherit');
verifiyEmail();
flag = false;
}
}
} else {
console.log("User is signed out.");
}
});
}
function verifiyEmail() {
var user = firebase.auth().currentUser;
user.sendEmailVerification().then(function() {
// Email sent.
console.log("Verification email sent");
$('#not-verified').text('**Email verification sent. Please check your email now!**');
}, function(error) {
// An error happened.
console.log("Email verification not sent. An error has occurred! >>" + error);
});
}
This is a classic case to use Firebase Cloud Functions
Sending Welcome Mail Example
const functions = require('firebase-functions');
const nodemailer = require('nodemailer');
const gmailEmail = encodeURIComponent(functions.config().gmail.email);
const gmailPassword = encodeURIComponent(functions.config().gmail.password);
const mailTransport = nodemailer.createTransport(
`smtps://${gmailEmail}:${gmailPassword}#smtp.gmail.com`);
const APP_NAME = 'My App';
exports.sendWelcomeEmail = functions.auth.user().onCreate(event => {
const user = event.data; // The Firebase user.
const email = user.email; // The email of the user.
const displayName = user.displayName; // The display name of the user.
return sendWelcomeEmail(email, displayName);
});
function sendWelcomeEmail(email, displayName) {
const mailOptions = {
from: `${APP_NAME} <noreply#firebase.com>`,
to: email
};
mailOptions.subject = `Welcome to ${APP_NAME}!`;
mailOptions.text = `Hey ${displayName || ''}! Welcome to ${APP_NAME}. I hope you will enjoy our service.`;
return mailTransport.sendMail(mailOptions).then(() => {
console.log('New welcome email sent to:', email);
});
}
Check this Link for More Info , used these functions to trigger a mail in this very app
UPDATE
const functions = require('firebase-functions');
const nodemailer = require('nodemailer');
const mailTransport = nodemailer.createTransport(
`smtps://emailid:password#smtp.gmail.com`);
const APP_NAME = 'My App';
exports.sendPageCountEmail = functions.database.ref('/yournode').onWrite(event => { // here we are specifiying the node where data is created
const data = event.data;
return sendEmail('emailid',data);
});
// Sends a welcome email to the given user.
function sendEmail(email,body) {
const mailOptions = {
from:`${APP_NAME}noreply#firebase.com`,
to: email
};
mailOptions.subject = `Welcome to ${APP_NAME}!`;
mailOptions.text = `Welcome to ${APP_NAME}.\n
return mailTransport.sendMail(mailOptions).then(() => {
console.log('New welcome email sent to:', email);
});
}

Resources