diff --git a/lib/Fhp/Response/GetVariables.php b/lib/Fhp/Response/GetVariables.php index f96f20fb..218a4172 100644 --- a/lib/Fhp/Response/GetVariables.php +++ b/lib/Fhp/Response/GetVariables.php @@ -2,7 +2,8 @@ namespace Fhp\Response; -use Fhp\Parser\Exception\MT940Exception; +use Fhp\Segment\BaseSegment; +use Fhp\Segment\HITANS\HITANS; /** * Class GetVariables @@ -22,121 +23,18 @@ public function getSupportedTanMechanisms() { return $this->get()->tanModes; } - public function parseTanModes($segments) + private function parseTanModes($segments) { - // extracted from https://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Security_Sicherheitsverfahren_PINTAN_2018-02-23_final_version.pdf - // Zwei-Schritt-TAN-Einreichung, Parameter - // - // 1. Segmentkopf: - // Beispiel: HITANS:169:6:4 - // 1.1. Segmentkennung (HITANS) - // 1.2. Segmentnummer - // 1.3. Segmentversion - // 1.4. Bezugssegment - // 2. Maximale Anzahl Aufträge (int(3)) - // 3. Anzahl Signaturen mindestens (0, 1, 2, 3) - // 4. Sicherheitsklasse (0, 1, 2, 3, 4) - // 5. Parameter Zwei-Schritt-TAN Einreichung - // 5.1. Einschrittverfahren erlaubt [jn] (V1-V6) - // 5.2. Mehr als ein TANpflichtiger Auftrag pro Nachricht erlaubt [jn] (V1-V6) - // 5.3. AuftragsHashwertverfahren [code] (V1-V6) - // 5.4. Sicherheitsprofil Banken-Signatur bei HITAN [code] (V1) - // 5.4. Verfahrensparameter ZweiSchritt-Verfahren (V2-V6) - // 5.5. Verfahrensparameter ZweiSchritt-Verfahren (V1) - // Sparkasse has 5 elements but declares version 6 $result = array(); foreach ($segments as $segmentRaw) { - $segment = $this->splitSegment($segmentRaw); - - $segmentHeader = $this->splitDeg($segment[0]); - $version = (int) $segmentHeader[2]; // 1.3 - - $paramsIndex = count($segment) - 1; - $params = $this->splitDeg($segment[$paramsIndex]); - - // 5. Parameter Zwei-Schritt-TAN-Einreichung: - // 5.4/5.5 s. Verfahrensparameter Zwei-Schritt-Verfahren - // Beispiel: J:N:0:910:2:HHD1.3.0:::chipTAN manuell:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:911:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:912:2:HHD1.3.2USB:HHDUSB1:1.3.2:chipTAN-USB:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:913:2:Q1S:Secoder_UC:1.2.0:chipTAN-QR:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:920:2:smsTAN:::smsTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:5:921:2:pushTAN:::pushTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:2:900:2:iTAN:::iTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:0" - // -> Version 6 - // J:N:0: (-> $processParamsOffset = 4) - // 910:2:HHD1.3.0:::chipTAN manuell:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1: - // 911:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1: - // 912:2:HHD1.3.2USB:HHDUSB1:1.3.2:chipTAN-USB:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1: - // 913:2:Q1S:Secoder_UC:1.2.0:chipTAN-QR:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1: - // 920:2:smsTAN:::smsTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:5: - // 921:2:pushTAN:::pushTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:2: - // 900:2:iTAN:::iTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:0" - - $processParamsOffset = $this->getTanProcessParamsOffsetForVersion($version); - $processNameIndex = $this->getTanProcessNameIndexForVersion($version); - $processParamElementCount = $this->getTanProcessParamElementCountForVersion($version); - array_splice($params, 0, $processParamsOffset); - - $paramCount = count($params); - if ($paramCount % $processParamElementCount === $processParamElementCount - 1) { - // From version 3 on, the last parameter is optional and may be omitted in the last group of HITANS parameters - // see https://github.com/nemiah/phpFinTS/pull/40#issuecomment-532362814 - $paramCount++; - } - - $paramBlockIterations = $paramCount / $processParamElementCount; - for ($i = 0; $i < $paramBlockIterations; $i++) { - $blockOffset = $i * $processParamElementCount; - $num = $params[$blockOffset]; // first element in block - $name = $params[$processNameIndex + $blockOffset]; - $result[$num] = $name; - } - } + $hitans = BaseSegment::parse($segmentRaw); + if (!($hitans instanceof HITANS)) { + throw new \InvalidArgumentException("All HITANS segments must implement the HITANS interface"); + } + foreach ($hitans->getParameterZweiSchrittTanEinreichung()->getVerfahrensparameterZweiSchrittVerfahren() as $verfahren) { + $result[$verfahren->getSicherheitsfunktion()] = $verfahren->getNameDesZweiSchrittVerfahrens(); + } + } return $result; } - - private function getTanProcessParamsOffsetForVersion($version) - { - switch ($version) { - case 1: - return 4; - case 2: - case 3: - case 4: - case 5: - case 6: - return 3; - default: - throw new MT940Exception('Unknown HITANS version ' . $version); - } - } - private function getTanProcessParamElementCountForVersion($version) - { - switch ($version) { - case 1: - return 11; - break; - case 2: - return 15; - case 3: - return 18; - case 4: - case 5: - return 22; - case 6: - return 21; - default: - throw new MT940Exception('Unknown HITANS version ' . $version); - } - } - private function getTanProcessNameIndexForVersion($version) - { - switch ($version) { - case 1: - case 2: - case 3: - return 3; - case 4: - case 5: - case 6: - return 5; - default: - throw new MT940Exception('Unknown HITANS version ' . $version); - } - } } diff --git a/lib/Fhp/Segment/BaseSegment.php b/lib/Fhp/Segment/BaseSegment.php index ed261f2c..ac5dd891 100644 --- a/lib/Fhp/Segment/BaseSegment.php +++ b/lib/Fhp/Segment/BaseSegment.php @@ -2,6 +2,7 @@ namespace Fhp\Segment; +use Fhp\Syntax\Delimiter; use Fhp\Syntax\Parser; use Fhp\Syntax\Serializer; @@ -17,6 +18,8 @@ */ abstract class BaseSegment implements SegmentInterface { + /** @var string Name of the PHP namespace under which all the segments are stored. */ + const SEGMENT_NAMESPACE = 'Fhp\Segment'; /** * Reference to the descriptor for this type of segment. @@ -68,8 +71,7 @@ public function __toString() } /** - * Convenience function for {@link Parser#parseSegment()}. This function should not be called on BaseSegment itself, - * but only on one of its sub-classes. + * Convenience function for {@link Parser#parseSegment()}. * @param string $rawSegment The serialized wire format for a single segment (segment delimiter may be present at * the end, or not). * @return BaseSegment The parsed segment. @@ -77,9 +79,23 @@ public function __toString() public static function parse($rawSegment) { if (static::class === BaseSegment::class) { - throw new \BadFunctionCallException("Do not call BaseSegment::parse() on the super class"); + // Called as BaseSegment::parse(), so we need to determine the right segment type/class. + $firstElementDelimiter = strpos($rawSegment, Delimiter::ELEMENT); + if ($firstElementDelimiter === false) { + throw new \InvalidArgumentException("Invalid segment $rawSegment"); + } + /** @var Segmentkopf $segmentkopf */ + $segmentkopf = Segmentkopf::parse(substr($rawSegment, 0, $firstElementDelimiter)); + $segmentType = static::SEGMENT_NAMESPACE . '\\' . $segmentkopf->segmentkennung . '\\' + . $segmentkopf->segmentkennung . 'v' . $segmentkopf->segmentversion; + if (!class_exists($segmentType)) { + throw new \InvalidArgumentException("Unsupported segment type/version $segmentType"); + } + } else { + // The parse() function was called on the segment subclass itself. + $segmentType = static::class; } - return Parser::parseSegment($rawSegment, static::class); + return Parser::parseSegment($rawSegment, $segmentType); } } diff --git a/lib/Fhp/Segment/HITANS/HITANS.php b/lib/Fhp/Segment/HITANS/HITANS.php new file mode 100644 index 00000000..65a1ebc1 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/HITANS.php @@ -0,0 +1,18 @@ +parameterZweiSchrittTanEinreichung; + } } diff --git a/lib/Fhp/Segment/HITANS/HITANSv2.php b/lib/Fhp/Segment/HITANS/HITANSv2.php new file mode 100644 index 00000000..8338562e --- /dev/null +++ b/lib/Fhp/Segment/HITANS/HITANSv2.php @@ -0,0 +1,33 @@ +parameterZweiSchrittTanEinreichung; + } +} diff --git a/lib/Fhp/Segment/HITANS/HITANSv3.php b/lib/Fhp/Segment/HITANS/HITANSv3.php index 721d1415..2c11beb0 100644 --- a/lib/Fhp/Segment/HITANS/HITANSv3.php +++ b/lib/Fhp/Segment/HITANS/HITANSv3.php @@ -14,7 +14,7 @@ * * @package Fhp\Segment\HITANS */ -class HITANSv3 extends BaseSegment +class HITANSv3 extends BaseSegment implements HITANS { /** @var integer */ public $maximaleAnzahlAuftraege; @@ -24,4 +24,10 @@ class HITANSv3 extends BaseSegment public $sicherheitsklasse; /** @var ParameterZweiSchrittTanEinreichungV3 */ public $parameterZweiSchrittTanEinreichung; + + /** @return ParameterZweiSchrittTanEinreichungV3 */ + public function getParameterZweiSchrittTanEinreichung() + { + return $this->parameterZweiSchrittTanEinreichung; + } } diff --git a/lib/Fhp/Segment/HITANS/HITANSv4.php b/lib/Fhp/Segment/HITANS/HITANSv4.php new file mode 100644 index 00000000..da393167 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/HITANSv4.php @@ -0,0 +1,33 @@ +parameterZweiSchrittTanEinreichung; + } +} diff --git a/lib/Fhp/Segment/HITANS/HITANSv5.php b/lib/Fhp/Segment/HITANS/HITANSv5.php new file mode 100644 index 00000000..42767874 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/HITANSv5.php @@ -0,0 +1,33 @@ +parameterZweiSchrittTanEinreichung; + } +} diff --git a/lib/Fhp/Segment/HITANS/HITANSv6.php b/lib/Fhp/Segment/HITANS/HITANSv6.php new file mode 100644 index 00000000..2b9b6fa8 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/HITANSv6.php @@ -0,0 +1,33 @@ +parameterZweiSchrittTanEinreichung; + } +} diff --git a/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichung.php b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichung.php new file mode 100644 index 00000000..ed564a18 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichung.php @@ -0,0 +1,9 @@ +verfahrensparameterZweiSchrittVerfahren; + } } diff --git a/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV2.php b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV2.php new file mode 100644 index 00000000..1f97dc73 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV2.php @@ -0,0 +1,28 @@ +verfahrensparameterZweiSchrittVerfahren; + } +} diff --git a/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV3.php b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV3.php index 16d24b6e..71b44215 100644 --- a/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV3.php +++ b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV3.php @@ -4,7 +4,7 @@ use Fhp\Segment\BaseDeg; -class ParameterZweiSchrittTanEinreichungV3 extends BaseDeg +class ParameterZweiSchrittTanEinreichungV3 extends BaseDeg implements ParameterZweiSchrittTanEinreichung { /** @var boolean */ public $einschrittVerfahrenErlaubt; @@ -19,4 +19,10 @@ class ParameterZweiSchrittTanEinreichungV3 extends BaseDeg public $auftragsHashwertverfahren; /** @var VerfahrensparameterZweiSchrittVerfahrenV3[] @Max(98) */ public $verfahrensparameterZweiSchrittVerfahren; + + /** @return VerfahrensparameterZweiSchrittVerfahrenV3[] */ + public function getVerfahrensparameterZweiSchrittVerfahren() + { + return $this->verfahrensparameterZweiSchrittVerfahren; + } } diff --git a/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV4.php b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV4.php new file mode 100644 index 00000000..00884528 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV4.php @@ -0,0 +1,28 @@ +verfahrensparameterZweiSchrittVerfahren; + } +} diff --git a/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV5.php b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV5.php new file mode 100644 index 00000000..e9f2e325 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV5.php @@ -0,0 +1,28 @@ +verfahrensparameterZweiSchrittVerfahren; + } +} diff --git a/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV6.php b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV6.php new file mode 100644 index 00000000..df8f784c --- /dev/null +++ b/lib/Fhp/Segment/HITANS/ParameterZweiSchrittTanEinreichungV6.php @@ -0,0 +1,28 @@ +verfahrensparameterZweiSchrittVerfahren; + } +} diff --git a/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahren.php b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahren.php new file mode 100644 index 00000000..fffb1e37 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahren.php @@ -0,0 +1,12 @@ +sicherheitsfunktion; + } + + public function getNameDesZweiSchrittVerfahrens() + { + return $this->nameDesZweiSchrittVerfahrens; + } } diff --git a/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV2.php b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV2.php new file mode 100644 index 00000000..bd9802e8 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV2.php @@ -0,0 +1,55 @@ +sicherheitsfunktion; + } + + public function getNameDesZweiSchrittVerfahrens() + { + return $this->nameDesZweiSchrittVerfahrens; + } +} diff --git a/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV3.php b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV3.php index 3ea7ad9e..09680631 100644 --- a/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV3.php +++ b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV3.php @@ -4,7 +4,7 @@ use Fhp\Segment\BaseDeg; -class VerfahrensparameterZweiSchrittVerfahrenV3 extends BaseDeg +class VerfahrensparameterZweiSchrittVerfahrenV3 extends BaseDeg implements VerfahrensparameterZweiSchrittVerfahren { /** @var integer Allowed values: 900 through 997 */ public $sicherheitsfunktion; @@ -48,4 +48,14 @@ class VerfahrensparameterZweiSchrittVerfahrenV3 extends BaseDeg public $bezeichnungDesTanMediumsErforderlich; /** @var integer|null */ public $anzahlUnterstuetzterAktiverTanMedien; + + public function getSicherheitsfunktion() + { + return $this->sicherheitsfunktion; + } + + public function getNameDesZweiSchrittVerfahrens() + { + return $this->nameDesZweiSchrittVerfahrens; + } } diff --git a/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV4.php b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV4.php new file mode 100644 index 00000000..b4991a69 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV4.php @@ -0,0 +1,69 @@ +sicherheitsfunktion; + } + + public function getNameDesZweiSchrittVerfahrens() + { + return $this->nameDesZweiSchrittVerfahrens; + } +} diff --git a/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV5.php b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV5.php new file mode 100644 index 00000000..26d87c89 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV5.php @@ -0,0 +1,69 @@ +sicherheitsfunktion; + } + + public function getNameDesZweiSchrittVerfahrens() + { + return $this->nameDesZweiSchrittVerfahrens; + } +} diff --git a/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV6.php b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV6.php new file mode 100644 index 00000000..1bfad0b8 --- /dev/null +++ b/lib/Fhp/Segment/HITANS/VerfahrensparameterZweiSchrittVerfahrenV6.php @@ -0,0 +1,67 @@ +sicherheitsfunktion; + } + + public function getNameDesZweiSchrittVerfahrens() + { + return $this->nameDesZweiSchrittVerfahrens; + } +} diff --git a/lib/Fhp/Syntax/Serializer.php b/lib/Fhp/Syntax/Serializer.php index fe43ea1b..ce126ab2 100644 --- a/lib/Fhp/Syntax/Serializer.php +++ b/lib/Fhp/Syntax/Serializer.php @@ -19,6 +19,16 @@ function array_key_last($array) abstract class Serializer { + /** + * Escapes syntax characters (delimiters). + * @param string $str The unescaped string. + * @return string The escaped string in wire format. + */ + public static function escape($str) + { + return preg_replace('/([+:\'?@])/', '?$1', $str); + } + /** * @param mixed $value A scalar (DE) value. * @param string $type The PHP type of this value. This should support exactly the values for which @@ -28,7 +38,7 @@ abstract class Serializer public static function serializeDataElement($value, $type) { if ($type === 'int' || $type === 'integer' || $type === 'string') { - return strval($value); + return static::escape(strval($value)); } elseif ($type === 'float') { // Format with fixed 2 decimal places (there has to be some limit, and the specification does not specify // one), then trim zeros from the end. diff --git a/lib/Tests/Fhp/ResponseTest/GetVariablesTest.php b/lib/Tests/Fhp/ResponseTest/GetVariablesTest.php index 3ea99a68..2b0e00ed 100644 --- a/lib/Tests/Fhp/ResponseTest/GetVariablesTest.php +++ b/lib/Tests/Fhp/ResponseTest/GetVariablesTest.php @@ -3,17 +3,17 @@ namespace Fhp\ResponseTest; use Fhp\Response\GetVariables; -use Tests\Fhp\Model\HITANSTest; +use Tests\Fhp\Segment\HITANSTest; class GetVariablesTest extends \PHPUnit_Framework_TestCase { public function testParseTanModesSparkasse() { $segments = array( - 'HITANS:169:6:4+1+1+1+J:N:0:910:2:HHD1.3.0:::chipTAN manuell:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:911:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:912:2:HHD1.3.2USB:HHDUSB1:1.3.2:chipTAN-USB:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:913:2:Q1S:Secoder_UC:1.2.0:chipTAN-QR:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:920:2:smsTAN:::smsTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:5:921:2:pushTAN:::pushTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:2:900:2:iTAN:::iTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:0' + "HITANS:169:6:4+1+1+1+J:N:0:910:2:HHD1.3.0:::chipTAN manuell:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:911:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:912:2:HHD1.3.2USB:HHDUSB1:1.3.2:chipTAN-USB:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:913:2:Q1S:Secoder_UC:1.2.0:chipTAN-QR:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:920:2:smsTAN:::smsTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:5:921:2:pushTAN:::pushTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:2:900:2:iTAN:::iTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:0'", ); - $gv = new GetVariables(null, null); - $modes = $gv->parseTanModes($segments); + $gv = new GetVariables(implode($segments), null); + $modes = $gv->getSupportedTanMechanisms(); $this->assertEquals($modes[910], 'chipTAN manuell'); $this->assertEquals($modes[911], 'chipTAN optisch'); $this->assertEquals($modes[912], 'chipTAN-USB'); @@ -27,10 +27,10 @@ public function testParseTanModesSparkasseLastParamRemoved() { // see https://github.com/nemiah/phpFinTS/pull/40#issuecomment-532362814 $segments = array( - 'HITANS:169:6:4+1+1+1+J:N:0:910:2:HHD1.3.0:::chipTAN manuell:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:911:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:912:2:HHD1.3.2USB:HHDUSB1:1.3.2:chipTAN-USB:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:913:2:Q1S:Secoder_UC:1.2.0:chipTAN-QR:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:920:2:smsTAN:::smsTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:5:921:2:pushTAN:::pushTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:2:900:2:iTAN:::iTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N' + "HITANS:169:6:4+1+1+1+J:N:0:910:2:HHD1.3.0:::chipTAN manuell:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:911:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:912:2:HHD1.3.2USB:HHDUSB1:1.3.2:chipTAN-USB:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:913:2:Q1S:Secoder_UC:1.2.0:chipTAN-QR:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N:1:920:2:smsTAN:::smsTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:5:921:2:pushTAN:::pushTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:2:N:2:900:2:iTAN:::iTAN:6:1:TAN-Nummer:3:J:2:N:0:0:N:N:00:0:N'", ); - $gv = new GetVariables(null, null); - $modes = $gv->parseTanModes($segments); + $gv = new GetVariables(implode($segments), null); + $modes = $gv->getSupportedTanMechanisms(); $this->assertEquals($modes[910], 'chipTAN manuell'); $this->assertEquals($modes[911], 'chipTAN optisch'); $this->assertEquals($modes[912], 'chipTAN-USB'); @@ -44,12 +44,12 @@ public function testParseTanModesPostbank() { // postbank provides different versions - maybe we just use the highest one? $segments = array( - 'HITANS:14:4:4+1+1+0+N:N:0:901:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:0:N:1:0:N:N:N:N:J:00:2:9:910:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch HHD1.3.2:6:1:Challenge:999:0:N:1:0:N:N:N:N:J:00:2:9:911:2:HHD1.3.2:HHD:1.3.2:chipTAN manuell HHD1.3.2:6:1:Challenge:999:0:N:1:0:N:N:N:N:J:00:2:9:920:2:BestSign:BestSign::BestSign:6:2:BestSign:999:0:N:1:0:N:N:N:N:J:00:2:9:930:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:0:N:1:0:N:N:N:N:J:00:2:9', - 'HITANS:15:5:4+1+1+0+N:N:0:901:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:0:N:1:0:N:0:2:N:J:00:2:9:910:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch HHD1.3.2:6:1:Challenge:999:0:N:1:0:N:0:2:N:J:00:2:9:911:2:HHD1.3.2:HHD:1.3.2:chipTAN manuell HHD1.3.2:6:1:Challenge:999:0:N:1:0:N:0:2:N:J:00:2:9:912:2:HHD1.4OPT:HHDOPT1:1.4:chipTAN optisch HHD1.4:6:1:Challenge:999:0:N:1:0:N:0:2:N:J:00:2:9:913:2:HHD1.4:HHD:1.4:chipTAN manuell HHD1.4:6:1:Challenge:999:0:N:1:0:N:0:2:N:J:00:2:9:920:2:BestSign:BestSign::BestSign:6:2:BestSign:999:0:N:1:0:N:0:2:N:J:00:2:9:930:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:0:N:1:0:N:0:2:N:J:00:2:9', - 'HITANS:16:6:4+1+1+0+N:N:0:901:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:N:1:N:0:2:N:J:00:2:N:9:910:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch HHD1.3.2:6:1:Challenge:999:N:1:N:0:2:N:J:00:2:N:9:911:2:HHD1.3.2:HHD:1.3.2:chipTAN manuell HHD1.3.2:6:1:Challenge:999:N:1:N:0:2:N:J:00:2:N:9:912:2:HHD1.4OPT:HHDOPT1:1.4:chipTAN optisch HHD1.4:6:1:Challenge:999:N:1:N:0:2:N:J:00:2:N:9:913:2:HHD1.4:HHD:1.4:chipTAN manuell HHD1.4:6:1:Challenge:999:N:1:N:0:2:N:J:00:2:N:9:920:2:BestSign:BestSign::BestSign:6:2:BestSign:999:N:1:N:0:2:N:J:00:2:N:9:930:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:N:1:N:0:2:N:J:00:2:N:9' + "HITANS:14:4:4+1+1+0+N:N:0:901:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:0:N:1:0:N:N:N:N:J:00:2:9:910:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch HHD1.3.2:6:1:Challenge:999:0:N:1:0:N:N:N:N:J:00:2:9:911:2:HHD1.3.2:HHD:1.3.2:chipTAN manuell HHD1.3.2:6:1:Challenge:999:0:N:1:0:N:N:N:N:J:00:2:9:920:2:BestSign:BestSign::BestSign:6:2:BestSign:999:0:N:1:0:N:N:N:N:J:00:2:9:930:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:0:N:1:0:N:N:N:N:J:00:2:9'", + "HITANS:15:5:4+1+1+0+N:N:0:901:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:0:N:1:0:N:0:2:N:J:00:2:9:910:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch HHD1.3.2:6:1:Challenge:999:0:N:1:0:N:0:2:N:J:00:2:9:911:2:HHD1.3.2:HHD:1.3.2:chipTAN manuell HHD1.3.2:6:1:Challenge:999:0:N:1:0:N:0:2:N:J:00:2:9:912:2:HHD1.4OPT:HHDOPT1:1.4:chipTAN optisch HHD1.4:6:1:Challenge:999:0:N:1:0:N:0:2:N:J:00:2:9:913:2:HHD1.4:HHD:1.4:chipTAN manuell HHD1.4:6:1:Challenge:999:0:N:1:0:N:0:2:N:J:00:2:9:920:2:BestSign:BestSign::BestSign:6:2:BestSign:999:0:N:1:0:N:0:2:N:J:00:2:9:930:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:0:N:1:0:N:0:2:N:J:00:2:9'", + "HITANS:16:6:4+1+1+0+N:N:0:901:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:N:1:N:0:2:N:J:00:2:N:9:910:2:HHD1.3.2OPT:HHDOPT1:1.3.2:chipTAN optisch HHD1.3.2:6:1:Challenge:999:N:1:N:0:2:N:J:00:2:N:9:911:2:HHD1.3.2:HHD:1.3.2:chipTAN manuell HHD1.3.2:6:1:Challenge:999:N:1:N:0:2:N:J:00:2:N:9:912:2:HHD1.4OPT:HHDOPT1:1.4:chipTAN optisch HHD1.4:6:1:Challenge:999:N:1:N:0:2:N:J:00:2:N:9:913:2:HHD1.4:HHD:1.4:chipTAN manuell HHD1.4:6:1:Challenge:999:N:1:N:0:2:N:J:00:2:N:9:920:2:BestSign:BestSign::BestSign:6:2:BestSign:999:N:1:N:0:2:N:J:00:2:N:9:930:2:mobileTAN:mobileTAN::mobileTAN:6:2:mobileTAN:999:N:1:N:0:2:N:J:00:2:N:9'", ); - $gv = new GetVariables(null, null); - $modes = $gv->parseTanModes($segments); + $gv = new GetVariables(implode($segments), null); + $modes = $gv->getSupportedTanMechanisms(); $this->assertEquals($modes[901], 'mobileTAN'); $this->assertEquals($modes[910], 'chipTAN optisch HHD1.3.2'); $this->assertEquals($modes[911], 'chipTAN manuell HHD1.3.2'); @@ -61,8 +61,8 @@ public function testParseTanModesPostbank() public function testParseTanModesDKB() { - $gv = new GetVariables(null, null); - $modes = $gv->parseTanModes(HITANSTest::REAL_DKB_RESPONSE); + $gv = new GetVariables(implode(HITANSTest::REAL_DKB_RESPONSE), null); + $modes = $gv->getSupportedTanMechanisms(); $this->assertEquals($modes[920], "smsTAN"); $this->assertEquals($modes[900], "iTAN"); $this->assertEquals($modes[910], "chipTAN manuell"); diff --git a/lib/Tests/Fhp/Segment/HITANSTest.php b/lib/Tests/Fhp/Segment/HITANSTest.php index 1c423144..8912f9e8 100644 --- a/lib/Tests/Fhp/Segment/HITANSTest.php +++ b/lib/Tests/Fhp/Segment/HITANSTest.php @@ -1,9 +1,11 @@ assertEquals(static::REAL_DKB_RESPONSE[1], $parsed->serialize()); } + + public function test_parse_DKB_response_v6() + { + /** @var HITANSv6 $parsed */ + $parsed = HITANSv6::parse(static::REAL_DKB_RESPONSE[2]); + $this->assertEquals(1, $parsed->maximaleAnzahlAuftraege); + $parsedParams = $parsed->parameterZweiSchrittTanEinreichung; + $this->assertEquals(true, $parsedParams->einschrittVerfahrenErlaubt); + $this->assertCount(7, $parsedParams->verfahrensparameterZweiSchrittVerfahren); + $this->assertEquals("HHD1.3.0", $parsedParams->verfahrensparameterZweiSchrittVerfahren[0]->technischeIdentifikationTanVerfahren); + $this->assertEquals("chipTAN manuell", $parsedParams->verfahrensparameterZweiSchrittVerfahren[0]->nameDesZweiSchrittVerfahrens); + $this->assertEquals("TAN2go", $parsedParams->verfahrensparameterZweiSchrittVerfahren[5]->technischeIdentifikationTanVerfahren); + $this->assertEquals("iTAN", $parsedParams->verfahrensparameterZweiSchrittVerfahren[6]->technischeIdentifikationTanVerfahren); + $this->assertEquals("00", $parsedParams->verfahrensparameterZweiSchrittVerfahren[6]->initialisierungsmodus); + } + + public function test_segmentVersion_detection() + { + $this->assertEquals(HITANSv1::parse(static::REAL_DKB_RESPONSE[0]), + BaseSegment::parse(static::REAL_DKB_RESPONSE[0])); + $this->assertEquals(HITANSv3::parse(static::REAL_DKB_RESPONSE[1]), + BaseSegment::parse(static::REAL_DKB_RESPONSE[1])); + $this->assertEquals(HITANSv6::parse(static::REAL_DKB_RESPONSE[2]), + BaseSegment::parse(static::REAL_DKB_RESPONSE[2])); + } } diff --git a/lib/Tests/Fhp/Segment/HIUPDTest.php b/lib/Tests/Fhp/Segment/HIUPDTest.php index 0e43d143..0cd968a8 100644 --- a/lib/Tests/Fhp/Segment/HIUPDTest.php +++ b/lib/Tests/Fhp/Segment/HIUPDTest.php @@ -1,6 +1,6 @@ assertEquals('ABC?+DEF', Serializer::escape('ABC+DEF')); + $this->assertEquals('ABC???+DEF', Serializer::escape('ABC?+DEF')); + $this->assertEquals('ABC??DEF', Serializer::escape('ABC?DEF')); + $this->assertEquals('ABC?:DEF', Serializer::escape('ABC:DEF')); + } + + public function test_serializeDataElement() { $this->assertSame('15', Serializer::serializeDataElement(15, 'int')); $this->assertSame('1000', Serializer::serializeDataElement(1000, 'integer')); @@ -16,8 +24,9 @@ public function test_serializeDataElement() $this->assertSame('J', Serializer::serializeDataElement(true, 'bool')); $this->assertSame('N', Serializer::serializeDataElement(false, 'boolean')); $this->assertSame('1000', Serializer::serializeDataElement("1000", 'string')); + $this->assertSame('5?:5', Serializer::serializeDataElement("5:5", 'string')); } - + public function test_fillMissingKeys() { $arr = array(0 => 'a', 2 => 'b', 4 => 'c');