如何排查Stripe API调用时出现的JSON Parse解析错误
Stripe测试卡调用JSON解析错误定位
错误发生位置
解析错误出现在向本地服务http://localhost:8080/buyer/payments发起请求后的resp.json()执行步骤,和第一次调用Stripe官方接口的JSON解析环节无关。
错误产生原因
- 直接原因:
resp.json()方法会强制把HTTP响应体按照JSON格式解析,但当前本地8080端口服务返回的响应体是纯文本内容,内容开头为Failed(常见为接口报错返回的Failed to process request/Failed to verify payment类纯文本提示,不是合法JSON结构),解析器读到非JSON语法的标识符就会抛出Unexpected identifier "Failed"错误。 - 根本触发原因:代码存在多处逻辑问题,直接导致本地接口返回非JSON的错误响应:
- 调用Stripe创建Token的POST请求参数传递方式、参数内容都有错误:你把卡信息、金额、货币参数全部拼接在了URL的查询字符串中,但你设置的
Content-Type为application/x-www-form-urlencoded,该类型要求POST参数放在请求体中传递,而非URL后;另外/v1/tokens接口仅用于生成卡支付令牌,不需要传amount、currency参数,这两个参数是后续服务端发起扣款请求时传递的;同时你填写的测试卡号码仅12位,标准Stripe 4242测试卡为16位4242424242424242,填写的2023年过期时间也已失效。以上多个参数问题叠加,会导致Stripe接口无法正确处理请求,大概率返回错误对象而非合法支付Token,你拿到错误结果传给本地接口后,本地接口校验失败直接返回纯文本报错。 - 传给本地支付接口的请求体格式错误:你直接执行
JSON.stringify(data.id)传递参数,最终发出去的请求体是一个被引号包裹的纯字符串(比如"tok_xxxx"),不是后端预期的JSON对象结构,后端解析请求体失败就会返回纯文本错误。
- 调用Stripe创建Token的POST请求参数传递方式、参数内容都有错误:你把卡信息、金额、货币参数全部拼接在了URL的查询字符串中,但你设置的
修正参考代码
// 按接口要求把合法参数放在请求体中传递给Stripe const stripeParams = new URLSearchParams({ "card[number]": "4242424242424242", "card[exp_month]": "10", "card[exp_year]": "2028", // 替换为未过期的年份 "card[cvc]": "123" }) fetch( "https://api.stripe.com/v1/tokens", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", Authorization: "Bearer sk_test_51L6xxxxxxxx", }, body: stripeParams } ) .then(async (resp) => { // 先判断响应状态再解析JSON,避免接口返回错误时解析失败 if (!resp.ok) throw new Error(`Stripe接口请求失败: ${await resp.text()}`) return resp.json() }) .then((data) => { console.log("获取到的Stripe Token:", data.id); // 传给本地接口时使用标准JSON对象结构,按后端实际要求调整字段即可 return fetch("http://localhost:8080/buyer/payments", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify({ token: data.id, amount: 999, currency: "usd" }), }) }) .then(async (resp) => { // 同样先判断本地接口响应状态,非2xx状态先读取文本排查错误 if (!resp.ok) throw new Error(`本地支付接口请求失败: ${await resp.text()}`) return resp.json() }) .then(function (response) { if (response.paid) { // 支付成功后的业务逻辑 } }) .catch((err) => console.log(err));
注意:浏览器端直接存储、使用Stripe密钥发起请求存在严重安全风险,生产环境必须把密钥放在服务端,前端仅使用Stripe官方JS SDK收集卡信息生成Token,避免密钥泄露造成资损。
内容的提问来源于stack exchange,提问作者Xwingoga06
相关产品推荐
相关产品推荐

