I tried integrating Stripe into my React app using the official doc at https://stripe.com/docs/recipes/elements-react. If you could go through this doc, you'll find out they're using a static value as amount (2000).
// server.js
const app = require("express")();
const stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
app.use(require("body-parser").text());
app.post("/charge", async (req, res) => {
try {
let {status} = await stripe.charges.create({
amount: 2000,
currency: "usd",
description: "An example charge",
source: req.body
});
res.json({status});
} catch (err) {
res.status(500).end();
}
});
The post API from frontend using fetch is:
async submit(ev) {
let {token} = await this.props.stripe.createToken({name: "Name"});
let response = await fetch("/charge", {
method: "POST",
headers: {"Content-Type": "text/plain"},
body: token.id
});
if (response.ok) console.log("Purchase Complete!")
}
Here, they're sending the token ID and referencing it in the backend as source:req.body.
Now I have tried to send amount from the frontend through the POST request as follows:
body:{
amount: 2000,
tokenId: token.Id
}
and then referencing it in backend as
...
amount: req.body.amount,
source: req.body.tokenid
...
It doesn't work. And consoling both returns undefined
I have tried many things like removing content-type header and pretty little things. Someone pointed out that I should change content-type to application/json and I've thought of setting
app.use(require("body-parser").text()) to app.use(require("body-parser").json()) but decided to consult you guys first.
If I understand you correctly, you want to post a json from client to express server. If so:
Client
fetch({
method: 'POST',
body: JSON.stringify({
amount: 2000,
tokenId: token.Id
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
Server
const app = express();
// if express >= 4
app.use(express.json());
app.post("/charge", async (req, res) => {
console.log(req.body);
});
Any by the way tokenId !== tokenid (in req.body.tokenid)
Related
I'm working through this tutorial on creating an app that uses the Spotify API. Everything was going great until I got to the callback portion of authenticating using the authentication code flow.
(I do have my callback URL registered in my Spotify app.)
As far as I can tell, my code matches the callback route that this tutorial and others use. Significantly, the http library is axios. Here's the callback method:
app.get("/callback", (req, res) => {
const code = req.query.code || null;
const usp = new URLSearchParams({
code: code,
redirect_uri: REDIRECT_URI,
grant_type: "authorization_code",
});
axios({
method: "post",
url: "https://accounts.spotify.com/api/token",
data: usp,
headers: {
"content-type": "application/x-www-form-urlencoded",
Authorization: `Basic ${new Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString("base64")}`,
},
})
.then(response => {
console.log(response.status); // logs 200
console.log(response.data); // logs encoded strings
if (response.status === 200) {
res.send(JSON.stringify(response.data))
} else {
res.send(response);
}
})
.catch((error) => {
res.send(error);
});
Though the response code is 200, here's a sample of what is getting returned in response.data: "\u001f�\b\u0000\u0000\u0000\u0000\u0000\u0000\u0003E�˒�0\u0000Ee�uS\u0015��\u000e�(\b\u0012h\u0005tC%\u0010\u0014T\u001e�����0��^:���p\u0014Ѻ\u000e��Is�7�:��\u0015l��ᑰ�g�����\u0"
It looks like it's encoded, but I don't know how (I tried base-64 unencoding) or why it isn't just coming back as regular JSON. This isn't just preventing me logging it to the console - I also can't access the fields I expect there to be in the response body, like access_token. Is there some argument I can pass to axios to say 'this should be json?'
Interestingly, if I use the npm 'request' package instead of axios, and pass the 'json: true' argument to it, I'm getting a valid token that I can print out and view as a regular old string. Below is code that works. But I'd really like to understand why my axios method doesn't.
app.get('/callback', function(req, res) {
// your application requests refresh and access tokens
// after checking the state parameter
const code = req.query.code || null;
const state = req.query.state || null;
const storedState = req.cookies ? req.cookies[stateKey] : null;
res.clearCookie(stateKey);
const authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: REDIRECT_URI,
grant_type: 'authorization_code',
},
headers: {
Authorization: `Basic ${new Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64')}`,
},
json: true,
};
request.post(authOptions, function (error, response, body) {
if (!error && response.statusCode === 200) {
const access_token = body.access_token;
const refresh_token = body.refresh_token;
var options = {
url: 'https://api.spotify.com/v1/me',
headers: { Authorization: 'Bearer ' + access_token },
json: true,
};
// use the access token to access the Spotify Web API
request.get(options, function(error, response, body) {
console.log(body);
});
// we can also pass the token to the browser to make requests from there
res.redirect('/#' + querystring.stringify({
access_token: access_token,
refresh_token: refresh_token,
}));
} else {
res.redirect(`/#${querystring.stringify({ error: 'invalid_token' })}`);
}
});
});
You need to add Accept-Encoding with application/json in axios.post header.
The default of it is gzip
headers: {
"content-type": "application/x-www-form-urlencoded",
'Accept-Encoding': 'application/json'
Authorization: `Basic ${new Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString("base64")}`,
}
I am implementing stripe payment in my react native app and created express api to get clientSecret Intent. So I want to make payment of the amount which I send from my api to api. But in api, I am getting nothing in the request body.
This is how I am calling my Apis
let data={totalAmount:amount, name:'XYZ_Name'}
fetch('http://10.0.2.2:3500/create-payment-intent', {
method: 'POST',
headers: { "Content-Type": "application/json" },
// "Content-Type" : "application/json",
body:data,
})
And this is my express api;
const app = express();
app.use(express.json());
app.use(
express.urlencoded({
extended: true,
})
);
app.post('/create-payment-intent', async (req,res)=>{
console.log('api Data',req.body.amount);
const paymentIntent = await stripe.paymentIntents.create({
amount:5000, //$50
currency:'gbp',
});
res.send({
clientSecret: paymentIntent.client_secret,
paymentIntent,
})
})
app.listen(3500,()=>{console.log('API Running!')});
I see two issues with the frontend code you shared.
First, you should replace totalAmount: amount by amount: amount, since the backend code is using req.body.amount.
Second, you can't directly send a JavaScript object using fetch, you need to convert it into a string with JSON.stringify(data).
With these two fixes, your frontend code should look like this:
let data= { amount: amount, name: 'XYZ_Name' };
fetch('http://10.0.2.2:3500/create-payment-intent', {
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
Note that I wouldn't recommend to pass the amount from the frontend to the backend, since a malicious user could directly change the amount in their browser.
Your data must be stringified
let data = { totalAmount:amount, name:'XYZ_Name' }
fetch('http://10.0.2.2:3500/create-payment-intent', {
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
})
I am trying to send a bas64 encoded image to my express server and parse it there to save it to disk. Id like to implement this with a simple http post request but couldn't get it to work. My first implementation utilized a websocket server and worked well:
Client:
const object = JSON.stringify({
action: "add_image",
data: dataUrl,
})
ws.send(object)
Server:
ws.on("message", (message) => {
const req = JSON.parse(message);
fs.writeFile(
"path/to/file.png",
data.split(";base64,").pop(),
{ encoding: "base64" },
(err) => err && console.log(err)
)
}
This is my trying to get the same result with an http request.
Client:
const object = JSON.stringify({
action: "add_image",
data: dataUrl,
})
fetch("http://localhost:3001/add_image", {
method: "POST",
headers: new Headers({
Origin: window.origin,
Accept: "image/png",
"Content-Type": "image/png",
}),
mode: "cors",
body: object,
})
Server:
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.post("/add_image", function (req, res) {
console.log(req.body);
});
Unfortunately, req.body always logs an empty object.
I am not quite sure what I am lacking. Any help would be greatly appreciated.
I found the answer in this article. I needed to combine all individual chunks of the request and then use the data once the process is complete.
app.post("/add_image", function (req, res) {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
console.log(JSON.parse(body));
res.end('ok');
});
});
It says me syntax error: JSON Parse error. unrecognized token '<'
Iam using Fetch to do the request.It let me send short base64 strings i tried so what can i do?
This is my call to the api:
export function uploadPost(post) {
let data = {
body: post.body,
picture: post.picture,
type: post.type,
user: {
_id: post.user._id,
name: post.user.name,
picture: post.user.picture
}
}
var headers = {
'Content-Type': 'application/json',
'Access-Control-Origin': '*'
}
return fetch(URL + "/uploadPost", {
method: "post",
headers: headers,
body: JSON.stringify(data)
})
.then(response => Promise.resolve(response.json()))
.catch(err => {
return Promise.reject(err);
})
}
I finally solved it. The problem was that the response was returning a 413 status and I found out that means payload too large. So I added to my node js express server this lines:
var app = express();
//after
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
I am using express to return an api response retrieved via a request call.
router.post('/', function(req, res){
var options = {
...
}
rp(options)
.then(function (parsedBody) {
console.log(parsedBody);
res.json(parsedBody)
})
The console log displays the expected payload, also when I use Postman I also see the expected payload.
When though my client app gets the response it is:
Response {type: "cors", url: "http://localhost:3001/api/", redirected: false, status: 200, ok: true, …}
Ive tried adding CORS middleware:
app.use(function(request, response, next) {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers",
"Origin, X-Rquested-With, Content-Type, Accept");
next();
});
My client is a very simple react app using fetch:
fetch('http://localhost:3001/api/', {
method: 'POST',
dataType: 'JSON',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: data,
}).then((response) => {
console.log(response);
}).catch((response) => {
console.log('Error');
});
My react app is localhost:3000 and the express api localhost:3001, the expected payload is a very simple object...
{
athlete: {
firstname: "Matt"
...
}
}
How can I just forward on the api request response to the clients fetch success method?
The problem is not CORS related, the response within the react app needed parsing as json:
.then((response) => {
console.log(response.json());
})