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

如何控制NodeJS+React支付场景中/getResponse接口重复调用

问题原因及解决方案

前端重复请求问题

你的useEffect依赖数组里包含了txnid、amount、status这三个本地状态,每次接口请求成功后调用setTxnid、setAmount、setStatus会更新这些状态,触发useEffect重新执行,形成循环调用,导致接口多次请求。

前端修复方案:

  1. 修改useEffect的依赖数组,移除txnid、amount、status,只保留真正需要触发重新请求的依赖(注意你代码里写的editPayment应该是editDonation的笔误):
useEffect(() => {
  const controller = new AbortController();
  Axios.get('http://localhost:8080/getResponse', { signal: controller.signal }).then(res =>{    
    setTxnid(res.data.txnid);
    setAmount(res.data.amount);
    setStatus(res.data.status);
    let value = new DonationEdit();
    value.donationStatus = res.data.status;
    value.transactionId=res.data.txnid;
    if(rootStore.commonStore.donation)
      value.donationId = parseInt( rootStore.commonStore.donation);
    editDonation(value); // 修正笔误,原代码写的editPayment
  }).catch(err => {
    if (err.name !== 'CanceledError') {
      // 处理其他错误
    }
  });

  // 组件卸载时取消请求
  return () => controller.abort();
}, [rootStore.commonStore.donation, editDonation])
  1. 更优方案:后端重定向时直接携带支付参数到前端,避免额外接口请求。比如修改后端/response接口的重定向逻辑:
// 成功时
res.redirect(`http://localhost:3000/response?txnid=${txnid}&amount=${amount}&status=${status}`);
// 失败时同理
res.redirect(`http://localhost:3000/responseFailure?txnid=${txnid}&status=failure`);

然后前端通过useLocation获取URL参数,无需调用/getResponse:

import { useLocation } from 'react-router-dom';

const PaymentSuccessPage = () => {
  const location = useLocation();
  const rootStore = useContext(RootStoreContext);
  const { editDonation } = rootStore.donationStore;
  
  useEffect(() => {
    const params = new URLSearchParams(location.search);
    const txnid = params.get('txnid');
    const amount = params.get('amount');
    const status = params.get('status');
    
    if (txnid && status) {
      let value = new DonationEdit();
      value.donationStatus = status;
      value.transactionId = txnid;
      if(rootStore.commonStore.donation)
        value.donationId = parseInt(rootStore.commonStore.donation);
      editDonation(value);
    }
  }, [location.search, rootStore.commonStore.donation, editDonation]);

  return <Container>...</Container>;
}

后端潜在问题

当前后端使用全局变量txnid、amount、status存储支付结果,多用户并发支付时会导致数据互相覆盖,出现严重的逻辑错误。

后端修复方案:

  1. 不要使用全局变量存储用户支付数据,改用Session或者将支付结果存入数据库:
    • 如果用Session,需要先配置express-session:
      const session = require('express-session');
      app.use(session({
        secret: 'your-secret-key',
        resave: false,
        saveUninitialized: true,
        cookie: { secure: false } // 生产环境建议设为true,配合HTTPS
      }));
      
    • 然后在/response接口中把数据存入session:
      app.post('/response', (req, res) => {
        // ... 原有hash验证逻辑
        if(hash == req.body.hash && req.body.status == 'success')   {
          // 存入session
          req.session.paymentResult = {
            status: req.body.status,
            txnid: req.body.txnid,
            amount: req.body.amount
          };
          res.redirect('http://localhost:3000/response');   
        } else {
          req.session.paymentResult = {
            status: req.body.status,
            txnid: req.body.txnid
          };
          res.redirect('http://localhost:3000/responseFailure');
        }
      });
      
    • 修改/getResponse接口从session取数据:
      app.get('/getResponse', (req, res) => {
        if (req.session.paymentResult) {
          res.send(req.session.paymentResult);
          // 可选:返回后清除session中的数据,避免重复使用
          delete req.session.paymentResult;
        } else {
          res.status(404).send({ message: 'No payment result found' });
        }
      });
      
  2. 结合前面的前端优化方案,直接通过重定向携带参数,彻底避免依赖后端全局变量或session的问题,同时减少一次接口请求,提升性能。

内容的提问来源于stack exchange,提问作者Pavi-98

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:27:36