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

Xero Python拉取会计数据OAuth2报错 无需Flask的自动化方案咨询

报错原因

xero-python SDK 要求你为 ApiClient 配置 oauth2_token_getter 回调函数,用来告诉 SDK 从哪里获取当前有效的 access token,你初始化配置时未提供该函数,因此触发该报错。

修复方案

你已经自己实现了令牌刷新逻辑,只需要在初始化 ApiClient 后,注册 token 获取回调即可,不需要引入任何 Web 框架。

在你初始化 api_client 的代码之后,添加如下注册逻辑:

# 注册token获取回调,SDK调用接口时会自动调用该函数拿access token
@api_client.oauth2_token_getter
def get_valid_access_token():
    with open(acces_token_dir, 'r', encoding='utf-8') as f:
        return f.read().strip()

修改完后即可正常调用接口拉取数据,以下是你原代码修复后的完整可运行版本(已替换转义字符):

import dateutil
import os
import requests
import base64
from xero_python.accounting import AccountingApi
from xero_python.api_client import ApiClient
from xero_python.api_client.configuration import Configuration
from xero_python.api_client.oauth2 import OAuth2Token
from xero_python.exceptions import AccountingBadRequestException

basedir = os.path.abspath(os.path.dirname(__file__))
dst_dir=basedir + f'/utils/data/refresh_token.txt'
tenant_dir=basedir + f'/utils/data/tenantId.txt'
acces_token_dir=basedir + f'/utils/data/accesstokenId.txt'

client_id = 'xxxxxx'
client_secret = 'xxxxxxx'
scope = 'offline_access accounting.journals.read accounting.settings.read accounting.transactions.read'
# 提前生成base64编码的client_id:client_secret,避免每次刷新重复计算
b64_id_secret = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()

def XeroRefreshToken(refresh_token):
    token_refresh_url = 'https://identity.xero.com/connect/token'
    response = requests.post(token_refresh_url,
                             headers={
                                 'Authorization': 'Basic ' + b64_id_secret,
                                 'Content-Type': 'application/x-www-form-urlencoded'
                             },
                             data={
                                 'grant_type': 'refresh_token',
                                 'refresh_token': refresh_token
                             })
    response.raise_for_status()
    json_response = response.json()

    new_refresh_token = json_response['refresh_token']
    with open(dst_dir, 'w', encoding='utf-8') as f:
        f.write(new_refresh_token)

    new_access_token = json_response['access_token']
    with open(acces_token_dir, 'w', encoding='utf-8') as f:
        f.write(new_access_token)
    return new_access_token, new_refresh_token

def XeroRequests():
    old_refresh_token = open(dst_dir,'r').read()
    new_token = XeroRefreshToken(old_refresh_token)
    # 注意:你原来的XeroTenants函数自行实现,用于获取租户ID
    xero_tenant_id = XeroTenants(new_token[0])
    with open(tenant_dir, 'w', encoding='utf-8') as f:
        f.write(xero_tenant_id)
    return xero_tenant_id

# 先刷新令牌,保证本地存储的是最新的有效令牌
XeroRequests()
xero_tenant_id = open(tenant_dir,'r').read()

# 初始化ApiClient
api_client = ApiClient(
    Configuration(
        debug=False,
        oauth2_token=OAuth2Token(
            client_id=client_id, client_secret=client_secret
        ),
    ),
    pool_threads=1,
)

# 注册token获取回调
@api_client.oauth2_token_getter
def get_valid_access_token():
    with open(acces_token_dir, 'r', encoding='utf-8') as f:
        return f.read().strip()

# 拉取会计科目示例
def accounting_get_accounts(xero_tenant_id):
    api_instance = AccountingApi(api_client)
    if_modified_since = dateutil.parser.parse("2020-02-06T12:17:43.202-08:00")
    where = 'Status=="ACTIVE" AND Type=="BANK"'
    order = 'Name ASC'

    try:
        api_response = api_instance.get_accounts(xero_tenant_id, if_modified_since=if_modified_since, where=where, order=order)
        print(api_response)
    except AccountingBadRequestException as e:
        print("Exception when calling AccountingApi->getAccounts: %s\n" % e)

accounting_get_accounts(xero_tenant_id)

权限适配

你当前的scope仅支持读取日记账,若需要拉取发票、会计科目表,需要先到Xero开发者平台修改应用的权限配置,添加对应scope:

  • 会计科目表:accounting.settings.read
  • 发票:accounting.transactions.read
    修改后需要重新走一次授权流程,获取新的refresh token替换你本地存储的旧令牌。

定时自动执行方案

不需要引入Web框架,直接用系统定时任务即可实现每日夜间自动执行:

  • Linux/Mac系统:配置crontab,例如每天凌晨2点执行脚本:
    0 2 * * * /usr/bin/python3 /path/to/your/xero_script.py >> /var/log/xero_sync.log 2>&1
    
  • Windows系统:添加任务计划程序,设置触发时间为每日夜间,执行动作选择你的Python解释器,参数填脚本路径即可。

注意事项

  • 本地存储的token文件建议设置最小访问权限,避免泄露敏感数据
  • 建议添加异常捕获和日志记录,方便排查定时任务执行失败的问题
  • Xero接口有调用频率限制,拉取大量数据时建议添加适当的延迟,避免触发限流

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 05:39:01