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

React应用本地对接Xero Accounting API的实现问题咨询

React对接Xero Accounting API授权流程调整

我正在本地React应用中对接Xero Accounting API,已搭建授权流程:先请求后端授权接口,再通过回调API获取用于数据调用的access_token。以下是我的代码,期望API返回响应:Access token obtained successfully, (Access Token)。

React前端组件代码

import { useLocation } from "react-router-dom";
import useXero from "../../hooks/useXero";

const SigninToXero: React.FC = () => {
  const location = useLocation();
  const queryParams = new URLSearchParams(location.search);
  const authorizationCode = queryParams.get("code");

  const handleAuthorizeClick = () => {
    window.location.href = "http://localhost:4000/authorize";
  };

  return <button onClick={handleAuthorizeClick}>Authorize Xero</button>;
};

export default SigninToXero;

Express后端Xero路由代码

const express = require("express");
const xero = express.Router();
const schemas = require("../models/schemas");

const clientId = "xxx";
const clientSecret = "xxx";
const redirectUri = "http://localhost:4000/callback";

xero.get('/authorize', (_, res) => {
  // 重定向用户至Xero授权端点
  const authorizeUrl = `https://login.xero.com/identity/connect/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}`;
  res.redirect(authorizeUrl);
});

xero.get("/callback", async (req, res) => {
  const authorizationCode = req.query.code;

  // 用授权码交换访问令牌
  const tokenResponse = await axios.post(
    "https://identity.xero.com/connect/token",
    null,
    {
      params: {
        client_id: clientId,
        client_secret: clientSecret,
        code: authorizationCode,
        grant_type: "authorization_code",
        redirect_uri: redirectUri,
      },
    }
  );

  const accessToken = tokenResponse.data.access_token;
  res.send("Access token obtained successfully", accessToken);
});

module.exports = xero;

Node服务器主文件代码

const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const router = require("./routes/router");
const xero = require("./routes/xero")
const mongoose = require("mongoose");
require("dotenv/config");

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

const corsOptions = {
  origin: "*",
  credentials: true,
  optionSuccessStatus: 200,
};

app.use(cors(corsOptions));
app.use("/", router);
app.use("/", xero)

const dbOptions = { useNewUrlParser: true, useUnifiedTopology: true };
mongoose
  .connect(process.env.DB_URI, dbOptions)
  .then(() => console.log("DB connected!"))
  .catch(err => console.log(err))

const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

问题修复及优化

  1. res.send用法错误:当前callback路由中res.send("Access token obtained successfully", accessToken)的写法不符合Express规范,res.send仅接受一个主要内容参数,第二个参数不会被正确拼接。需改为字符串拼接形式:
res.send(`Access token obtained successfully, ${accessToken}`);
  1. 缺失axios依赖:后端路由代码中使用了axios但未引入,需在Xero路由文件顶部添加:
const axios = require('axios');
  1. 敏感信息硬编码风险:建议将clientId、clientSecret这类敏感信息移至环境变量(如.env文件),通过process.env.CLIENT_ID、process.env.CLIENT_SECRET读取,避免代码泄露风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:55:41