config = $this->resolveOptions($options); } /** * @throws ApiClientException */ public function getPersonalData(string $email, string $password): Notification|PersonalData { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => 'Adressdaten', 'email' => $email, 'passwort' => $password, ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data); } /** * @throws ApiClientException */ public function register(RegistrationData $registrationData): Notification { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => 'Adresse_Neu', 'adressdaten' => [ 'geschlecht' => $registrationData->gender, 'vorname' => $registrationData->firstName, 'name' => $registrationData->name, 'kommunikation' => [ 'email' => $registrationData->email, ], ], ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data); } /** * @throws ApiClientException */ public function resetPassword(string $email): Notification { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => 'Passwort_Anfrage', 'email' => $email, ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data); } /** * @throws ApiClientException */ public function updatePersonalData( string $email, string $password, PersonalData $personalData, bool $debug = false, ): Notification|PersonalData { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => 'Adressdaten_Ändern', 'email' => $email, 'passwort' => $password, 'idadresse' => $personalData->addressId, 'adressdaten' => $personalData->toPayload(), ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data, $debug); } /** * @throws ApiClientException */ public function updateNewsletterRegistration(string $email, string $password, PersonalData $personalData): Notification|PersonalData { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => 'Newsletter', 'email' => $email, 'passwort' => $password, 'idadresse' => $personalData->addressId, 'newsletter' => [ 'email' => $email, 'anmeldung' => $personalData->communication->newsletter ? 'True' : 'False', ], ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data); } /** * @throws ApiClientException */ public function getBookings(string $email, string $password): Notification|BaseData { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => 'Vorgänge', 'email' => $email, 'passwort' => $password, ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data); } /** * @throws ApiClientException */ public function getBooking(string $email, string $password, int $id): Notification|Booking { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => 'Vorgang_Details', 'email' => $email, 'passwort' => $password, 'idbuchung' => $id, ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data); } /** * @throws ApiClientException */ public function updateBooking(BookingData $formData, bool $debug = false): Notification|BookingUpdate { $payload = (new BookingDataProcessor())->createUpdateRequestPayload($formData); $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_BOOKING_UPDATE), 'satz' => ['@typ' => static::TYPE_BOOKING_UPDATE], 'buchungsart' => 'Buchung', ...$payload, ]; return $this->sendRequest(static::TYPE_BOOKING_UPDATE, $data, $debug); } /** * @throws ApiClientException */ public function getMutableData(int $id): Notification|BaseData { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_MUTABLE_DATA), 'satz' => ['@typ' => static::TYPE_MUTABLE_DATA], 'art' => 'Vorgang_Details', 'idreise' => $id, ]; return $this->sendRequest(static::TYPE_MUTABLE_DATA, $data); } /** * @throws ApiClientException */ public function getAvailabilities(int $id): Notification|BaseData { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_AVAILABILITY), 'satz' => ['@typ' => static::TYPE_AVAILABILITY], 'idreise' => $id, ]; return $this->sendRequest(static::TYPE_AVAILABILITY, $data); } /** * @throws ApiClientException */ public function getCrmAttributes(string $email, string $password): Notification|CrmAttributes { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => 'SelektionCRM', 'email' => $email, 'passwort' => $password, ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data); } /** * @throws ApiClientException */ public function getBaseData(string $type): Notification|BaseData { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], $type), 'satz' => ['@typ' => $type], ]; return $this->sendRequest($type, $data); } /** * @throws ApiClientException */ public function getDocuments(string $email, string $password, int $id, string $type): mixed { $data = [ 'user' => $this->config['bpn_username'], 'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA), 'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA], 'art' => $type, 'email' => $email, 'passwort' => $password, 'idbuchung' => $id, ]; return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data); } /** * @throws ApiClientException */ private function sendRequest(string $type, array $data, bool $debug = false): mixed { $requestId = date(DATE_ATOM).uniqid(); $body = $this ->serializer ->serialize($data, 'xml', [ XmlEncoder::ROOT_NODE_NAME => 'anfrage', XmlEncoder::ENCODING => 'UTF-8', ]) ; $this->logger->info('Sending request to BPN API', [ 'requestId' => $requestId, ]); if (true === $debug || true === $this->config['debug']) { $this->dumpXmlToFile('request', $requestId, $body); } $socket = $this->connect( $this->config['bpn_api_ip'], $this->config['bpn_api_port'], $this->config['max_retries'] ); $this->send($socket, $body); $response = $this->receive($socket); $this->disconnect($socket); // message length (10 bytes) is prepended to actual message $xml = substr($response, 10); if (true === $debug || true === $this->config['debug']) { $this->dumpXmlToFile('response', $requestId, $xml); } try { return $this->responseParser->parseXmlString($type, $xml); } catch (ResponseParserException $e) { $this->dumpXmlToFile('response', $requestId, $xml); } $this->logger->error('Unexpected response received from API', [ 'request_id' => $requestId, ]); throw new ApiClientException('Unexpected response received from API'); } private function dumpXmlToFile(string $type, string $requestId, string $body): void { try { $this->xmlDump->write($requestId.'_'.$type.'.xml', $body); } catch (FilesystemException $e) { } } 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_username', 'bpn_password', 'bpn_api_ip', 'bpn_api_port', ]); $optionsResolver->setDefaults([ 'max_retries' => 25, 'debug' => false, ]); return $optionsResolver->resolve($options); } }