I am trying to get a response from '/razorpay' route in my index.js file, and use it in displayRazorpay()
. For this, I'm using fetch, but it shows forbidden 403 error. Can someone help out? I have attached my '/razorpay' route, and displayRazorpay() function below. I'm new to node.js, so any help is appreciated!
router.post('/razorpay', async function(req,res,next){
if(!req.session.cart){
return res.redirect('/shopping-cart');
}
var cart = new Cart(req.session.cart);
const payment_capture = 1;
const amount = cart.totalPrice;
const currency = 'INR';
const options = {
amount: amount * 100,
currency,
receipt: shortid.generate(),
payment_capture,
}
try {
const response = await razorpay.orders.create(options);
console.log(response);
res.json({
id: response.id,
currency: response.currency,
amount: response.amount
});
} catch (error) {
console.log(error);
}
});
async function displayRazorpay() {
const data = await fetch('/razorpay', {method:'POST'}).then((t) =>
t.json()
);
console.log(data);
const options = {
key: 'rzp_test_2eJE3rP3gEWqze',
amount: 400,
order_id: data.id,
name: 'Donation',
description: 'Thank you for nothing. Please give us some money',
image: '/images/modiLogo3.png',
handler: function (response) {
alert(response.razorpay_payment_id);
alert(response.razorpay_order_id);
alert(response.razorpay_signature);
},
prefill: {
email: 'sdfdsjfh2#ndsfdf.com',
phone_number: '9899999999'
}
}
const paymentObject = new window.Razorpay(options);
paymentObject.open();
}
This is a problem of CORS. Make sure you enable cors on your server side.
Since you are using express, here's sample code
First install cors: npm install cors
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
Related
For some reason I am getting a 404 error but only on when sending a post request to '/webhook' but I cannot figure out why. the rest of my post's are absolutely fine but I keep getting this message [404] POST http://localhost:3001/webhook [evt_1IzeQ1EUG2WFNVaczcOMJWgu]
Port 3001 is my client and my server is running on port 8080 (firebase emulator). Any idea what I could be doing incorrectly?
index.js
require("dotenv").config();
const functions = require("firebase-functions");
const express = require("express");
const cors = require("cors");
const { buffer } = require('micro');
const admin = require('firebase-admin');
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
const serviceAccount = require("./permissions.json");
const firebaseAdmin = !admin.apps.length ? admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
}, 'firebaseAdmin') : admin.firebaseAdmin();
// api
// app config
const app = express();
// middlewares
app.use(cors({origin: true}));
app.use(express.json());
// api routes
app.get("/", (request, response) => response.status(200).send("hello world"));
app.post("/create-checkout-session", async (request, response) => {
const { cart, email} = request.body;
const transformedItems = cart.map(item => ({
description: item.description === '' ? 'no description' : item.description,
quantity: 1,
price_data: {
currency: 'usd',
unit_amount: item.price * 100,
product_data: {
name: item.title,
},
}
}));
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
shipping_address_collection: {
allowed_countries: ['US']
},
line_items: transformedItems,
mode: 'payment',
success_url: `${process.env.DOMAIN}/confirmation`,
cancel_url: `${process.env.DOMAIN}/sorry`,
metadata: {
email
}
});
response.status(200).json({ id: session.id});
});
const endpointSecret = process.env.STRIPE_SIGNING_SECRET;
const fulfillOrder = async (session) => {
console.log('Fulfilling Booking', session);
return firebaseAdmin
.firestore()
.collection('customers')
.doc(session.metadata.email)
.collection('orders')
.doc(session.id).set({
amount: session.amount_total / 100,
timestamp: admin.firestore.FieldValue.serverTimestamp(),
})
.then(() => {
console.log(`SUCCESS! Order #${session.id} has been added to the database!`);
})
}
app.post("/webhook", async (request, response) => {
const requestBuffer = await buffer(request);
const payload = requestBuffer.toString();
const sig = request.headers("stripe-signature");
let event;
try {
event = stripe.webhooks.constructEvent(payload, sig, endpointSecret);
} catch (err) {
console.log('ERROR!!!', err.message);
return res.status(400).send(`Webhook error: ${err.message}`);
}
if (event.type === 'checkout.session.completed') {
const session = event.data.object;
return fulfillOrder(session)
.then(() => response.status(200))
.catch((err) => response.status(400)
.send(`Webhook error ${err.message}`));
}
});
// listen command
exports.api = functions.https.onRequest(app, firebaseAdmin);
To test Stripe webhooks locally (i.e. on localhost), you need to forward those webhook events to your localhost port. For that you need to install and configure the Stripe CLI. Once installed you can configure it using these commands:
stripe login
stripe listen --forward-to localhost:5001/webhook
// To manually trigger events using CLI
stripe trigger payment_intent.created
Because if you are triggering events from the dashboard they won't reach your localhost.
The port number should be the same as Cloud Functions emulator and the complete URL should match where your function is running. In you case, "http://localhost:5001/piers-laine/us-central1/api/webhook"
I try to post json to Line' messaging api with koa.js and request-promise but got error as attached image :
I'm using heroku with koa.js to connect with Line messaging api.
Here is my code :
const Koa = require('koa');
const Router = require('koa-router');
const logger = require('koa-logger');
const bodyParser = require('koa-bodyparser');
const app = new Koa();
const router = new Router();
const port = process.env.PORT || 4000;
app.use(logger());
app.use(bodyParser());
app.on('error', (err, ctx) => {
console.log('server error', err, ctx)
});
app.use(router.routes());
app.use(router.allowedMethods());
router
.get('/', (ctx, next) => {
console.log(ctx);
ctx.body = ctx;
})
.post('/webhook', async (ctx, next) => {
var reply_Token = ctx.request.body.events[0].replyToken;
console.log('token = ' , ctx.request.body.events[0].replyToken);
var rp_body = JSON.stringify({
replyToken: reply_Token,
messages: [{
type: 'text',
text: 'Hello'
},
{
type: 'text',
text: 'How are you?'
}]
});
var options = {
method: 'POST',
url: 'https://api.line.me/v2/bot/message/reply',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer {xxxxxxxx}'
},
json: true,
body: rp_body
};
var rp = require('request-promise');
rp(options)
.then(function (parsedBody){
console.log('rq success');
})
.catch(function (err) {
console.log('server error', err, ctx);
});
});
app.listen(port);
module.exports = { app }
After try to solving with changing variable but seem doesn't work at all. This is what I try to adapt from using Node.Js to Koa.js.
Solving the problems!, thanks to #num8er for pointing to it.
As the body entity has 'json : true' so the body is already stringify by this. There's no need to do stringify before.
So removing it like :
var rp_body = JSON.stringify({
replyToken: reply_Token,
messages: [{
to
var rp_body = ({
replyToken: reply_Token,
messages: [{
However after pull off stringify from body you might encounter 'Invalid Token' if process api.line.me verification.
It's what it should be, because api.line.me will throw zeros as reply token for verification and Koa.js look at it like an error.
So checking for if token is zeros then send status 200 to complete the verification, otherwise do the POST METHOD if token is not zeros.
if(reply_Token === '00000000000000000000000000000000') {
ctx.status = 200;
} else {
//POST METHOD
}
I have been trying to use mailgun. js to respond to a get request and when I move it out of my routes file and into a controller function, I know I am missing something.
It works fine when I make a request to
const mailgun = require('mailgun.js');
const router = express.Router();
router.get('/', (req, res) => {
const API_KEY = 'secret';
const DOMAIN = 'secretdomain';
const mg= mailgun({ apiKey: API_KEY, domain: DOMAIN });
const data = {
from: 'bob#thebuilder.com',
to: 'barney#rubble.com',
subject: 'Whats up doc',
template: "reqfeedback",
};
mg.messages().send(data, function (error, body) {
if (error) {
console.log(error);
}
console.log(body);
});
});
but when I try to add it to my controller file as a function, I get an unhandled promise TypeError saying mailgun is not a function so I made sure it's wrapped in a try/catch like so...
controller.js
const mongoose = require('mongoose');
const mailgun = require('mailgun.js');
const sendEmail = async(req,res,next) => {
try{
const API_KEY = 'secret';
const DOMAIN = 'secretdomain';
const mg= mailgun({ apiKey: API_KEY, domain: DOMAIN });
const data = {
from: 'bob#thebuilder.com',
to: 'barney#rubble.com',
subject: 'Whats up doc',
template: "reqfeedback",
};
await mg.messages().send(data, function (error, body) {
if (error) {
console.log(error);
}
console.log(body);
});
catch (err) {
const error = new HttpError(
'Something went wrong, could not send email.',
500
);
return next(error);
}
res.status(200).json({ message: 'email sent' });
};
exports.sendEmail = sendEmail;
and I add this route:
routes.js
const controllers = require('../controllers/controllers');
const router = express.Router();
const express = require('express');
router.get('/sendEmail', controllers.sendEmail);
module.exports = router;
But when I send the get request I keep getting the 500 error "message": "Something went wrong, could not request feedback."
Halp pls.
The rest api I use with express js below sends an electronic signature request to the defined user mail. He makes this request with his email address in the json body. The e-mail addresses to be sent may be different. How can I send the email_address and name fields in the opts body in a parametric way to api? The main problem I have is how do I send the parameters of email_address and name to json body parametrically. I don't want to send hard coded.
Express JS API:
const express = require('express');
const router = express.Router();
const hellosign = require('hellosign-sdk')({ key: 'key123' });
const fs = require('fs');
hellosign.account.update({
callback_url: process.env.HOST_URL+'api/callback'
}).then((res) => {
// handle response
console.log("--- sign res ---");
console.log(res);
}).catch((err) => {
// handle error
console.log(err)
});
router.post('/sign',(req,res)=>{
res.send('Sign request is called');
const opts = {
test_mode: 1,
title: 'PDF Sign via Node Server',
subject: 'PDF Sign via Node Server',
message: 'Please sign this pdf.',
signers: [
{
email_address: 'example#gmail.com',
name: 'Mr Okoreni'
}
],
files: ['nda.pdf']
};
hellosign.signatureRequest.send(opts).then((res) => {
// handle response
console.log(res);
}).catch((err) => {
// handle error
console.log(err)
});
});
router.post('/callback',(req,res)=>{
res.send('Hello API Event Received');
console.log('callback request is called');
try{
res.send(res.data);
console.log(res.data);
console.log(res.body);
}catch (e) {
console.log(e)
}
});
router.get('/download/',(req,res)=>{
res.send('download request is called');
try {
console.log('download request is called');
var signatureRequestId = 'sign123';
hellosign.signatureRequest.download(signatureRequestId, { file_type: 'zip' }, (err, res) => {
const file = fs.createWriteStream("./downloads/"+signatureRequestId+"files.zip");
res.pipe(file);
file.on('finish', () => {
file.close();
console.log("finish");
});
});
}catch (e) {
console.log(e);
}
});
router.get('/', (req, res) => {
res.send("Server is listening...")
});
module.exports = router;
Totally depends where you're getting the parameterised fields from
From the request..
const opts = {
test_mode: 1,
title: 'PDF Sign via Node Server',
subject: 'PDF Sign via Node Server',
message: 'Please sign this pdf.',
signers: [
{
email_address: req.email_address,
name: req.name,
},
],
files: ['nda.pdf'],
}
I have been implementing a Next.js app for a side project of mine. It is a basic brochure-style site with a contact form.
The form works perfectly fine when the site is run locally, however I have just published the site to Netlify and now when submitting a form I encounter the following error:
POST https://dux.io/api/form 404
Uncaught (in promise) Error: Request failed with status code 404
at e.exports (contact.js:9)
at e.exports (contact.js:16)
at XMLHttpRequest.d.(/contact/anonymous function) (https://dux.io/_next/static/cFeeqtpSGmy3dLZAZZWRt/pages/contact.js:9:4271)
Any help would be extremely appreciated!
This is my Form Submit function:
async handleSubmit(e) {
e.preventDefault();
const { name, email, option, message } = this.state;
const form = await axios.post('/api/form', {
name,
email,
option,
message
});
this.setState(initialState);}
This is my server.js file:
const express = require('express');
const next = require('next');
const bodyParser = require('body-parser');
const mailer = require('./mailer');
const compression = require('compression');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.use(compression());
server.use(bodyParser.json());
server.post('/api/form', (req, res) => {
const { email = '', name = '', option = '', message = '' } = req.body;
mailer({ email, name, option, text: message })
.then(() => {
console.log('success');
res.send('success');
})
.catch(error => {
console.log('failed', error);
res.send('badddd');
});
});
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(3000, err => {
if (err) throw err;
console.log('> Read on http://localhost:3000');
});
});
It looks like nextjs tries to render the /api/form page and you get a not found with that.
Please make sure you start the server with node server.js instead of next start.
What about try to use full endpoint http://~~~/api/form instead of just /api/form?
Or I think, you can solve this problem if you use process.env
const config = {
endpoint: 'http://localhost:8080/api'
}
if (process.env.NODE_ENV === 'production') {
config.endpoint = 'hostname/api'
}