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

ReactJS集成Stripe API删除卡片时setupIntent未定义报错求助

问题排查:Stripe支付卡片管理中的setupIntent未定义错误

核心错误根源

触发错误Uncaught (in promise) TypeError: can't access property "client_secret", setupIntent is undefined的直接原因是:调用stripe.confirmCardSetup时,setupIntent状态还未被正确初始化。同时代码中还存在多处逻辑错误,导致卡片添加、删除功能均无法正常工作。


前端代码问题修复

1. 修正SetupIntent创建逻辑

原代码中createSetupIntent默认使用GET请求调用/wallet,但后端只有POST /wallet才会创建SetupIntent,且按钮点击与表单提交的异步时序问题会导致setupIntent未就绪就执行confirmCardSetup。

修改createSetupIntent为POST请求,并调整表单提交流程,确保先获取SetupIntent再执行卡片确认:

const createSetupIntent = async () => {
  // 明确使用POST请求调用创建SetupIntent的接口
  const si = await fetchFromAPI('wallet', { method: 'POST' });
  setSetupIntent(si);
};

// 调整handleSubmit,先检查setupIntent是否存在
const handleSubmit = async (event) => {
  event.preventDefault();
  if (!setupIntent) {
    alert('请先获取支付配置');
    return;
  }
  const cardElement = elements.getElement(CardElement);
  const { setupIntent: updatedSetupIntent, error } = await stripe.confirmCardSetup(
    setupIntent.client_secret,
    { payment_method: { card: cardElement } }
  );
  if (error) {
    alert(error.message);
    console.log(error);
  } else {
    setSetupIntent(updatedSetupIntent);
    await getCardDetails();
    alert('卡片添加成功!');
  }
};

// 修改按钮禁用条件,确保setupIntent就绪后才能提交
<button type="submit" disabled={!stripe || !setupIntent}>
  添加卡片
</button>

2. 修复删除卡片功能

原删除逻辑存在数组取值错误、请求方法错误、参数传递错误:

// 修改DeleteSavedCard,接收当前卡片的id作为参数
const DeleteSavedCard = async (cardId) => {
  const uId = localStorage.getItem("USERID");
  try {
    // 使用POST请求,GET请求不支持body
    const response = await fetchFromAPI('deleteCard', {
      method: 'POST',
      body: JSON.stringify({ cardId, uId })
    });
    const result = await response.json();
    if (response.ok) {
      console.log('卡片删除成功');
      // 删除后刷新卡片列表
      await getCardDetails();
    } else {
      console.error('卡片删除失败:', result.Error);
    }
  } catch (error) {
    console.error('发生错误:', error);
  }
};

// 在CreditCard组件中传递当前卡片的id
function CreditCard(props) {
  const { last4, brand, exp_month, exp_year, id } = props.card;
  return (
    <p className="TEST">
      {brand} **** **** **** {last4} expires {exp_month}/{exp_year} 
      <button onClick={() => DeleteSavedCard(id)}>Delete</button>
    </p>
  );
}

3. 列表渲染优化

确保cardComplete初始值为数组,渲染时添加空状态提示:

// 初始状态保持数组
const [cardComplete, setCardComplete] = useState([]);

// 渲染列表时添加空状态提示
<div>
  <p>已保存的支付方式</p>
  {cardComplete.length === 0 ? (
    <p>暂无已保存卡片</p>
  ) : (
    cardComplete.map((paymentSource) => (
      <CreditCard key={paymentSource.id} card={{...paymentSource.card, id: paymentSource.id}} />
    ))
  )}
</div>

后端代码问题修复

1. 修正删除卡片接口逻辑

原接口存在变量覆盖、条件判断错误、Stripe方法调用错误:

app.post("/deleteCard", 
  runAsync( async (req: Request, res: Response) => {
    console.log("\n\n Body Passed:", req.body);   
    const { cardId } = req.body;
    const user = validateUser(req);
    
    // 修正条件判断:检查cardId是否存在
    if (!cardId) {
      return res.status(400).send({
        Error: "CardId是删除卡片的必填参数",
      });
    }
    try {
      // 调用Stripe官方删除Payment Method的方法
      const deletedCard = await stripe.customers.deletePaymentMethod(
        user.uid, // Stripe customer id
        cardId
      );
      return res.status(200).send(deletedCard);
    } catch (error) {
      console.error('删除卡片错误:', error);
      return res.status(400).send({
        Error: "删除卡片失败",
        details: error.message
      });
    }
  })
);

2. 确保SetupIntent接口正确返回

确认createSetupIntent函数正确创建并返回Stripe的SetupIntent对象:

// customers.js中的createSetupIntent示例
export const createSetupIntent = async (customerId) => {
  const setupIntent = await stripe.setupIntents.create({
    customer: customerId,
  });
  return setupIntent;
};

关键注意事项

  1. 确保fetchFromAPI函数正确处理请求方法和请求头(比如携带Authorization Bearer token),否则后端的validateUser会失败。
  2. Stripe的Payment Method和Source是不同的概念,当前代码用listPaymentMethods,删除时要对应使用deletePaymentMethod。
  3. 所有异步操作要做好错误捕获,避免未处理的Promise异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:25:00