Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP;
|
||||
|
||||
class Config
|
||||
{
|
||||
private $clientid;
|
||||
|
||||
private $orgunitid;
|
||||
|
||||
private $orgunitguid;
|
||||
|
||||
private $soapurl;
|
||||
|
||||
/**
|
||||
* Config constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*
|
||||
* @throws PostAtException
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$requiredSettings = [
|
||||
'soapurl',
|
||||
'clientid',
|
||||
'orgunitid',
|
||||
'orgunitguid',
|
||||
];
|
||||
|
||||
foreach ($requiredSettings as $setting) {
|
||||
if (empty($config[$setting])) {
|
||||
throw new PostAtException(
|
||||
'Configuration of the Post.at module is invalid. Please verify the configuration.'
|
||||
);
|
||||
}
|
||||
|
||||
$this->$setting = $config[$setting];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string The URL of the SOAP API endpoint.
|
||||
*/
|
||||
public function getSoapUrl(): string
|
||||
{
|
||||
return $this->soapurl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ClientId (a.k.a DebitorID).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getClientId(): int
|
||||
{
|
||||
return (int) $this->clientid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OrganisationID; unique for a customerID.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOrgUnitId(): int
|
||||
{
|
||||
return (int) $this->orgunitid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique GUID of the customerID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOrgUnitGuid(): string
|
||||
{
|
||||
return $this->orgunitguid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP\Method;
|
||||
|
||||
use Xentral\Modules\Postat\SOAP\MethodInterface;
|
||||
use Xentral\Modules\Postat\SOAP\ParameterInterface;
|
||||
use Xentral\Modules\Postat\SOAP\PostAtClient;
|
||||
use Xentral\Modules\Postat\SOAP\PostAtException;
|
||||
use Xentral\Modules\Postat\SOAP\Result\AllowedServicesResult;
|
||||
|
||||
class GetAllowedServicesForCountry implements MethodInterface
|
||||
{
|
||||
/** @var PostAtClient */
|
||||
private $postAtClient;
|
||||
|
||||
/** @var array Array of ISO 3166 ALPHA-2 country codes. */
|
||||
private $countries;
|
||||
|
||||
/**
|
||||
* AllowedServicesForCountry constructor.
|
||||
*
|
||||
* @param PostAtClient $postAtClient
|
||||
*/
|
||||
public function __construct(PostAtClient $postAtClient)
|
||||
{
|
||||
$this->postAtClient = $postAtClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the API endpoint.
|
||||
*
|
||||
* @param ParameterInterface $countries
|
||||
*
|
||||
* @return AllowedServicesResult
|
||||
* @throws PostAtException
|
||||
*/
|
||||
public function call(ParameterInterface $countries)
|
||||
{
|
||||
$this->countries = $countries->getData();
|
||||
|
||||
$response = $this->postAtClient->call($this);
|
||||
|
||||
return new AllowedServicesResult($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content for the SOAP body element.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function getBody(): array
|
||||
{
|
||||
return [
|
||||
'countryList' => $this->countries,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP\Method;
|
||||
|
||||
use Xentral\Modules\Postat\SOAP\MethodInterface;
|
||||
use Xentral\Modules\Postat\SOAP\ParameterInterface;
|
||||
use Xentral\Modules\Postat\SOAP\PostAtClient;
|
||||
use Xentral\Modules\Postat\SOAP\PostAtException;
|
||||
|
||||
class ImportShipment implements MethodInterface
|
||||
{
|
||||
/** @var PostAtClient */
|
||||
private $postAtClient;
|
||||
|
||||
/** @var array */
|
||||
private $shipmentRow;
|
||||
|
||||
/**
|
||||
* ImportShipment constructor.
|
||||
*
|
||||
* @param PostAtClient $postAtClient
|
||||
*/
|
||||
public function __construct(PostAtClient $postAtClient)
|
||||
{
|
||||
$this->postAtClient = $postAtClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the SOAP API with the given data.
|
||||
*
|
||||
* @param ParameterInterface $shipmentRow
|
||||
*
|
||||
* @throws PostAtException
|
||||
*
|
||||
* @return array $data
|
||||
*/
|
||||
public function call(ParameterInterface $shipmentRow)
|
||||
{
|
||||
$this->shipmentRow = $shipmentRow->getData();
|
||||
|
||||
return $this->postAtClient->call($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getBody(): array
|
||||
{
|
||||
return $this->shipmentRow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP;
|
||||
|
||||
/**
|
||||
* Each API method call should be represented by a class that implements this interface.
|
||||
*
|
||||
* The name of the class must be identical with the name of the API method found
|
||||
* in the Post.at SOAP API documentation.
|
||||
*
|
||||
* See the existing API method implementations in the Postat/SOAP/Method/ directory.
|
||||
*/
|
||||
interface MethodInterface
|
||||
{
|
||||
/**
|
||||
* MethodInterface constructor.
|
||||
*
|
||||
* @param PostAtClient $client
|
||||
*/
|
||||
public function __construct(PostAtClient $client);
|
||||
|
||||
/**
|
||||
* @param ParameterInterface $data Data needed for the body of the SOAP call.
|
||||
*/
|
||||
public function call(ParameterInterface $data);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP\Parameter;
|
||||
|
||||
use Xentral\Modules\Postat\SOAP\ParameterInterface;
|
||||
use Xentral\Modules\Postat\SOAP\PostAtException;
|
||||
|
||||
class Countries implements ParameterInterface
|
||||
{
|
||||
private $countries;
|
||||
|
||||
public function __construct(array $countries)
|
||||
{
|
||||
if (!is_array($countries)) {
|
||||
throw new PostAtException('The given target countries are invalid.');
|
||||
}
|
||||
|
||||
$this->countries = $countries;
|
||||
}
|
||||
|
||||
public function getData(): array
|
||||
{
|
||||
return $this->countries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP\Parameter;
|
||||
|
||||
use Xentral\Modules\Postat\SOAP\ParameterInterface;
|
||||
use Xentral\Modules\Postat\SOAP\PostAtException;
|
||||
|
||||
class ShipmentRow implements ParameterInterface
|
||||
{
|
||||
/** var array $shipmentRow */
|
||||
private $shipmentRow;
|
||||
|
||||
public function __construct(array $shipmentRow)
|
||||
{
|
||||
if (empty($shipmentRow['row'])) {
|
||||
throw new PostAtException('The given shipment data is invalid');
|
||||
}
|
||||
|
||||
$this->shipmentRow = $shipmentRow;
|
||||
}
|
||||
|
||||
public function getData(): array
|
||||
{
|
||||
return $this->shipmentRow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP;
|
||||
|
||||
/**
|
||||
* Validate the data given to the constructor.
|
||||
*
|
||||
* In case of validation errors, the class should throw a PostAtException.
|
||||
*/
|
||||
interface ParameterInterface
|
||||
{
|
||||
public function __construct(array $data);
|
||||
|
||||
public function getData(): array;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP;
|
||||
|
||||
use Xentral\Components\Logger\Logger;
|
||||
|
||||
class PostAtClient
|
||||
{
|
||||
/** @var */
|
||||
private $apiConfig;
|
||||
|
||||
/** @var Logger */
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* PostAtClient constructor.
|
||||
*
|
||||
* @param $apiConfig
|
||||
* @param Logger $logger
|
||||
*/
|
||||
public function __construct(Config $apiConfig, Logger $logger)
|
||||
{
|
||||
$this->apiConfig = $apiConfig;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a SOAP API call.
|
||||
*
|
||||
* @param MethodInterface $method
|
||||
*
|
||||
* @throws PostAtException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function call(MethodInterface $method)
|
||||
{
|
||||
$body = $method->getBody();
|
||||
|
||||
$body = $this->appendConfiguration($body);
|
||||
|
||||
try {
|
||||
$client = new \SoapClient($this->apiConfig->getSoapUrl());
|
||||
} catch (\SoapFault $exception) {
|
||||
$this->logger->error('Cannot connect to the Post.at SOAP API.', ['exception' => $exception]);
|
||||
|
||||
// The exception thrown above would be too technical for the end
|
||||
// user, so use a more user-friendly message instead.
|
||||
throw new PostAtException(
|
||||
'Configuration of the Post.at module is invalid. Please verify the configuration.'
|
||||
);
|
||||
}
|
||||
|
||||
$response = $client->__soapCall($this->getClassName($method), [$body]);
|
||||
|
||||
if ($response->errorCode !== null) {
|
||||
// A user-friendly error such as "This package type is not available for the chosen target country".
|
||||
throw new PostAtException("{$response->errorCode} - {$response->errorMessage}");
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends SOAP body entries that are required for every request.
|
||||
*
|
||||
* - clientID: DebitorID
|
||||
* - orgUnitID: OrganisationID; unique for a customerID
|
||||
* - orgUnitGuid: Unique GUID of the customerID
|
||||
*
|
||||
* For some reason the location of these entries is different within the SOAP
|
||||
* body structure depending on which API method is used. This function attempts
|
||||
* to cover all use cases.
|
||||
*
|
||||
* @param array $body
|
||||
*
|
||||
* @return array $body
|
||||
*/
|
||||
private function appendConfiguration(array $body): array
|
||||
{
|
||||
if (isset($body['row'])) {
|
||||
$body['row']['ClientID'] = $this->apiConfig->getClientId();
|
||||
$body['row']['OrgUnitID'] = $this->apiConfig->getOrgUnitId();
|
||||
$body['row']['OrgUnitGuid'] = $this->apiConfig->getOrgUnitGuid();
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
if (isset($body['addresses'])) {
|
||||
// TODO Add this once one of the address API methods gets implemented.
|
||||
}
|
||||
|
||||
// In simple requests the entries are at the root of the body.
|
||||
$body['clientID'] = $this->apiConfig->getClientId();
|
||||
$body['orgUnitID'] = $this->apiConfig->getOrgUnitId();
|
||||
$body['orgUnitGuid'] = $this->apiConfig->getOrgUnitGuid();
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the short name of the class (the part without the namespace).
|
||||
*
|
||||
* @param $method
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getClassName($method): string
|
||||
{
|
||||
return (new \ReflectionClass($method))->getShortName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP;
|
||||
|
||||
class PostAtException extends \Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP\Result;
|
||||
|
||||
class AllowedServicesResult
|
||||
{
|
||||
/** @var The raw data received from the SOAP API. */
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* AllowedServicesResult constructor.
|
||||
*
|
||||
* @param $data
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get two-level associative array of service codes and the service names.
|
||||
*
|
||||
* Can be used for example to generate options for a <select> element.
|
||||
*
|
||||
* [
|
||||
* 45 => [
|
||||
* 'name' => 'Premium Int. Outbound B2B',
|
||||
* 'features' => [
|
||||
* '007' => '24-Stundenpaket',
|
||||
* '022' => 'Nachnahme COD International',
|
||||
* '024' => 'Zerbrechlich international',
|
||||
* '063' => 'Höherversicherung',
|
||||
* '065' => 'Postlagernd',
|
||||
* '074' => 'Gefahrgut - begrenzte Menge (LQ)',
|
||||
* ],
|
||||
* ],
|
||||
* 46 => [
|
||||
* 'name' => 'Post Express International',
|
||||
* 'features' => [],
|
||||
* ],
|
||||
* etc...
|
||||
* ]
|
||||
*
|
||||
* @return array $options
|
||||
*/
|
||||
public function toOptionsArray(): array
|
||||
{
|
||||
$services = $this->data->GetAllowedServicesForCountryResult->CarrierServiceRow;
|
||||
|
||||
$options = [];
|
||||
foreach ($services as $service) {
|
||||
$features = [];
|
||||
foreach ($service->FeatureList->AdditionalInformationResult as $test) {
|
||||
$features[$test->ThirdPartyID] = $test->Name;
|
||||
}
|
||||
|
||||
$options[$service->ThirdPartyID] = [
|
||||
'name' => $service->Name,
|
||||
'features' => $features,
|
||||
];
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP;
|
||||
|
||||
use Xentral\Modules\Postat\SOAP\Method\GetAllowedServicesForCountry;
|
||||
use Xentral\Modules\Postat\SOAP\Method\ImportShipment;
|
||||
use Xentral\Modules\Postat\SOAP\Parameter\Countries;
|
||||
use Xentral\Modules\Postat\SOAP\Parameter\ShipmentRow;
|
||||
use Xentral\Modules\Postat\SOAP\Result\AllowedServicesResult;
|
||||
|
||||
/**
|
||||
* Constructs the individual methods that the SOAP API service exposes.
|
||||
*/
|
||||
class SoapService
|
||||
{
|
||||
/** @var PostAtClient */
|
||||
private $postAtClient;
|
||||
|
||||
/**
|
||||
* Methods constructor.
|
||||
*
|
||||
* @param PostAtClient $postAtClient
|
||||
*/
|
||||
public function __construct(PostAtClient $postAtClient)
|
||||
{
|
||||
$this->postAtClient = $postAtClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available postal services for the given countries.
|
||||
*
|
||||
* @param array $countries Array of ISO 3166 ALPHA-2 country codes.
|
||||
*
|
||||
* @throws PostAtException
|
||||
*
|
||||
* @return AllowedServicesResult
|
||||
*/
|
||||
public function getAllowedServicesForCountry(array $countries): AllowedServicesResult
|
||||
{
|
||||
$countries = new Countries($countries);
|
||||
$soapMethod = new GetAllowedServicesForCountry($this->postAtClient);
|
||||
|
||||
return $soapMethod->call($countries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a shipping label for the given package and chosen delivery type.
|
||||
*
|
||||
* The $shipmentRow parameter is an associative array of the delivery details:
|
||||
*
|
||||
* [
|
||||
* 'row' => [
|
||||
* 'PrinterObject' => [
|
||||
* 'LabelFormatID' => '100x150',
|
||||
* 'LanguageID' => 'pdf',
|
||||
* 'PaperLayoutID' => '2xA5inA4'
|
||||
* ],
|
||||
* 'Number' => 'XEN-12345,
|
||||
* 'DeliveryServiceThirdPartyID' => 28,
|
||||
* etc...
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* See the official Post.at SOAP API documentation for further details.
|
||||
*
|
||||
* @param array $shipmentRow
|
||||
*
|
||||
* @throws PostAtException
|
||||
*
|
||||
* @return mixed The raw SOAP API result containing ImportShipmentResult.
|
||||
* See the official Post.at SOAP API documentation for details.
|
||||
*/
|
||||
public function importShipment(array $shipmentRow)
|
||||
{
|
||||
$shipmentRow = new ShipmentRow($shipmentRow);
|
||||
$soapMethod = new ImportShipment($this->postAtClient);
|
||||
|
||||
return $soapMethod->call($shipmentRow);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\Postat\SOAP;
|
||||
|
||||
use Xentral\Components\Logger\Logger;
|
||||
|
||||
/**
|
||||
* Factory for new SoapService instances.
|
||||
*
|
||||
* A dedicated factory is needed because the configuration for the SOAP API
|
||||
* service depends on the context where it is being used, and therefore the
|
||||
* configuration cannot be injected directly into it by the DI container.
|
||||
*/
|
||||
class SoapServiceFactory
|
||||
{
|
||||
private $logger;
|
||||
|
||||
public function __construct(Logger $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Post.at SOAP API service from the given config array.
|
||||
*
|
||||
* @param array $soapConfig
|
||||
*
|
||||
* @throws PostAtException
|
||||
*
|
||||
* @return SoapService
|
||||
*/
|
||||
public function fromConfigArray(array $soapConfig): SoapService
|
||||
{
|
||||
$soapConfig = new Config($soapConfig);
|
||||
|
||||
$client = new PostAtClient($soapConfig, $this->logger);
|
||||
|
||||
return new SoapService($client);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user