xeops/xero-php

是 Xero API 的客户端实现,具有更简洁的 OAuth 接口和类似 ORM 的抽象。

v2.2.4 2020-11-26 18:27 UTC

README

Build Status Latest Stable Version Total Downloads

Xero API 的客户端库,封装了 Guzzle 和类似 ORM 的模型。

此库最初是为传统的私有、公共和合作伙伴应用程序开发的,但现在基于 OAuth 2 范围。

需求

  • PHP 5.6+

设置

使用 composer

composer require calcinai/xero-php

从 1.x/OAuth 1a 迁移

现在所有应用程序只有一个流程,这与旧版 公共 应用程序最相似。所有应用程序现在都需要 OAuth 2 授权流程,并在运行时授权特定组织,而不是在应用程序创建期间创建证书。

由于现在只有一种类型的应用程序,您现在可以使用您的访问令牌和 tenantId 创建一个通用的 XeroPHP\Application,从现在开始,所有代码都应该保持不变。

用法

在可以发出资源请求之前,应用程序必须获得授权。授权流程将为您提供访问令牌和刷新令牌。访问令牌可以用来检索应用程序有权查询的租户(Xero 组织)列表,然后,与所需的 tenantId 结合,您可以实例化一个 XeroPHP\Application 来查询特定组织的 API。

对于需要长期访问组织的应用程序,需要构建刷新流程来捕获过期的访问令牌并刷新它。

授权码流程

用法与 The League 的 OAuth 客户端相同,使用 \Calcinai\OAuth2\Client\Provider\Xero 作为提供者。

session_start();
 
$provider = new \Calcinai\OAuth2\Client\Provider\Xero([
    'clientId'          => '{xero-client-id}',
    'clientSecret'      => '{xero-client-secret}',
    'redirectUri'       => 'https://example.com/callback-url',
]);
 
if (!isset($_GET['code'])) {

    // If we don't have an authorization code then get one
    $authUrl = $provider->getAuthorizationUrl([
        'scope' => 'openid email profile accounting.transactions'
    ]);

    $_SESSION['oauth2state'] = $provider->getState();
    header('Location: ' . $authUrl);
    exit;

// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {

    unset($_SESSION['oauth2state']);
    exit('Invalid state');

} else {

    // Try to get an access token (using the authorization code grant)
    $token = $provider->getAccessToken('authorization_code', [
        'code' => $_GET['code']
    ]);


    //If you added the openid/profile scopes you can access the authorizing user's identity.
    $identity = $provider->getResourceOwner($token);
    print_r($identity);

    //Get the tenants that this user is authorized to access
    $tenants = $provider->getTenants($token);
    print_r($tenants);
}

然后您可以存储令牌并使用它对 API 的所需租户发出请求

范围

OAuth 范围,表示您希望应用程序能够访问 Xero 组织的哪些部分。完整的范围列表可以在 这里 找到。

$authUrl = $provider->getAuthorizationUrl([
   'scope' => 'bankfeeds accounting.transactions'
]);

刷新令牌

$newAccessToken = $provider->getAccessToken('refresh_token', [
    'refresh_token' => $existingAccessToken->getRefreshToken()
]);

与 API 交互

一旦您获得了有效的访问令牌和 tenantId,您就可以实例化一个 XeroPHP\Application。以下所有示例都涉及 XeroPHP\Models\Accounting 命名空间中的模型。此外,还有 PayrollAUPayrollUSFilesAssets 的模型。

创建 XeroPHP 实例(包含示例配置)

$xero = new \XeroPHP\Application($accessToken, $tenantId);

加载对象集合并遍历它们

$contacts = $xero->load(Contact::class)->execute();

foreach ($contacts as $contact) {
    print_r($contact);
}

加载单个页面的对象集合,并遍历它们 (为什么?)

$contacts = $xero->load(Contact::class)->page(1)->execute();

foreach ($contacts as $contact) {
    print_r($contact);
}

搜索满足特定标准的对象

$xero->load(Invoice::class)
    ->where('Status', Invoice::INVOICE_STATUS_AUTHORISED)
    ->where('Type', Invoice::INVOICE_TYPE_ACCREC)
    ->execute();

通过 GUID 加载某些内容

$contact = $xero->loadByGUID(Contact::class, $guid);

或创建并填充它

$contact = new Contact($xero);

$contact->setName('Test Contact')
    ->setFirstName('Test')
    ->setLastName('Contact')
    ->setEmailAddress('test@example.com');

保存它

$contact->save();

如果您创建了多个相同类型的对象,您可以通过将数组传递给 $xero->saveAll() 来批量保存它们。

从 v1.2.0+ 开始,可以在创建对象本身时直接注入 Xero 上下文,这样就可以公开 ->save() 方法。这对于对象与其关系保持状态是必要的。

保存相关模型

如果您一次保存多个模型,默认情况下不会更新额外的模型属性。这意味着如果您保存了一个包含新联系人的发票,则不会更新联系人 ContactID。如果您想更新相关模型的属性,可以在保存方法中传递一个布尔标志,值为 true

$xero->save($invoice, true);

嵌套对象

$invoice = $xero->loadByGUID(Invoice::class, '[GUID]');
$invoice->setContact($contact);

附件

$attachments = $invoice->getAttachments();
foreach ($attachment as $attachment) {
    //Do something with them
    file_put_contents($attachment->getFileName(), $attachment->getContent());
}

//You can also upload attachemnts
$attachment = Attachment::createFromLocalFile('/path/to/image.jpg');
$invoice->addAttachment($attachment);

要设置附件上的 IncludeOnline 标志,将 true 作为 ->addAttachment() 方法的第二个参数传递。

PDF - 支持PDF导出的模型将继承一个 ->getPDF() 方法,该方法返回PDF的原始内容。目前这仅限于发票和信用通知。

有关更复杂的使用和嵌套/相关对象,请参阅 示例。还有使用此库的 PHP 示例应用

Webhooks

如果您正在接收来自Xero的webhooks,有一个 Webhook 类可以帮助处理请求并解析相关事件列表。

// Configure the webhook signing key on the application
$application->setConfig(['webhook' => ['signing_key' => 'xyz123']]);
$webhook = new Webhook($application, $request->getContent());

/**
 * @return int
 */
$webhook->getFirstEventSequence();

/**
 * @return int
 */
$webhook->getLastEventSequence();

/**
 * @return \XeroPHP\Webhook\Event[]
 */
$webhook->getEvents();

参阅:Webhooks 文档

验证Webhooks

为确保webhooks来自Xero,您必须验证Xero提供的传入请求头。

if (! $webhook->validate($request->headers->get('x-xero-signature'))) {
    throw new Exception('This request did not come from Xero');
}

参阅:签名文档

处理错误

您的请求可能导致Xero出现错误,您可能需要处理这些错误。您可能会遇到以下错误:

  • HTTP 400 错误请求,例如发送格式错误的电子邮件地址。
  • HTTP 503 请求过多,如果您在短时间内频繁调用API。
  • HTTP 400 错误请求,请求的资源不存在。

这只是几个示例,您应该阅读官方文档以了解更多关于可能出现的错误。

抛出异常

此库将解析Xero返回的响应,并在遇到这些错误之一时抛出异常。以下是一个表格,显示了响应代码和对应的抛出的异常:

参阅:响应代码和错误文档

处理异常

要捕获和处理这些异常,您可以在请求周围使用 try / catch 块,并根据需要处理每个异常。

try {
    $xero->save($invoice);
} catch (NotFoundException $exception) {
    // handle not found error
} catch (RateLimitExceededException $exception) {
    // handle rate limit error
}

参阅:与异常一起工作