From e9e914b14efe4a76ce5d14997f100dc0c599048f Mon Sep 17 00:00:00 2001 From: fabio Date: Wed, 14 Oct 2026 18:10:49 +0200 Subject: [PATCH 1/2] fix(hydrator): fall back to UNKNOWN for enum values the SDK does not know The API can return enum values added after the SDK was generated. For example, Italian PagoBancomat cards are returned with card type "BANCOMAT", which is missing from CardResponseType: Transactions::get() then throws a ValueError and the whole transaction is unreadable, even though it is SUCCESSFUL and every other field is valid. Enums that declare an UNKNOWN case now map unrecognised values to it. Enums without UNKNOWN keep the current strict behaviour (ValueError). --- src/Hydrator.php | 8 ++++++++ tests/HydratorTest.php | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Hydrator.php b/src/Hydrator.php index b30b9a3..3908c82 100644 --- a/src/Hydrator.php +++ b/src/Hydrator.php @@ -144,6 +144,14 @@ private static function castEnumValue($value, $enumClass) if ($enum !== null) { return $enum; } + + // The API can return values added after the SDK was generated + // (e.g. a new card network). Enums that declare an UNKNOWN case + // are meant to absorb them instead of failing the whole response. + $unknown = $enumClass::tryFrom('UNKNOWN'); + if ($unknown !== null) { + return $unknown; + } } if (method_exists($enumClass, 'from')) { diff --git a/tests/HydratorTest.php b/tests/HydratorTest.php index faea8e6..e46e39f 100644 --- a/tests/HydratorTest.php +++ b/tests/HydratorTest.php @@ -4,6 +4,8 @@ use PHPUnit\Framework\TestCase; use SumUp\Hydrator; +use SumUp\Types\CardResponse; +use SumUp\Types\CardResponseType; use SumUp\Types\Checkout; use SumUp\Types\CheckoutCurrency; use SumUp\Types\MandateResponse; @@ -79,6 +81,18 @@ public function testHydrateArrayItemsFromDocblockClassNames() $this->assertSame('https://example.test/2', $response->links[1]->href); } + public function testHydrateUnknownValueOfEnumWithUnknownCaseFallsBackToUnknown() + { + $card = Hydrator::hydrate([ + 'type' => 'SOME_FUTURE_NETWORK', + 'last_4_digits' => '1234', + ], CardResponse::class); + + $this->assertInstanceOf(CardResponse::class, $card); + $this->assertSame(CardResponseType::UNKNOWN, $card->type); + $this->assertSame('1234', $card->last4Digits); + } + public function testHydrateInvalidBackedEnumValueThrowsValueError() { $this->expectException(\ValueError::class); From 99170fbd041ec9f1c890c7759ab4b6ed4f915553 Mon Sep 17 00:00:00 2001 From: fabio Date: Wed, 14 Oct 2026 18:10:49 +0200 Subject: [PATCH 2/2] feat: add BANCOMAT card type Italian PagoBancomat debit cards are reported by the API with card type "BANCOMAT". Add it to the CardType schema and regenerate the card type enums. --- openapi.json | 1 + src/Types/CardResponseType.php | 1 + src/Types/CardType.php | 1 + src/Types/PaymentInstrumentResponseCardType.php | 1 + src/Types/TransactionHistoryCardType.php | 1 + tests/HydratorTest.php | 10 ++++++++++ 6 files changed, 15 insertions(+) diff --git a/openapi.json b/openapi.json index f514d26..a8cba7a 100644 --- a/openapi.json +++ b/openapi.json @@ -8061,6 +8061,7 @@ "enum": [ "ALELO", "AMEX", + "BANCOMAT", "CONECS", "CUP", "DINERS", diff --git a/src/Types/CardResponseType.php b/src/Types/CardResponseType.php index 0442c42..9d900ec 100644 --- a/src/Types/CardResponseType.php +++ b/src/Types/CardResponseType.php @@ -11,6 +11,7 @@ enum CardResponseType: string { case ALELO = 'ALELO'; case AMEX = 'AMEX'; + case BANCOMAT = 'BANCOMAT'; case CONECS = 'CONECS'; case CUP = 'CUP'; case DINERS = 'DINERS'; diff --git a/src/Types/CardType.php b/src/Types/CardType.php index 227c8e7..2e75b22 100644 --- a/src/Types/CardType.php +++ b/src/Types/CardType.php @@ -11,6 +11,7 @@ enum CardType: string { case ALELO = 'ALELO'; case AMEX = 'AMEX'; + case BANCOMAT = 'BANCOMAT'; case CONECS = 'CONECS'; case CUP = 'CUP'; case DINERS = 'DINERS'; diff --git a/src/Types/PaymentInstrumentResponseCardType.php b/src/Types/PaymentInstrumentResponseCardType.php index 06ddd68..dce45e3 100644 --- a/src/Types/PaymentInstrumentResponseCardType.php +++ b/src/Types/PaymentInstrumentResponseCardType.php @@ -11,6 +11,7 @@ enum PaymentInstrumentResponseCardType: string { case ALELO = 'ALELO'; case AMEX = 'AMEX'; + case BANCOMAT = 'BANCOMAT'; case CONECS = 'CONECS'; case CUP = 'CUP'; case DINERS = 'DINERS'; diff --git a/src/Types/TransactionHistoryCardType.php b/src/Types/TransactionHistoryCardType.php index 8c5a4f8..e052a28 100644 --- a/src/Types/TransactionHistoryCardType.php +++ b/src/Types/TransactionHistoryCardType.php @@ -11,6 +11,7 @@ enum TransactionHistoryCardType: string { case ALELO = 'ALELO'; case AMEX = 'AMEX'; + case BANCOMAT = 'BANCOMAT'; case CONECS = 'CONECS'; case CUP = 'CUP'; case DINERS = 'DINERS'; diff --git a/tests/HydratorTest.php b/tests/HydratorTest.php index e46e39f..0ceddee 100644 --- a/tests/HydratorTest.php +++ b/tests/HydratorTest.php @@ -81,6 +81,16 @@ public function testHydrateArrayItemsFromDocblockClassNames() $this->assertSame('https://example.test/2', $response->links[1]->href); } + public function testHydrateBancomatCardType() + { + $card = Hydrator::hydrate([ + 'type' => 'BANCOMAT', + ], CardResponse::class); + + $this->assertInstanceOf(CardResponse::class, $card); + $this->assertSame(CardResponseType::BANCOMAT, $card->type); + } + public function testHydrateUnknownValueOfEnumWithUnknownCaseFallsBackToUnknown() { $card = Hydrator::hydrate([