diff --git a/src/Resources/Keypair.php b/src/Resources/Keypair.php index 6308e6ea..ef8db4d9 100755 --- a/src/Resources/Keypair.php +++ b/src/Resources/Keypair.php @@ -2,8 +2,8 @@ namespace UnzerSDK\Resources; -use UnzerSDK\Adapter\HttpAdapterInterface; use stdClass; +use UnzerSDK\Adapter\HttpAdapterInterface; /** * This represents the key pair resource. @@ -14,7 +14,7 @@ class Keypair extends AbstractUnzerResource { /** @var string $publicKey */ - private $publicKey; + protected $publicKey; /** @var string $privateKey */ private $privateKey; @@ -23,19 +23,19 @@ class Keypair extends AbstractUnzerResource private $detailed = false; /** @var array $paymentTypes */ - private $paymentTypes = []; + protected $paymentTypes = []; /** @var string $secureLevel */ - private $secureLevel; + protected $secureLevel; /** @var string $alias */ - private $alias; + protected $alias; /** @var string $merchantName */ - private $merchantName; + protected $merchantName; /** @var string $merchantAddress */ - private $merchantAddress; + protected $merchantAddress; /** * Credentials on File / Card on File @@ -43,10 +43,10 @@ class Keypair extends AbstractUnzerResource * * @var bool|null $cof */ - private $cof; + protected $cof; /** @var bool $validateBasket */ - private $validateBasket; + protected $validateBasket; /** * @return string|null diff --git a/test/integration/Resources/KeypairTest.php b/test/integration/Resources/KeypairTest.php index 523ac22c..d3c40c84 100644 --- a/test/integration/Resources/KeypairTest.php +++ b/test/integration/Resources/KeypairTest.php @@ -12,6 +12,7 @@ namespace UnzerSDK\test\integration\Resources; use RuntimeException; +use UnzerSDK\Resources\Keypair; use UnzerSDK\test\BaseIntegrationTest; use UnzerSDK\Unzer; @@ -52,14 +53,30 @@ public function invalidKeysShouldResultInException($key): void * * @test */ - public function keypairShouldReturnExpectedValues(): void + public function keypairShouldReturnExpectedValues(): Keypair { $keypair = $this->unzer->fetchKeypair(); $this->assertNotNull($keypair); $this->assertNotEmpty($keypair->getPublicKey()); - $this->assertNotEmpty($keypair->getPrivateKey()); $this->assertNotEmpty($keypair->getAvailablePaymentTypes()); $this->assertNotEmpty($keypair->getSecureLevel()); + return $keypair; + } + + /** + * Verify keypair can be fetched using the public key extracted from a previous fetch. + * + * @test + * + * @depends keypairShouldReturnExpectedValues + */ + public function keypairCanBeFetchedUsingPublicKey(Keypair $keypair): void + { + $publicKey = $keypair->getPublicKey(); + $fetchedKeypair = (new Unzer($publicKey))->fetchKeypair(); + $this->assertNotNull($fetchedKeypair); + $this->assertEquals($publicKey, $fetchedKeypair->getPublicKey()); + $this->assertNotEmpty($fetchedKeypair->getSecureLevel()); } /** @@ -76,4 +93,27 @@ public function keypairShouldBeFetchableWithDetails(): void $this->assertNotEmpty($keypair->getPaymentTypes()); $this->assertNotEmpty($keypair->getSecureLevel()); } + + /** + * Verify expose() reflects the fetched keypair's properties and excludes privateKey and detailed. + * + * @test + */ + public function exposeReflectsKeypairPropertiesAfterFetch(): void + { + $keypair = $this->unzer->fetchKeypair(true); + $exposed = $keypair->expose(); + + // Main scalar properties must match keypair getters + $this->assertEquals($keypair->getPublicKey(), $exposed['publicKey']); + $this->assertEquals($keypair->getSecureLevel(), $exposed['secureLevel']); + + // Nested payment type objects must be present and match + $this->assertNotEmpty($exposed['paymentTypes']); + $this->assertEquals($keypair->getPaymentTypes(), $exposed['paymentTypes']); + + // privateKey (private) and detailed (private) must never be exposed + $this->assertArrayNotHasKey('privateKey', $exposed); + $this->assertArrayNotHasKey('detailed', $exposed); + } } diff --git a/test/unit/Resources/KeypairTest.php b/test/unit/Resources/KeypairTest.php index 0abba060..a7b696cf 100755 --- a/test/unit/Resources/KeypairTest.php +++ b/test/unit/Resources/KeypairTest.php @@ -135,4 +135,42 @@ public function aKeypairShouldBeUpdatedWithDetailsThroughResponseHandling(): voi $this->assertEquals('Unzer GmbH', $keypair->getMerchantName()); $this->assertEquals('Vangerowstraße 18, 69115 Heidelberg', $keypair->getMerchantAddress()); } + + /** + * Verify expose() contains all relevant key data but excludes privateKey and detailed. + * + * @test + */ + public function exposeContainsAllRelevantKeyDataExceptPrivateKeyAndDetailed(): void + { + $keypair = new Keypair(); + $paymentTypes = [(object)['type' => 'card'], (object)['type' => 'paypal']]; + $keypair->handleResponse((object)[ + 'publicKey' => 's-pub-1234', + 'privateKey' => 's-priv-4321', + 'paymentTypes' => $paymentTypes, + 'secureLevel' => 'SAQ-D', + 'alias' => 'Readme.io user', + 'merchantName' => 'Unzer GmbH', + 'merchantAddress' => 'Vangerowstraße 18, 69115 Heidelberg', + 'cof' => true, + 'validateBasket' => false, + ]); + + $exposed = $keypair->expose(); + + // All relevant protected key data should be exposed with correct values + $this->assertEquals('s-pub-1234', $exposed['publicKey']); + $this->assertEquals($paymentTypes, $exposed['paymentTypes']); + $this->assertEquals('SAQ-D', $exposed['secureLevel']); + $this->assertEquals('Readme.io user', $exposed['alias']); + $this->assertEquals('Unzer GmbH', $exposed['merchantName']); + $this->assertEquals('Vangerowstraße 18, 69115 Heidelberg', $exposed['merchantAddress']); + $this->assertTrue($exposed['cof']); + $this->assertFalse($exposed['validateBasket']); + + // privateKey (private) and detailed (private) must never be exposed + $this->assertArrayNotHasKey('privateKey', $exposed); + $this->assertArrayNotHasKey('detailed', $exposed); + } }