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

Laravel中使用Xero-php-oauth2更新联系人遇401认证失败

Xero联系人更新401 AuthenticationUnsuccessful错误排查与解决

问题背景

在Laravel中使用xero-php-oauth2工具处理发票关联的Xero联系人更新操作时,调用updateContact接口返回401 AuthenticationUnsuccessful错误,但使用相同Bearer令牌进行发票创建/更新、随新发票创建联系人的操作均正常。

已尝试的代码

$xero = resolve(AccountingApi::class);
$invoice = new Invoice();
$invoice->setLineItems($lineItems);
$result = $xero->updateInvoice($tenantId, $invoice_id, $invoice);
$contactId = $result->getInvoices()[0]['contact']['contact_id'];
$contact = $this->newContact();
$contact->setContactId($contactId);
//$tenantId, $contactid, and $contact are correct
$xero->updateContact($tenantId, $contactId, $contact);

请求详情

Request {#1160 ▼
  -method: "POST"
  -requestTarget: null
  -uri: Uri {#1212 ▼
    -scheme: "https"
    -userInfo: ""
    -host: "api.xero.com"
    -port: null
    -path: "/api.xro/2.0/Contacts/134ab308-7d07-4c2d-a770-c01325947ede"
    -query: ""
    -fragment: ""
  }
  -headers: array:6 [▼
    "Host" => array:1 [▼
      0 => "api.xero.com"
    ]
    "User-Agent" => array:1 [▼
      0 => "[xero-php-oauth2 (2.11.0)]"
    ]
    "xero-tenant-id" => array:1 [▼
      0 => "TENANT_ID_HERE"
    ]
    "Accept" => array:1 [▼
      0 => "application/json"
    ]
    "Content-Type" => array:1 [▼
      0 => "application/json"
    ]
    "Authorization" => array:1 [▼
      0 => "Bearer BEARER_TOKEN_HERE"
    ]
  ]
  -headerNames: array:6 [▶]
  -protocol: "1.1"
  -stream: Stream {#1217 ▼
    -stream: stream resource @755 ▼
      wrapper_type: "PHP"
      stream_type: "TEMP"
      mode: "w+b"
      unread_bytes: 0
      seekable: true
      uri: "php://temp"
      options: []
    }
    -size: null
    -seekable: true
    -readable: true
    -writable: true
    -uri: "php://temp"
    -customMetadata: []
  }
}

已尝试的操作

添加accounting.contacts权限范围,但问题未解决:

$options = ['scope' => ['openid email profile offline_access accounting.settings accounting.transactions accounting.contacts accounting.journals.read accounting.reports.read accounting.attachments']];

错误信息

[401] Client error: `POST https://api.xero.com/api.xro/2.0/Contacts/134ab308-7d07-4c2d-a770-c01325947ede` resulted in a `401 Unauthorized` response: {"Type":null,"Title":"Unauthorized","Status":401,"Detail":"AuthenticationUnsuccessful","Instance":"94b725d8-435b-4a98-be (truncated...)

解决方案

  • 验证令牌权限范围:解码当前Bearer令牌的JWT payload,确认scope字段包含accounting.contacts。若未包含,需重新发起授权流程,确保刷新令牌时携带完整权限范围,且用户已同意该权限。
  • 核对租户与联系人归属:确认获取的contactId对应的联系人属于当前请求的tenantId,Xero令牌仅对指定租户有效,跨租户操作会返回401。
  • 检查请求体格式:确保$contact对象包含必要字段(如Name),即使仅更新部分字段,Xero可能要求必填字段存在。可通过$contact->toJson()查看请求体是否符合API规范。
  • 升级SDK版本:当前使用的xero-php-oauth2版本为2.11.0,尝试升级到最新稳定版,旧版本可能存在联系人更新接口的授权处理bug。
  • 检查应用租户权限:登录Xero开发者后台,确认当前租户允许应用修改联系人数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 10:45:44