I am making a test e-commerce sight to learn nextjs. I am trying to implement the checkout through stripe and I have it working if all of the information is static. when I make any of the information set to a variable it stops working and tells me that I am not passing any values into my variables. to test this I am making all of my data that needs to be passed, static data except for one which is when I get the error that I am not passing in information properly
obviously I am not sending the data to the api correctly. I think that my code looks just like the guides and docs so I am stuck. any help would be greatly appreciated. here is the error message that I get:
"Missing required param: line_items[0][price_data][product_data][name]."
even if I change the state variable 'title' to a single value instead of an array, and in the updateState function settitle("title") I still get the same error
here is the front end code where I try to send the data to the api endpoint:
basket is an array of objects containing all of the products that the user has chosen.
const [id, setId] = useState([]);
const [price, setprice] = useState([]);
const [description, setdescription] = useState([]);
const [title, settitle] = useState([]);
const updateState = () => {
basket.forEach(element => {
setId([...id, element.id]);
setdescription([...description, element.description]);
setprice([...price, element.price]);
settitle([...title, basket.title]);
});
console.log(id);
console.log(description);
console.log(price);
console.log(title);
}
//send data to the api
const postData = async () => {
const response = await fetch("/api/checkout_sessions", {
method: "POST",
body: JSON.stringify(
id,
price,
description,
title,
),
});
return response.json();
};
return (
<form action="/api/checkout_sessions" method="POST">
<button
type="submit"
role="link"
className="button"
onClick={() => {
updateState;
postData;
}}
>
proceed to checkout
</button>
</form>
)}
here is the api code where I try to get that data and use it which is not working how I expect:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
export default async function handler(req, res) {
// var priceVariable ='price_1MB8P4FqoomU2P4qrVmtxCvp';
if (req.method === 'POST') {
const items = req.body.id
const amount = req.body.price
const description = req.body.description
const title = req.body.title
try {
// Create Checkout Sessions from body params.
const session = await stripe.checkout.sessions.create({
// shipping_options: ["shr_1MBn0HFqoomU2P4qZk4vqOQ3"],
shipping_address_collection: {
allowed_countries: ["US", "CA", "GB"],
},
line_items:[{
price_data: {
unit_amount: 1000,
currency: 'usd',
product_data: {
name: title,
description: "description",
},
},
quantity: 1,
}],
mode: 'payment',
success_url: `${req.headers.origin}/?success=true`,
cancel_url: `${req.headers.origin}/?canceled=true`,
});
res.redirect(303, session.url);
} catch (err) {
res.status(err.statusCode || 500).json(err.message);
}
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
}
you can see in the line_items that everything is static except for the one variable that I am testing.
CodePudding user response:
JSON.stringify expects an object (https://www.w3schools.com/js/js_json_stringify.asp)
const postData = async () => {
const response = await fetch("/api/checkout_sessions", {
method: "POST",
body: JSON.stringify({
id,
price,
description,
title,
}),
});
return response.json();
};
And on the api side you may have to parse the body before accessing any properties like so
const body = JSON.parse(req.body)
const title = body.title
(https://www.w3schools.com/Js/js_json_parse.asp)
CodePudding user response:
It's unclear if the array/string mismatch is due to your testing changes, but you'll need to ensure a single string is supplied for name
.
Your actual issue is likely here:
onClick={() => {
updateState;
postData;
}}
I'm surprised this is invoking the functions without ()
, but even if it were your postData()
would start before the react state change happened.
I suspect if you initialized title
with a value your endpoint would receive that.
const [title, setTitle] = useState("some default title");
You'll need to review how your application is tracking state here, and perhaps calculate that title
and pass it through to the request alongside updating the state.