You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Stripe支付集成遇StripeAuthenticationError,附代码求排查

Stripe PaymentIntent 创建时出现 StripeAuthenticationError 排查与解决

首次基于Stripe搭建支付API,严格遵循官方文档操作,但创建PaymentIntent时触发Error creating payment intent: StripeAuthenticationError错误,请求排查原因及解决方法。

相关代码

Payment.jsx

import React from "react";
import CheckoutForm from "./CheckoutForm";
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";
import useCart from "../../hooks/useCart";

const stripePromise = loadStripe(import.meta.env.VITE_Stripe_PK);
const Payment = () => {
    const [cart] = useCart();
    console.log(cart);
    // calculate the checkout prices
    const cartTotal = cart.reduce((sum,item)=> sum + item.price ,0)
    const totalPrice = parseFloat(cartTotal.toFixed(2));


  return (
    <div className="max-w-screen-2xl container mx-auto xl:px-24 px-4 py-28">
      <Elements stripe={stripePromise}>
        <CheckoutForm price={totalPrice} cart={cart} />
      </Elements>
    </div>
  );
};

export default Payment;

CheckoutForm.jsx

import React, { useEffect, useState } from "react";
import { CardElement, useStripe, useElements } from "@stripe/react-stripe-js";
import { FaPaypal } from "react-icons/fa";
import useAxiosSecure from "../../hooks/useAxiosSecure";
import useAuth from "../../hooks/useAuth";

const CheckoutForm = ({ price, cart }) => {
  const stripe = useStripe();
  const elements = useElements();
  const axiosSecure = useAxiosSecure();
  const { user } = useAuth();

  const [cardError, setCardError] = useState("");
  const [clientSecret, setClientSecret] = useState("");

  useEffect(() => {
    if (typeof price !== "number" || price < 1) {
      console.log("Price is not a number or less than 1");
      return;
    }
    axiosSecure.post(`/create-payment-intent`, { price }).then((res) => {
      console.log(res.data.clientSecret);
      setClientSecret(res.data.clientSecret);
    });
  }, [price, axiosSecure]);
  


  const handleSubmit = async (event) => {
    event.preventDefault();
    if (!stripe || !elements) {
      // Stripe.js has not loaded yet. Make sure to disable
      // form submission until Stripe.js has loaded.
      return;
    }
    // create a card element
    const card = elements.getElement(CardElement);
  
    if (card == null) {
      return;
    }
  
    // Use your card Element with other Stripe.js APIs
    const { error, paymentMethod } = await stripe.createPaymentMethod({
      type: 'card',
      card,
    });
  
    if (error) {
      console.log("[error]", error);
      setCardError(error.message);
    } else {
      setCardError("success!");
      console.log("[PaymentMethod]", paymentMethod);
    }
  
    // Correct the usage of clientSecret
    const { paymentIntent, error:confirmError } =
      await stripe.confirmCardPayment(
        `${clientSecret}_secret`,  // Corrected usage of clientSecret
        {
          payment_method: {
            card: card,
            billing_details: {
              name: user?.displayName || "anonymous",
              email: user?.email || "unknown",
            },
          },
        }
      );
    if (confirmError) {
      console.log(confirmError);
    }
    console.log(paymentIntent);
    if (paymentIntent.status === "succeeded") {
        console.log(paymentIntent.id);
        setCardError(`Your transactionId is${paymentIntent.id} `)
        // payment info data
        const paymentInfo ={
            email: user.email,
            transitionId:paymentIntent.id,
            price,
            quantity: cart.length,
            status:"Order pending",
            itemName: cart.map(item => item.name),
            cartItems: cart.map(item => item._id),
            menuItem: cart.map(item => item.menuItem)
        }
        console.log(paymentInfo);
        // send information to backend
        axiosSecure.post('/payments',paymentInfo)
        .then( res =>{
            console.log(res.data);
        })
    }
  };
  

  return (
    <div className="flex flex-col sm:flex-row justify-start items-start gap-8">
      {/*left side */}
      <div className="md:w-1/2 w-full space-y-3 ">
        <h4 className="text-lg font-semibold">Order Summary</h4>
        <p>Total Price: ${price}</p>
        <p>Number of Items: {cart.length}</p>
      </div>
      {/* right side*/}
      <div className="md:w-1/3 w-full space-y-3 card shrink-0 max-w-sm shadow-2xl bg-base-100 px-4 py-8">
        <h4 className="text-lg font-semibold">Process Your Payment!</h4>
        <h5 className="font-medium">Credit/Debit Card</h5>
        {/* Stripe Form */}
        <form onSubmit={handleSubmit}>
          <CardElement
            options={{
              style: {
                base: {
                  fontSize: "16px",
                  color: "#424770",
                  "::placeholder": {
                    color: "#aab7c4",
                  },
                },
                invalid: {
                  color: "#9e2146",
                },
              },
            }}
          />
          <button
            type="submit"
            disabled={!stripe}
            className="btn btn-sm mt-5 btn-primary w-full text-white"
          >
            Pay
          </button>
        </form>
        {cardError ? (
          <p className="text-red text-center italic text-xs">{cardError}</p>
        ) : (
          ""
        )}

        {/* Paypal */}
        <div className="mt-5 text-center">
          <hr />
          <button
            type="submit"
            disabled={!stripe}
            className="btn btn-sm mt-5 bg-orange-500 text-white"
          >
            <FaPaypal /> Pay With Paypal
          </button>
        </div>
      </div>
    </div>
  );
};

export default CheckoutForm;

服务端代码

const express = require("express");
const app = express();
const cors = require("cors");
const port = process.env.PORT || 6001;
const mongoose = require("mongoose");
const jwt = require("jsonwebtoken");
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
require("dotenv").config();

// middleware
app.use(cors());
app.use(express.json());

//mongodb configuration using mongoose
mongoose
  .connect(
    `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASSWORD}@demo-foodi-client.xsy4pne.mongodb.net/demo-foodi-client?retryWrites=true&w=majority`
  )
  .then(console.log("MongoDB Connected Successfully"))
  .catch((error) => console.log("Error connecting to MongoDB", error));

// jwt authentication
app.post("/jwt", async (req, res) => {
  const user = req.body;
  const token = jwt.sign(user, process.env.ACCESS_TOKEN_SECRET, {
    expiresIn: "1hr",
  });
  res.send({ token });
});

//   import routes here
const menuRoutes = require("./api/routes/menuRoutes");
const cartRoutes = require("./api/routes/cartRoutes");
const userRoutes = require("./api/routes/userRoutes");
const paymentRoutes = require("./api/routes/paymentRoutes");
app.use("/menu", menuRoutes);
app.use("/carts", cartRoutes);
app.use("/users", userRoutes);
app.use("/payments", paymentRoutes);

app.post("/create-payment-intent", async (req, res) => {
  try {
    const { price } = req.body;
    const amount = price * 100; // Convert price to cents

    // Create a PaymentIntent with the order amount and currency
    const paymentIntent = await stripe.paymentIntents.create({
      amount: amount,
      currency: "usd",
      payment_method_types: ["card"],
    });

    res.send({ clientSecret: paymentIntent.client_secret });
  } catch (error) {
    console.error("Error creating payment intent:", error);
    res.status(500).send({ error: "Failed to create payment intent" });
  }
});

app.get("/", (req, res) => {
  res.send("Hello Foodi Client Server!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

错误截图

Stripe认证错误截图

排查方向与解决方法

1. 检查Stripe Secret Key配置

  • 确认环境变量STRIPE_SECRET_KEY的值是Stripe控制台提供的Secret Key(测试环境以sk_test_开头,生产环境以sk_live_开头),绝对不能使用Publishable Key(pk_开头)。
  • 检查.env文件中变量名是否拼写正确,比如是否写成STRIPE_SECRET而非STRIPE_SECRET_KEY,同时确保密钥前后无多余空格。
  • 登录Stripe控制台,确认该Secret Key未被禁用或删除,状态为有效。

2. 验证服务器网络与API访问权限

  • 测试服务器能否正常连接Stripe API:在服务器终端执行以下curl命令,替换sk_test_your_secret_key为实际密钥:
    curl -u sk_test_your_secret_key: https://api.stripe.com/v1/payment_intents -d amount=100 -d currency=usd
    
    如果请求失败,说明服务器存在网络限制(防火墙、代理等),需要开放对https://api.stripe.com的访问权限。
  • 确保使用的Stripe Node.js库版本为稳定版,过时版本可能存在API兼容性问题,可通过npm update stripe更新。

3. 修复代码中的潜在问题

  • 前端clientSecret拼接错误:confirmCardPayment中代码写了${clientSecret}_secret,但paymentIntent.client_secret本身已经是完整的密钥格式(如pi_xxx_secret_xxx),额外拼接会导致密钥无效,引发认证错误。修改为直接使用clientSecret:
    const { paymentIntent, error:confirmError } =
      await stripe.confirmCardPayment(
        clientSecret, // 移除多余的"_secret"拼接
        { /* ... */ }
      );
    
  • 金额精度问题:前端计算totalPrice时使用parseFloat(cartTotal.toFixed(2)),后端计算amount = price * 100可能出现浮点精度丢失(比如0.1 *100 =9.999999999999998),导致Stripe拒绝请求。建议后端使用Math.round(price *100)处理金额:
    const amount = Math.round(price * 100);
    

内容的提问来源于stack exchange,提问作者Yosef Elsersy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:15:55