This commit is contained in:
Björn Fromme
2023-07-07 18:19:15 +02:00
parent 1e9d1c5ac4
commit 305699b1ac
28 changed files with 1428 additions and 63 deletions
+131
View File
@@ -0,0 +1,131 @@
<?php
namespace App\BusProNet;
use App\BusProNet\Model\CrmAttributeSelection;
use App\BusProNet\Model\Profile;
use App\BusProNet\Model\ErrorResponse;
use App\BusProNet\Model\Result;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class ApiClient
{
private array $config;
public function __construct(
private readonly HttpClientInterface $httpClient,
private readonly SerializerInterface $serializer,
array $options
) {
$this->config = $this->resolveOptions($options);
}
/**
* @throws ApiClientException
*/
public function getProfile(string $email, string $password): mixed
{
$data = [
'anfrage' => [
'user' => $this->config['bpn_username'],
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], 'KUNDENKONTO'),
'satz' => ['@typ' => 'KUNDENKONTO'],
'art' => 'Adressdaten',
'email' => $email,
'passwort' => md5($password),
],
];
$body = $this
->serializer
->serialize($data, 'xml')
;
try {
$response = $this->httpClient->request('GET', $this->config['bpn_url'], [
'query' => [
'operation' => $body,
]
]);
$xml = $response->getContent();
if (str_contains($xml, 'HINWEIS')) {
return $this->serializer->deserialize($xml, ErrorResponse::class, 'xml');
}
return $this->serializer->deserialize($xml, Profile::class, 'xml');
} catch (\Throwable $e) {
}
throw new ApiClientException($e->getMessage());
}
public function updateProfile(): void
{}
/**
* @throws ApiClientException
*/
public function getCrmSelection(string $email, string $password): mixed
{
$data = [
'anfrage' => [
'user' => $this->config['bpn_username'],
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], 'KUNDENKONTO'),
'satz' => ['@typ' => 'KUNDENKONTO'],
'art' => 'SelektionCRM',
'email' => $email,
'passwort' => md5($password),
],
];
$body = $this
->serializer
->serialize($data, 'xml')
;
try {
$response = $this->httpClient->request('GET', $this->config['bpn_url'], [
'query' => [
'operation' => $body,
]
]);
$xml = $response->getContent();
if (str_contains($xml, 'HINWEIS')) {
return $this->serializer->deserialize($xml, ErrorResponse::class, 'xml');
}
return $this->serializer->deserialize($xml, CrmAttributeSelection::class, 'xml');
} catch (\Throwable $e) {
}
throw new ApiClientException($e->getMessage());
}
/**
* @Creates key for BusPro API access according to documentation
*/
private function createKey(string $username, string $password, string $type): string
{
$date = (new \DateTimeImmutable())->format('Ymd');
return md5($username.$password.$date.$type);
}
private function resolveOptions(array $options): array
{
$optionsResolver = new OptionsResolver();
$optionsResolver->setRequired(['bpn_url', 'bpn_username', 'bpn_password']);
return $optionsResolver->resolve($options);
}
}
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace App\BusProNet;
class ApiClientException extends \Exception
{
}
+68
View File
@@ -0,0 +1,68 @@
<?php
namespace App\BusProNet\Model;
use Symfony\Component\Serializer\Annotation\SerializedName;
class Address
{
#[SerializedName('strasse')]
private ?string $street = null;
#[SerializedName('plz')]
private ?string $postCode = null;
#[SerializedName('ort')]
private ?string $city = null;
#[SerializedName('land')]
private ?string $country = null;
public function getStreet(): ?string
{
return $this->street;
}
public function setStreet(?string $street): static
{
$this->street = $street;
return $this;
}
public function getPostCode(): ?string
{
return $this->postCode;
}
public function setPostCode(?string $postCode): static
{
$this->postCode = $postCode;
return $this;
}
public function getCity(): ?string
{
return $this->city;
}
public function setCity(?string $city): static
{
$this->city = $city;
return $this;
}
public function getCountry(): ?string
{
return $this->country;
}
public function setCountry(?string $country): static
{
$this->country = $country;
return $this;
}
}
+53
View File
@@ -0,0 +1,53 @@
<?php
namespace App\BusProNet\Model;
use Symfony\Component\Serializer\Annotation\SerializedName;
class Communication
{
#[SerializedName('telefonprivat')]
private ?string $phone = null;
#[SerializedName('telefonmobil')]
private ?string $mobile = null;
#[SerializedName('email')]
private ?string $email = null;
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(?string $phone): static
{
$this->phone = $phone;
return $this;
}
public function getMobile(): ?string
{
return $this->mobile;
}
public function setMobile(?string $mobile): static
{
$this->mobile = $mobile;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(?string $email): static
{
$this->email = $email;
return $this;
}
}
+66
View File
@@ -0,0 +1,66 @@
<?php
namespace App\BusProNet\Model;
use Symfony\Component\Serializer\Annotation\Ignore;
use Symfony\Component\Serializer\Annotation\SerializedName;
class CrmAttribute
{
#[SerializedName('@id')]
private ?int $id = null;
#[SerializedName('@bezeichnung')]
private ?string $label = null;
#[SerializedName('@auswahl')]
private ?string $selectedAsString = null;
public function getId(): ?int
{
return $this->id;
}
public function setId(?int $id): static
{
$this->id = $id;
return $this;
}
public function getLabel(): ?string
{
return $this->label;
}
public function setLabel(?string $label): static
{
$this->label = $label;
return $this;
}
public function getSelectedAsString(): ?string
{
return $this->selectedAsString;
}
public function setSelectedAsString(?string $selectedAsString): static
{
$this->selectedAsString = $selectedAsString;
return $this;
}
public function isSelected(): bool
{
return 'true' === strtolower($this->selectedAsString);
}
public function setSelected(bool $selected): static
{
$this->selectedAsString = $selected ? 'True' : 'False';
return $this;
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\BusProNet\Model;
use Symfony\Component\Serializer\Annotation\SerializedPath;
class CrmAttributeSelection
{
#[SerializedPath('[selektionsmerkmale][selektionsgruppe]')]
private ?array $selectionGroups = null;
/**
* @return CrmAttributeSelectionGroup[]|null
*/
public function getSelectionGroups(): ?array
{
return $this->selectionGroups;
}
/**
* @param CrmAttributeSelectionGroup[]|null $selectionGroups
* @return $this
*/
public function setSelectionGroups(?array $selectionGroups): static
{
$this->selectionGroups = $selectionGroups;
return $this;
}
}
@@ -0,0 +1,45 @@
<?php
namespace App\BusProNet\Model;
use Symfony\Component\Serializer\Annotation\SerializedName;
class CrmAttributeSelectionGroup
{
#[SerializedName('@bezeichnung')]
private ?string $label = null;
#[SerializedName('selektion')]
private ?array $attributes = null;
public function getLabel(): ?string
{
return $this->label;
}
public function setLabel(?string $label): static
{
$this->label = $label;
return $this;
}
/**
* @return CrmAttribute[]|null
*/
public function getAttributes(): ?array
{
return $this->attributes;
}
/**
* @param CrmAttribute[]|null $attributes
* @return $this
*/
public function setAttributes(?array $attributes): static
{
$this->attributes = $attributes;
return $this;
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App\BusProNet\Model;
use Symfony\Component\Serializer\Annotation\SerializedPath;
class ErrorResponse
{
#[SerializedPath('[satz][nr]')]
private ?string $code;
#[SerializedPath('[satz][text]')]
private ?string $type;
public function getCode(): ?string
{
return $this->code;
}
public function setCode(?string $code): static
{
$this->code = $code;
return $this;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(?string $type): static
{
$this->type = $type;
return $this;
}
}
+161
View File
@@ -0,0 +1,161 @@
<?php
namespace App\BusProNet\Model;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Annotation\SerializedPath;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Profile
{
#[SerializedPath('[idadresse]')]
private ?int $addressId = null;
#[SerializedPath('[idperson]')]
private ?int $personId = null;
#[SerializedPath('[adressdaten][name]')]
private ?string $name = null;
#[SerializedPath('[adressdaten][vorname]')]
private ?string $firstName = null;
#[SerializedPath('[adressdaten][anrede]')]
private ?string $salutation = null;
#[SerializedPath('[adressdaten][titel]')]
private ?string $title = null;
#[SerializedPath('[adressdaten][geschlecht]')]
private ?string $gender = null;
#[SerializedPath('[adressdaten][geburtsdatum]')]
#[Context([DateTimeNormalizer::FORMAT_KEY => 'd.m.Y'])]
private ?\DateTimeImmutable $dateOfBirth = null;
#[SerializedPath('[adressdaten][anschrift]')]
private ?Address $address = null;
#[SerializedPath('[adressdaten][kommunikation]')]
private ?Communication $communication = null;
public function getAddressId(): ?int
{
return $this->addressId;
}
public function setAddressId(?int $addressId): static
{
$this->addressId = $addressId;
return $this;
}
public function getPersonId(): ?int
{
return $this->personId;
}
public function setPersonId(?int $personId): static
{
$this->personId = $personId;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): static
{
$this->name = $name;
return $this;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): static
{
$this->firstName = $firstName;
return $this;
}
public function getSalutation(): ?string
{
return $this->salutation;
}
public function setSalutation(?string $salutation): static
{
$this->salutation = $salutation;
return $this;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(?string $title): static
{
$this->title = $title;
return $this;
}
public function getGender(): ?string
{
return $this->gender;
}
public function setGender(?string $gender): static
{
$this->gender = $gender;
return $this;
}
public function getDateOfBirth(): \DateTimeImmutable
{
return $this->dateOfBirth;
}
public function setDateOfBirth(?\DateTimeImmutable $dateOfBirth): static
{
$this->dateOfBirth = $dateOfBirth;
return $this;
}
public function getAddress(): ?Address
{
return $this->address;
}
public function setAddress(?Address $address): static
{
$this->address = $address;
return $this;
}
public function getCommunication(): ?Communication
{
return $this->communication;
}
public function setCommunication(?Communication $communication): static
{
$this->communication = $communication;
return $this;
}
}