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
相关产品推荐
相关产品推荐

