wyzz/practicalafas

一个用于以实用方式与AFAS Profit进行通信的PHP库。

2.3 2020-11-06 22:56 UTC

This package is not auto-updated.

Last update: 2024-09-21 17:11:24 UTC


README

使用SOAP或REST以实用方式与AFAS Profit进行通信的PHP库。

简介

这是库代码,供您的代码/另一个项目使用。阅读此文档的人,应该已经有一个关于他们想实现什么以及什么是AFAS的想法,所以我们在这里不会讨论这些。(http://www.afas.nl/ - 他们当前的文档在 https://static-kb.afas.nl/datafiles/help/2_9_7/SE/EN/index.htm,但无疑这个URL将会改变。)

此代码基于三个原则形成

  • 实用性(对程序员而言);
  • 使REST API调用与SOAP API调用类似工作;
  • 在可能的情况下,不掩盖API端点的任何功能(例如,在一次调用中发送多个项目)或任何已知的API调用参数。

第一个(以及第三个)原则意味着可理解的代码比创建单独类别的未来兼容性扩展和引入大量样板代码更受欢迎。这意味着有良好注释的代码。这也意味着没有意外/未经文档记录的行为。(输入参数的验证以及从远程系统接收到的结果的验证涵盖了程序员可能遇到意外的情况,并抛出文档化的异常。)

话虽如此:第二个/第三个原则、不断发展的AFAS功能以及向后兼容性考虑,使得Connection::getData()的参数在某些方面不合理。但代码仍然相当易于阅读(因为方法不多)且易于调用“简单”用例。

兼容性

库的版本2与PHP5(5.4及以上)和PHP7兼容。

REST和SOAP的客户端类使用PHP的标准Curl + JSON和SOAP + SimpleXML扩展;如果您发现这些不起作用,欢迎提交包含新/修改客户端的PR。

对UpdateConnector类进行了PHP5.6、7.1和7.2的自动测试。(我目前不考虑客户端类需要测试。将来可能在Connection中添加一些轻量级测试,但这不在我的清单上。)

尽管PHP5.6不再官方支持,但此库将与它保持兼容,直到有真正的理由引入仅适用于PHP7的语言结构。

使用类

此库的一些部分并不是紧密耦合的

  • 客户端类可以独立使用,以对AFAS连接器进行调用。您需要知道AFAS对他们的REST或SOAP API的期望的确切参数;有两个客户端。如果您想保持与AFAS自身结构相似,则REST客户端似乎最适合。使用RestCurlClient(见下文示例)并忘记其他类。您需要知道有一个公共方法,callAfas(),它要么返回一个(JSON)字符串,包含成功的调用结果,要么抛出异常。

  • Connection类围绕SOAP或REST客户端,抽象了一些不太容易处理的参数。如果您例如

    • 不喜欢调用中的过滤器参数的结构(包括操作符的数字代码)
    • 希望返回数组数据,而不是XML(对于SOAP)/ JSON(对于REST)
    • 希望指定更简单的数组结构(而不是AFAS接受的JSON/XML字符串)以向更新连接器发送数据
    • 希望能够在REST和SOAP API之间进行切换,原因不明。(尽管它们的结果并不完全相同;请参阅README.get.md获取详细信息。)
    • 希望以尽可能小的跳行风险批量获取大量数据集。Helper类中有一个用于此目的的方法。
  • UpdateObject(及其子类)可用于为更新连接器创建XML或JSON负载,并验证其内容。它们的输出是字符串,可以按任何方式使用(例如,通过客户端类发送字符串数据,或通过Connection::sendData()发送,或使用UpdateObjects与您自己的自定义代码)。

  • 还有一个Helper类,其中包含一些可能对某些程序员有用的额外静态方法,但我不想让客户端/Connection过载。此外,IsoCountryTrait / KnBasicAddress / OrgPersonContact包含一些程序员可以使用的公共方法,用于他们自己的自定义验证,例如地址验证,而无需使用这些类的主要功能。这些方法没有进一步说明。

我们将首先讨论客户端,并给出与Connection比较的调用示例。除非您对差异感到好奇,否则可以跳过这些内容。

客户端类

这些可以独立使用,以对AFAS Profit进行SOAP/REST调用,如果您知道调用的结构。客户端类只处理

  • 连接详细信息(例如,可以编写一个不使用Curl的不同REST客户端)
  • 连接的认证详细信息。例如,在每次调用中插入应用程序令牌;以前有不同类执行NTLM认证而不是令牌。
  • 非常基本的参数验证(例如,跳过和获取必须是数字)。

连接和认证设置在构造函数中传递;不是传递给每个AFAS调用。

您将只使用一个公共方法:callAfas()。(还有一个公共方法:static getClientType() - 但对于独立使用来说这不是必要的。)客户端类对远程API调用几乎没有假设;需要传递确切的(类型)远程方法和参数,并且它将返回结果正文作为字符串。

RestCurlClient示例

所需的选项在下面的构造函数中;请参阅代码以获取其他选项。

use PracticalAfas\Client\RestCurlClient;
$client = new RestCurlClient( [ 'customerId' => 12345, 'appToken' => '64CHARS' ] );

$result_as_json_string = $client->callAfas(
  'GET',
  'connectors/MyGetConnectorName',
  [ 'take' => 1000,
    'filterfieldids' => 'SomeCategory,Updated',
    'filtervalues' => 'CategName,2017-01-01T16:00:00',
    'operatortypes' => '1,4',
    'orderbyfieldids' => '-Updated'
  ]
);
$attachment = $client->callAfas('GET', 'subjectconnector/123');

// This is inserting a new organisation with only its name filled:
$client->callAfas('POST', 'connectors/KnOrganisation', [], '{"KnOrganisation":{"Element":{ "Fields":{"MatchOga":0,"Nm":MyCompany Ltd."}}}}'

SoapAppClient示例

以下几乎等同于上述REST示例(除了它返回XML字符串而不是JSON字符串)。请注意,这不是PHP 'Soapclient'类;它是SOAPClient的包装器。

use PracticalAfas\Client\SoapAppClient;
$client = new SoapAppClient( [ 'customerId' => 12345, 'appToken' => '64CHARS' ] );

$result_as_xml_string = $client->callAfas(
  'get',
  'GetDataWithOptions',
  [ 'connectorId' => 'MyGetConnectorName',
    'take' => 1000,
    'filtersXml' => '<Filters><Filter><Field FieldId="SomeCategory" OperatorType="1">CategName</Field>
      <Field FieldId="Updated" OperatorType="4">2017-01-01T16:00:00</Field></Filter></Filters>',
    'options' => '<options><Index><Field FieldId="Updated" OperatorType="0"/></Index>
      <Outputoptions>3</Outputoptions><Outputmode>1</Outputmode><Metadata>0</Metadata></options>',
  ]
);
$attachment = $client->callAfas('subject', 'GetAttachment', [ 'subjectID' => 123 ] );

$client->callAfas('update', 'Execute', [ 'connectorType' => 'KnOrganisation', 'dataXml => '<KnOrganisation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Element><Fields Action="insert"><MatchOga>0</MatchOga><Nm>MyCompany Ltd.</Nm></Fields></Element></KnOrganisation>' ] );

Connection

Connection包装了一个客户端,抽象了所有非客户端特定的参数验证/数据处理。它有自己的过滤器语法。它有两个重要方法:sendData()用于包装AFAS的更新连接器,getData()用于包装所有其他连接器。(所有其他方法都是您可能永远不需要的获取器和设置器。)

上述示例的等效方法是

use PracticalAfas\Connection;
use PracticalAfas\Client\RestCurlClient;
$client = new RestCurlClient( [ 'customerId' => 12345, 'appToken' => '64CHARS' ] );
$connection = new Connection($client);

// A (more common) example for a Get connector with simple filter, returning an
// array of rows:
$result_as_array = $connection->getData('MyGetConnectorName',  [ 'SomeCategory' => 'CategName' ] );

// The equivalent of above:
$result_as_string = $connection->getData(
  'MyGetConnectorName',
  [ 'SomeCategory' => 'CategName',
    [ 'Updated' => '2017-01-01T16:00:00', '#op' => Connection::OP_LARGER_THAN ],
  ],
  Connection::GET_FILTER_AND,
  [ 'take => 1000,
    'orderbyfieldids' => '-Updated',
    'options' => ['Outputmode' => Connection::GET_OUTPUTMODE_LITERAL ]
  ]
);
$attachment = $connection->getData(123, [], Connection::DATA_TYPE_SUBJECT);

$connection->sendData(['name' => 'MyCompany Ltd.'], 'KnOrganisation', 'insert');

...因此,如果'Outputmode'选项没有提供,getData()将返回数据行数组(即,XML/JSON字符串为您解码)。

进一步阅读

获取连接器

更新连接器/UpdateObject类

开发者提示

作者

  • Roderik Muit - Wyz - 重写,再重写,再再重写。

我喜欢向世界贡献开源软件,我喜欢开放半封闭的文档系统。这曾是2012年AFAS的情况,但现在它已经变得更好。如果您觉得这有用或有贡献,请告诉我。如果您需要完成集成工作,请与我联系。(我有其他几个系统的经验。)

许可证

本库遵循MIT许可证 - 有关详细信息,请参阅LICENSE.md文件。

致谢

  • 向Philip Vergunst和Nathan Vergunst-Kolozsvári致敬,他们来自Your source - 他们编写了第一个版本的PHP代码,至少能正确交换数据,这一定不容易。

  • Yellowgrape致以敬意,他们是电子商务策略/营销/设计的专业人士。虽然我在业余时间免费制作了这个软件,但如果没有他们,我就不会有AFAS的经验。