无法从Stripe获取client_secret以完成支付问题求助
克隆亚马逊页面时Stripe client_secret获取失败排查
问题描述
我跟着视频教程克隆亚马逊页面,在支付流程中遇到无法获取Stripe的client_secret密钥的问题。控制台仅显示初始状态值true,当我将商品添加到购物车并尝试支付时,client_secret既不更新也不生成。
相关代码片段
前端Payment组件代码
import { CardElement, useElements, useStripe } from "@stripe/react-stripe-js"; import React, { useEffect, useState } from "react"; import CurrencyFormat from "react-currency-format"; import CheckoutProducts from "./CheckoutProducts"; import "./Payment.css"; import { getBasketTotal } from "./Reducer"; import { useStateValue } from "./StateProvider"; import axios from "./axios"; import { Link, useNavigate } from "react-router-dom"; import { db } from "./Firebase"; function Payment() { const [{ basket, user }, dispatch] = useStateValue(); const elements = useElements(); const stripe = useStripe(); const [error, setError] = useState(null); const [disabled, setDisabled] = useState(true); const [succeeded, setSucceeded] = useState(false); const [processing, setProcessing] = useState(""); const [clientSecret, setClientSecret] = useState(true); const Navigate = useNavigate(); useEffect(()=>{ const getClientSecret = async () => { const response = await axios({ method: "post", url: `/payments/create?total${getBasketTotal(basket) * 100}`, }); setClientSecret(response.data.clientSecret); }; getClientSecret(); }, [basket]); console.log("the secret is>>>", clientSecret); console.log(getBasketTotal(basket)) const handleSubmit = async (e) => { e.preventDefault(); setProcessing(true); const payload = await stripe .confirmCardPayment(clientSecret, { payment_method: { card: elements.getElement(CardElement), }, }) .then(({ paymentIntent }) => { db.collection("users") .doc(user?.uid) .collection("Orders") .doc(paymentIntent.id) .set({ basket: basket, amount: paymentIntent.amount, created: paymentIntent.created, }); setSucceeded(true); setError(null); setProcessing(false); dispatch({ type: "EMPTY__BASKET", }); Navigate("/Orders, { replace: true }"); }); }; }
后端云函数代码
const functions = require("firebase-functions"); const express = require("express"); const cors = require("cors"); const stripe = require("stripe")( ".... " ); const app = express(); app.use(cors({origin:true })); app.use(express.json()); app.get("/", (request, response) => response.status(200).send("hello World")); app.post("/payments/create", async (request, response) => { const total = request.query.total; console.log( `payment request recieved BOOHOOOO!!! for this amount >>>`, total ); const paymentIntent = await stripe.paymentIntents.create({ amount: total, // subunits of the currency currency: "usd", }); response.status(201).send({ clientSecret: paymentIntent.client_secret, }); }); exports.api = functions.https.onRequest(app);
Axios实例配置
import axios from "axios"; const instance=axios.create({ baseURL:'http://127.0.0.1:5001/cleaver-clone/us-central1/api' // the API (cloud Function) URL }); export default instance
排查方向
- URL参数格式错误:前端请求URL中
total参数缺少=号,正确写法应为/payments/create?total=${getBasketTotal(basket) * 100}。参数格式错误会导致后端无法获取total值,进而无法创建Stripe PaymentIntent。 - 初始状态值不合理:
clientSecret初始值设为true,建议改为null或空字符串,避免与返回的密钥字符串混淆,也便于判断是否已获取到有效密钥。 - 缺少请求错误捕获:前端
getClientSecret函数未添加try/catch,无法得知请求是否失败。建议添加错误处理,打印错误信息定位问题:const getClientSecret = async () => { try { const response = await axios({ method: "post", url: `/payments/create?total=${getBasketTotal(basket) * 100}`, }); setClientSecret(response.data.clientSecret); } catch (err) { console.error("获取clientSecret失败:", err); } }; - 后端参数校验缺失:后端未校验
total参数是否存在或合法,若total为空或非数字,Stripe会抛出错误。建议添加校验逻辑:app.post("/payments/create", async (request, response) => { const total = request.query.total; if (!total || isNaN(total)) { return response.status(400).send({ error: "无效的金额参数" }); } // 后续逻辑... }); - Stripe密钥验证:确认后端填写的Stripe密钥是有效的测试密钥(以
sk_test_开头),而非空值或错误密钥。 - 云函数运行状态:确认本地云函数模拟器正常运行,访问
http://127.0.0.1:5001/cleaver-clone/us-central1/api应返回"hello World",确保API可正常访问。 - 跳转语法错误:前端
Navigate调用存在语法错误,正确写法为Navigate("/Orders", { replace: true });,该错误虽不影响client_secret获取,但会导致支付成功后跳转失败。
内容的提问来源于stack exchange,提问作者Fits
相关产品推荐
相关产品推荐

