From c109cafe7873477515af36f091b1a438c423b9b7 Mon Sep 17 00:00:00 2001 From: "david.owusu" Date: Thu, 6 Aug 2026 16:31:08 +0200 Subject: [PATCH 1/3] [CC-3981] Fix Paypage requests being broken by internal keyClassMap leaking into serialized payload exposeProperties() filtered properties by visibility only, so a protected static lookup table was picked up by reflection and sent to the API. Exclude static properties in the base class and tighten keyClassMap's visibility to private since it is only used internally. Co-Authored-By: Claude Sonnet 5 --- src/Resources/AbstractUnzerResource.php | 5 +++++ src/Resources/V2/Paypage.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Resources/AbstractUnzerResource.php b/src/Resources/AbstractUnzerResource.php index 59a3750d..178864f4 100644 --- a/src/Resources/AbstractUnzerResource.php +++ b/src/Resources/AbstractUnzerResource.php @@ -501,6 +501,11 @@ private function exposeProperties(): array $properties = []; foreach ($reflectionProperties as $propertyObject) { + // static properties are internal to the class and must never be sent to the API + if ($propertyObject->isStatic()) { + continue; + } + $property = $propertyObject->getName(); $value = $propertyObject->getValue($this); diff --git a/src/Resources/V2/Paypage.php b/src/Resources/V2/Paypage.php index d7a7b4fa..8ae7571f 100644 --- a/src/Resources/V2/Paypage.php +++ b/src/Resources/V2/Paypage.php @@ -22,7 +22,7 @@ class Paypage extends AbstractUnzerResource { public const URI = '/merchant/paypage'; - protected static $keyClassMap = [ + private static $keyClassMap = [ 'urls' => Urls::class, 'style' => Style::class, 'resources' => Resources::class, From 19c8a0fdb672ce6acf7e0b3a9472130ce7a03dc1 Mon Sep 17 00:00:00 2001 From: "david.owusu" Date: Fri, 7 Aug 2026 11:20:08 +0200 Subject: [PATCH 2/3] [CC-3981] remove comment --- src/Resources/AbstractUnzerResource.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Resources/AbstractUnzerResource.php b/src/Resources/AbstractUnzerResource.php index 178864f4..b1abfb7e 100644 --- a/src/Resources/AbstractUnzerResource.php +++ b/src/Resources/AbstractUnzerResource.php @@ -501,7 +501,6 @@ private function exposeProperties(): array $properties = []; foreach ($reflectionProperties as $propertyObject) { - // static properties are internal to the class and must never be sent to the API if ($propertyObject->isStatic()) { continue; } From d81bbc894f446ff716224f6d210bb41f5d311aac Mon Sep 17 00:00:00 2001 From: "david.owusu" Date: Fri, 7 Aug 2026 11:20:40 +0200 Subject: [PATCH 3/3] [CC-3981] Repair broken integration tests --- test/integration/Resources/BasketV2Test.php | 6 +++--- test/integration/Resources/BasketV3Test.php | 6 +++--- test/integration/Resources/PaypageV2Test.php | 4 +++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/test/integration/Resources/BasketV2Test.php b/test/integration/Resources/BasketV2Test.php index ec9a666d..3469675e 100644 --- a/test/integration/Resources/BasketV2Test.php +++ b/test/integration/Resources/BasketV2Test.php @@ -212,7 +212,7 @@ public function authorizeTransactionsShouldPassAlongTheBasketIdIfSet(): void /** @var Paypal $paypal */ $paypal = $this->unzer->createPaymentType(new Paypal()); - $authorize = $paypal->authorize(123.4, 'EUR', 'https://unzer.com', null, null, null, $basket); + $authorize = $paypal->authorize(99.99, 'EUR', 'https://unzer.com', null, null, null, $basket); $fetchedPayment = $this->unzer->fetchPayment($authorize->getPaymentId()); $this->assertEquals($basket->expose(), $fetchedPayment->getBasket()->expose()); @@ -261,7 +261,7 @@ public function authorizeTransactionsShouldCreateBasketIfItDoesNotExistYet(): vo /** @var Paypal $paypal */ $paypal = $this->unzer->createPaymentType(new Paypal()); - $authorize = $paypal->authorize(123.4, 'EUR', 'https://unzer.com', null, null, null, $basket); + $authorize = $paypal->authorize(99.99, 'EUR', 'https://unzer.com', null, null, null, $basket); $this->assertNotEmpty($basket->getId()); $fetchedPayment = $this->unzer->fetchPayment($authorize->getPaymentId()); @@ -290,7 +290,7 @@ public function chargeTransactionsShouldCreateBasketIfItDoesNotExistYet(): void /** @var Paypal $paypal */ $paypal = $this->unzer->createPaymentType(new Paypal()); - $charge = $paypal->charge(123.4, 'EUR', 'https://unzer.com', null, null, null, $basket); + $charge = $paypal->charge(99.99, 'EUR', 'https://unzer.com', null, null, null, $basket); $this->assertNotEmpty($basket->getId()); $fetchedPayment = $this->unzer->fetchPayment($charge->getPaymentId()); diff --git a/test/integration/Resources/BasketV3Test.php b/test/integration/Resources/BasketV3Test.php index 55f60d99..07ddefd9 100644 --- a/test/integration/Resources/BasketV3Test.php +++ b/test/integration/Resources/BasketV3Test.php @@ -220,7 +220,7 @@ public function authorizeTransactionsShouldPassAlongTheBasketIdIfSet(): void /** @var Paypal $paypal */ $paypal = $this->unzer->createPaymentType(new Paypal()); - $authorize = $paypal->authorize(123.4, 'EUR', 'https://unzer.com', null, null, null, $basket); + $authorize = $paypal->authorize(99.99, 'EUR', 'https://unzer.com', null, null, null, $basket); $fetchedPayment = $this->unzer->fetchPayment($authorize->getPaymentId()); $this->assertEquals($basket->expose(), $fetchedPayment->getBasket()->expose()); @@ -248,7 +248,7 @@ public function authorizeTransactionsShouldCreateBasketIfItDoesNotExistYet(): vo /** @var Paypal $paypal */ $paypal = $this->unzer->createPaymentType(new Paypal()); - $authorize = $paypal->authorize(123.4, 'EUR', 'https://unzer.com', null, null, null, $basket); + $authorize = $paypal->authorize(99.99, 'EUR', 'https://unzer.com', null, null, null, $basket); $this->assertNotEmpty($basket->getId()); $fetchedPayment = $this->unzer->fetchPayment($authorize->getPaymentId()); @@ -277,7 +277,7 @@ public function chargeTransactionsShouldCreateBasketIfItDoesNotExistYet(): void /** @var Paypal $paypal */ $paypal = $this->unzer->createPaymentType(new Paypal()); - $charge = $paypal->charge(123.4, 'EUR', 'https://unzer.com', null, null, null, $basket); + $charge = $paypal->charge(99.99, 'EUR', 'https://unzer.com', null, null, null, $basket); $this->assertNotEmpty($basket->getId()); $fetchedPayment = $this->unzer->fetchPayment($charge->getPaymentId()); diff --git a/test/integration/Resources/PaypageV2Test.php b/test/integration/Resources/PaypageV2Test.php index 73c4fd0e..f2d8f25e 100644 --- a/test/integration/Resources/PaypageV2Test.php +++ b/test/integration/Resources/PaypageV2Test.php @@ -76,7 +76,8 @@ public function createMinimumPaypageTest() $this->assertNull($paypage->getUrls()); $this->assertNull($paypage->getStyle()); - $this->assertNull($paypage->getResources()); + $this->assertNull($paypage->getResources()->getCustomerId()); + $this->assertNull($paypage->getResources()->getBasketId()); $this->assertNull($paypage->getPaymentMethodsConfigs()); $this->assertNull($paypage->getRisk()); } @@ -271,6 +272,7 @@ public function assertCreatedPaypage(Paypage $paypage): void { $this->assertNotNull($paypage->getId()); $this->assertNotNull($paypage->getRedirectUrl()); + $this->assertNotNull($paypage->getResources()->getMetadataId()); $this->assertStringContainsString($paypage->getId(), $paypage->getRedirectUrl()); }