hibpa->bpdVersion; } public function getBankCode() { return $this->hibpa->kreditinstitutskennung->kreditinstitutscode; } public function getBankName() { return $this->hibpa->kreditinstitutsbezeichnung; } /** * @param string $type A business transaction type, represented by the segment name of the respective parameter * segment (Geschäftsvorfallparameter segment, aka. Segmentparametersegment). Example: 'HIKAZS'. * @return BaseSegment[] All parameter segments of that type ordered descendingly by version (newest first), * excluding such that are not explicitly implemented in this library (no AnonymousSegments). The returned array * is possibly empty if no versions offered by the bank are also supported by the library. */ public function getAllSupportedParameters(string $type): array { return array_filter($this->parameters[$type] ?? [], function (BaseSegment $segment) { return !($segment instanceof AnonymousSegment); }); } /** * @param string $type A business transaction type, represented by the segment name of the respective parameter * segment (Geschäftsvorfallparameter segment, aka. Segmentparametersegment). Example: 'HIKAZS'. * @return BaseSegment|null The latest parameter segment that is explicitly implemented in this library (never an * AnonymousSegment), or null if none exists. */ public function getLatestSupportedParameters(string $type): ?BaseSegment { if (!array_key_exists($type, $this->parameters)) { return null; } foreach ($this->parameters[$type] as $segment) { if (!($segment instanceof AnonymousSegment)) { return $segment; } } return null; } /** * @param string $type A business transaction type, see above. * @return BaseSegment The latest parameter segment, never null. * @throws UnexpectedResponseException If no version exists. */ public function requireLatestSupportedParameters(string $type): BaseSegment { $result = $this->getLatestSupportedParameters($type); if ($result === null) { throw new UnexpectedResponseException( "The server does not support any $type versions implemented in this library"); } return $result; } /** * @param string $type A business transaction type, see above. * @param int $version The segment version of the business transaction. * @return bool If that version of the given transaction type is supported by the bank. */ public function supportsParameters(string $type, int $version): bool { foreach ($this->parameters[$type] as $segment) { if ($segment->getVersion() === $version) { return true; } } return false; } /** * @param SegmentInterface[] $requestSegments The segments that shall be sent to the bank. * @return string|null Identifier of the (first) segment that requires a TAN according to HIPINS, or null if none of * the segments require a TAN. */ public function tanRequiredForRequest(array $requestSegments): ?string { foreach ($requestSegments as $segment) { if ($this->tanRequired[$segment->getName()] ?? false) { return $segment->getName(); } } return null; } /** * @param SegmentInterface[] $requestSegments The segments that shall be sent to the bank. * @return string|null Identifier of the (first) segment that requires Verification of Payee according to HIPINS, or * null if none of the segments require verification. */ public function vopRequiredForRequest(array $requestSegments): ?string { /** @var HIVPPSv1 $hivpps */ $hivpps = $this->getLatestSupportedParameters('HIVPPS'); $vopRequiredTypes = $hivpps?->parameter?->vopPflichtigerZahlungsverkehrsauftrag; if ($vopRequiredTypes === null) { return null; } foreach ($requestSegments as $segment) { if (in_array($segment->getName(), $vopRequiredTypes)) { return $segment->getName(); } } return null; } /** * @return bool Whether the BPD indicates that the bank supports PSD2. */ public function supportsPsd2(): bool { return $this->supportsParameters('HITANS', 6); } /** * @param Message $response The dialog initialization response from the server. * @return BPD A new BPD instance with the extracted configuration data. */ public static function extractFromResponse(Message $response): BPD { $bpd = new BPD(); $bpd->hibpa = $response->requireSegment(HIBPAv3::class); // Extract the HIxyzS segments, which contain parameters that describe how (future) requests for the particular // type of business transaction have to look. foreach ($response->plainSegments as $segment) { $segmentName = $segment->getName(); if (strlen($segmentName) === 6 && $segmentName[5] === 'S') { $bpd->parameters[$segmentName][$segment->getVersion()] = $segment; krsort($bpd->parameters[$segmentName]); // Newest first. } } ksort($bpd->parameters); // Sort alphabetically, for easier debugging. // Extract from HIPINS which HKxyz requests will need a TAN. /** @var HIPINSv1 $hipins */ $hipins = $response->requireSegment(HIPINSv1::class); foreach ($hipins->parameter->geschaeftsvorfallspezifischePinTanInformationen as $typeInfo) { $bpd->tanRequired[$typeInfo->segmentkennung] = $typeInfo->tanErforderlich; } // Extract all TanModes from HIPINS. if ($bpd->supportsPsd2()) { /** @var HITANS[] $allHitans */ $allHitans = $bpd->getAllSupportedParameters('HITANS'); if (count($allHitans) === 0) { throw new UnexpectedResponseException( 'The server does not support any HITANS versions implemented in this library'); } foreach ($allHitans as $hitans) { $tanParams = $hitans->getParameterZweiSchrittTanEinreichung(); $bpd->singleStepTanModeAllowed = $tanParams->isEinschrittVerfahrenErlaubt(); foreach ($tanParams->getVerfahrensparameterZweiSchrittVerfahren() as $verfahren) { if (!array_key_exists($verfahren->getId(), $bpd->allTanModes)) { $bpd->allTanModes[$verfahren->getId()] = $verfahren; } } } } return $bpd; } }