如何访问序列化JSON的属性?Stripe支付跳转问题排查
问题:调用接口获取URL后无法跳转,出现JSON解析错误
我调用接口后会返回url和错误信息,需要获取url来通过router跳转,但遇到了问题。
原前端代码
const redirectToStripe = async () => { const response = await fetch( "http://localhost:5000/create-checkout-session", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify(cartItems.value), } ) .then((response) => response.json()) .then((response) => console.log("stringied response", JSON.stringify(response)) ); const { url } = await response.json(); console.log("url=", url); // 无法执行,无控制台输出 // window.location.href = url; // router.go(url) // 需要修复并取消注释 };
出现的错误
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'json')
at redirectToStripe
控制台输出
stringied response {"url":"https://checkout.stripe.com/c/pay/cs_test_a1X3r92YtZfM9H"}
这个就是我需要跳转的url,但不知道怎么在序列化后的结果里访问它,怎么获取"url"的值传入router.go(url)?后面的url控制台输出因为JSON错误无法执行,我猜它和上面输出的url是同一个。
另外我不清楚为什么会出现这个错误,或者是否需要修复——毕竟我已经拿到了需要的url。这个错误和"Content-Type"请求头有关吗?我选的请求头是否正确?还是其他地方出错了?
后端接口参考代码
app.post("/create-checkout-session", async (req, res) => { // 仅提取Stripe价格ID和数量组成数组 const lineItems = req.body.map((item) => { console.log("lineItems= ", item.item.priceId, item.item.quantity); return { price: item.item.priceId, quantity: item.item.quantity, }; }); const session = await stripe.checkout.sessions.create({ mode: "payment", line_items: lineItems, success_url: `http://localhost:8080/success?session_id={CHECKOUT_SESSION_ID}`, cancel_url: `http://localhost:8080/`, }); return res.send({ url: session.url }); });
补充修改尝试
尝试了以下代码:
const redirectToStripe = () => { const response = fetch("http://localhost:5000/create-checkout-session", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify(cartItems.value), }).then((response) => response.json()); const {url} = response.json(); // const { url } = await response.json(); console.log("url=", url); };
出现新错误:
Uncaught TypeError: response.json is not a function
解决方案
问题根源
- 原代码混用了
async/await和.then()链式调用:await fetch(...)后面接.then(),最后.then()里只做了console.log,没有返回值,导致response变量是undefined,所以后续调用response.json()会报错。 - 补充修改的代码里,
fetch(...).then(...)返回的是一个Promise对象,不是响应体,直接调用response.json()自然会报错,因为Promise没有json()方法。
正确代码写法(二选一即可)
写法一:纯async/await风格
const redirectToStripe = async () => { try { const fetchResponse = await fetch( "http://localhost:5000/create-checkout-session", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify(cartItems.value), } ); const data = await fetchResponse.json(); console.log("url=", data.url); // 取消注释下面一行进行跳转(Vue Router中一般用push而非go,go是控制前进/后退步数) // router.push(data.url); } catch (error) { console.error("请求出错:", error); } };
写法二:纯.then()链式调用风格
const redirectToStripe = () => { fetch("http://localhost:5000/create-checkout-session", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify(cartItems.value), }) .then((response) => response.json()) .then((data) => { console.log("url=", data.url); // 取消注释下面一行进行跳转 // router.push(data.url); }) .catch((error) => { console.error("请求出错:", error); }); };
关于请求头的说明
你设置的Accept和Content-Type请求头是正确的:
Content-Type: application/json告诉后端你发送的是JSON格式的请求体,后端可以正确解析req.bodyAccept: application/json告诉后端你期望接收JSON格式的响应,和后端返回的{ url: session.url }格式匹配,所以这部分没有问题。
内容的提问来源于stack exchange,提问作者Eric Andre
相关产品推荐
相关产品推荐

