twilio isn't sending sms nodejs - node.js

I use twilio to send sms after a order is placed, but it isn't sending any sms and also not console logging anything.
Code: npm i twilio
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const client = require("twilio")(accountSid, authToken);
exports.createOrder = (req, res) => {
const { orders, status, details } = req.body;
const order = new Order({
orders: orders,
status: status,
details: details,
});
order.save((error, order) => {
if (error) return res.status(400).json(error);
if (order) {
// if (res.status === 201) {
client.messages
.create({
body: "This is the ship that made the Kessel Run in fourteen parsecs?",
from: "+xxxxxxxxx",
to: "+xxxxxxxxxx",
})
.then((message) => console.log(message.sid));
// }
return res.status(201).json({ order });
}
});
};
LINK TO DOC (where I took the code) : https://www.twilio.com/docs/sms/quickstart/node

Twilio developer evangelist here.
There is likely an issue in sending your message, but the code you have is dropping errors, so you can't see what is going on. Try updating it to this:
client.messages
.create({
body: "This is the ship that made the Kessel Run in fourteen parsecs?",
from: "+xxxxxxxxx",
to: "+xxxxxxxxxx",
})
.then((message) => console.log(message.sid))
.catch(error => console.error(error));
Once you see what the error is, you will be able to fix it. My guess is that you have either configured your Account Sid and Auth Token incorrectly, or you are using a trial account and trying to send a message to a number you haven't verified yet, or you are trying to send a message to a country that isn't enabled.

Related

When I try to run a Post User Registration script in Auth0 it gives "Error! API Error. Please contact support if the problem persists" error

I am trying to use Auth0's actions for post user registration. When I try to test it via UI, it gives me an error like "Error! API Error. Please contact support if the problem persists" and in the console it only writes "Error: {}". The script I wrote for this action looks something like this:
const https = require('https');
const jsonwebtoken = require('jsonwebtoken');
/**
* #param {Event} event - Details about registration event.
*/
exports.onExecutePostUserRegistration = async (event) => {
const TOKEN_SIGNING_KEY = event.secrets.signingKey
const TOKEN_EXPIRATION_IN_SECONDS = 10
const payload = {
email: event.user.email,
name: event.user.given_name,
surname: event.user.family_name
};
const token = jsonwebtoken.sign(payload, TOKEN_SIGNING_KEY,
{ subject: "postUserRegistration",
expiresIn: TOKEN_EXPIRATION_IN_SECONDS });
console.log("Starting post user registration operations for user with email: ", payload.email);
return new Promise((resolve, reject) => {
const request = https.request(url, options,
(res) => {
if (res.statusCode === 200) {
resolve({statusCode: res.statusCode, headers: res.headers})
} else {
reject({
headers: res.headers,
statusCode: res.statusCode
})
}
res.on('error', reject);
});
request.on("error", function (e) {
console.error(e);
reject({message: {e}});
});
request.on("timeout", function () {
reject({message: "request timeout"});
})
request.end();
});
}
Can you help me about what exactly causes this problem?
In order to understand this problem I tried to assign the Promise to a variable and then see what it returned. The funny part was that it was "pending". It couldn't be "pending" in any way, because it everything was true it would be "resolved", else "rejected" and if there is a timeout/error from the request it would be "rejected".
It turns out that Auth0 has some limitations for actions and the endpoint called was stuck to our firewall which caused a timeout in Auth0 before an HTTPS timeout. As the request was broken halfway, it stayed as "pending".

Checkout flow: how should I process a new order?

I'm trying to build an App which allows the customer to download a custom document after his order (so, the product I'm selling it's a digital custom document in pdf).
I'm trying to build that using React for the frontend, Node and Express for the backend, and PayPal Express Checkout (full-stack implementation) as payment.
What is not clear to me is what steps I should take to process an order.
I'm a this point:
Once customer clicks on PayPal button on client side it starts a call on http://localhost/api/paypal/orders endpoint which create the order on the Paypal side and return the PayPal order ID (e.g. id12345)
After the customer approves the payment on the PayPal popup, the client starts a call on http://localhost/api/paypal/orders/id12345/capture endpoint
then? What other endpoints should I crete on the server and what they should return? Maybe... 1 for save the actual store order on my MongoDB and the transaction details, 1 for create the invoice for the order, 1 for allowing the product download ???
Could you please clarify what steps I need to take, what are the endpoints I should create, and what each endpoints should return?
Maybe something like this?
You're trying to do too many things in too many routes. just create a route called something like process-order then you could have an async controller of that route which would contain separate functions for
Storing the order details in mongodb.
Create an invoice
Send a token that allows access to download page.
first , just await the function to complete then call the next.
exports.processOrder = async (req, res, next) => {
try {
const newOrder = await Order.create({
order: req.params.id,
details: req.body.details
})
const createInvoice = () => {
return newOrder._id;
}
const invoice = createInvoice();
const token = jwt.sign(
{
invoiceId = newOrder._id,
},
process.env.JWT_SECRET,
{
expiresIn: '24h'
}
);
return res.status(200).json({status: 'success', message: 'you have 24 hours to download your digital goods', token})
} catch (error) {
res.status(500).send(error)
}
}
This is a very basic idea, but basically store all of your info in one controller, then send a token with the id of the invoice, then when they go to download the book you would have a route where you verify the token. If it succeeds then the book is sent. like this:
app.use(
'/book-download',
expressJwt({ secret: process.env.JWT_SECRET, algorithms: ['HS256'] })
);
app.get('/book-download/success', async (req, res) => {
try{
const invoiceId = req.user.invoiceId;
const invoice = await Invoice.find({_id: invoiceId})
if (invoice) {
return res.status(200).json({status: 'success', message: 'congratulations on your new download', data: {E-book})
} else {
return.res.status(404).json({status: 'fail', message: 'could not find an invoice with that ID'})
} catch (error) {
return res.send(error)
}
});
You can choose to send the pdf via express, or you can allow them to enter a certain part of the website if the return is valid. There you go, that's an idea.
In Express check out, you need to define success / cancel handler
Ref here : https://www.section.io/engineering-education/nodejs-paypal-checkout/
In the success handler, based on the returned URI => you will get a Payer ID and payment ID. Based on that retrieve the transactio information (that internally contains yours order ID). Update your Order id as scucess / cancelled based on the paypal response.
app.get('/success', (req, res) => {
const payerId = req.query.PayerID;
const paymentId = req.query.paymentId;
const execute_payment_json = {
"payer_id": payerId,
"transactions": [{
"amount": {
"currency": "USD",
"total": "25.00"
}
}]
};
// Obtains the transaction details from paypal
paypal.payment.execute(paymentId, execute_payment_json, function (error, payment) {
//When error occurs when due to non-existent transaction, throw an error else log the transaction details in the console then send a Success string reposponse to the user.
if (error) {
console.log(error.response);
throw error;
} else {
console.log(JSON.stringify(payment));
res.send('Success');
}
});
});

Stripe Webhook Returning Error 401 and Success

I have a checkout session:
app.post("/create-checkout-session", async (req, res) => {
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
line_items: converted_items,
mode: "payment",
success_url: process.env.URL + "/order-success.html",
cancel_url: process.env.URL + `/order-page.html`,
billing_address_collection: 'required',
});
res.json({ id: session.id, order: req.body });
});
And I would like to set up a webhook so that after a payment is successfully made, it collects the data from the customer (name, address, products purchased)
I copied this right from the webhook docs:
const fulfillOrder = (session) => {
// TODO: fill me in
console.log("Fulfilling order", session);
}
app.post('/webhook', bodyParser.raw({ type: 'application/json' }), (request, response) => {
const payload = request.body;
const sig = request.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(payload, sig, endpointSecret);
} catch (err) {
return response.status(400).send(`Webhook Error: ${err.message}`);
}
console.log(event.type)
// Handle the checkout.session.completed event
if (event.type === 'checkout.session.completed') {
const session = event.data.object;
console.log("did order")
// Fulfill the purchase...
fulfillOrder(session);
}
response.status(200);
});
How I am setting it up is I am first running my server on localhost and then I am running the testing webhook command from the terminal
stripe listen --forward-to localhost:3000/webhook --events=checkout.session.completed
When I make a payment, it shows me these messages in the terminal:
It looks like you've made some modifications to that webhook handler code from the docs. If you're using Checkout and following the docs, what made you switch the code to look for charge.succeeded?
You should add some logging to figure out why your server is returning 400, but most likely the verification is failing in constructEvent. The snippet you've shared doesn't show you setting endpointSecret, but you need to update the value using the secret shown to you when you run stripe listen.
You should review the Checkout fulfillment docs and focus on checkout.session.completed events. You can modify your CLI command to listen to online these events:
stripe listen --forward-to localhost:3000/webhook --events=checkout.session.completed
then your handler would look like the docs and you can implement fulfillOrder to meet your needs. If you want the details you listed, then you will need to retrieve the session with expansion to include the line items and payment details:
const session = await stripe.checkout.sessions.retrieve(
'cs_test_123',
{
expand: ['line_items', 'payment_intent.payment_method']
},
);
Then session.line_items will be what you created and the name, address and email will be on session.payment_intent.payment_method.billing_details.
Updated to suggest removing signature verification temporarily to diagnose:
The 400 errors suggest your server is returning an error, most likely as a result of signature verification. I recommend testing a basic endpoint without verification following this example, to ensure everything else is working as intended. When that is settled, re-adding signature verification is strongly recommended.

Twilio Check the Verification Token API+postman timeout

I am setting up phone authentication with Twilio, using nodejs....All is working as expected, except when verifying the token. Below is the function which I am using:
verifyPhone: function (req, res) {
client.verify.services('VAxxxxxxxxxxxxxxxx')
.verificationChecks
.create({ to: '+15017122661', code: '123456' })
.then(function (err, verification_check) {
if (err) {
res.status(500).send(err);
} else if (verification_check ==='approved') {
res.status(200).send('Account Verified');
}
})
}
I am checking the endpoint in postman, and it is timing out with no response.
When, I checked in twilio portal, the number status changed to approved.
Any idea why the response is not showing up.
Btw, I turned off SSL certificate
Thanks,
The Twilio Function JavaScript below works for me.
Since Verify v2 is relatively new, make sure your Twilio Helper library is up to date, https://github.com/twilio/twilio-node/releases.
Example to execute function (I have Check for valid Twilio signature turned off for my Twilio function to demo this):
(Example URL to Run Function):
https://mango-abcdef-1234.twil.io/v2start?phoneNumber=%2b15555551234&code=720732
exports.handler = function(context, event, callback) {
const client = context.getTwilioClient();
const code = event.code;
let phoneNumber = event.phoneNumber;
client.verify.services('VAxxxxxxxxxxxxxxxx')
.verificationChecks
.create({to: phoneNumber, code: code})
.then(verification_check => {
console.log(`***VERIFICATION STATUS***: ${verification_check.status}`);
callback(null, `${verification_check.status}`);
})
.catch(err => {
console.log(err);
callback();
});
};
Also recent blog on this topic.
Serverless Phone Verification with Twilio Verify and Twilio Functions

Unable to send email using MailGun Node API

When trying to send a simple test message via mailgun using their Node api I don't get any errors, but I also am not receiving emails nor am I seeing any response in the mailgun logs.
Here is the code I am using ...
const mailgun = require('mailgun-js')({
apiKey: 'XXXXXXXXXX',
domain: 'https://api.mailgun.net/v3/XXXXXXXXX'
})
async function sendInvite() {
var email = process.argv[process.argv.length - 1]
const data = {
from: 'support#acme.com',
to: email,
subject: 'Welcome!',
html: '<p>Welcome!</p><p>You are very special!</p>'
}
return new Promise((resolve, reject) => {
mailgun.messages().send(data, (error, body) => {
if (error) {
console.error(error)
reject(error)
return
}
console.log(`Invite sent to ${email}`)
console.log(data)
console.log(body)
resolve();
})
})
}
sendInvite().then(() => console.log('Done')).catch((err) => console.error(err))
I discovered that the problem I had was in the format of the domain I was passing into mailgun.
Before I had the following :
const mailgun = require('mailgun-js')({
apiKey: 'XXXXXXXXXX',
domain: 'https://api.mailgun.net/v3/XXXXXXXXX'
})
The problem is that the value for domain should not include the https://api.mailgun.net/v3/ portion of the URL. Instead it should ONLY have your domain, e.g. mail.mydomain.com
Did you attach your credit card to mailGun account? Or if you just need to test your logic, in your account settings you should confirm any email address, which will get emails from mailgun
https://wordpress.org/support/topic/mailgun-http-api-test-failure-status-free-accounts-are-for-test-purposes-only/

Resources