From 5917f81b222fa037da646ee763a5f3022a63a0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Wed, 1 Oct 2025 09:38:12 +0200 Subject: [PATCH 01/16] DX-1364 Add create merchant method --- src/Api/Accounts/AccountsApi.php | 14 +++- src/Model/Fields/Address/FlatNumber.php | 15 ++++ src/Model/Fields/PersonContact/Email.php | 15 ++++ src/Model/Fields/PersonContact/Phone.php | 15 ++++ src/Model/Objects/Accounts/Address.php | 61 +------------- src/Model/Objects/Accounts/PointOfSale.php | 36 ++------- src/Model/Objects/Common/AddressFields.php | 34 ++++++++ .../Objects/Common/AddressPropertiesTrait.php | 51 ++++++++++++ .../Objects/Common/PointOfSaleFields.php | 22 ++++++ .../Common/PointOfSalePropertiesTrait.php | 31 ++++++++ src/Model/Objects/Merchant/Address.php | 31 ++++++++ src/Model/Objects/Merchant/ContactPerson.php | 32 ++++++++ src/Model/Objects/Merchant/PointOfSale.php | 22 ++++++ src/Model/Objects/RequestBody/Merchant.php | 79 +++++++++++++++++++ 14 files changed, 369 insertions(+), 89 deletions(-) create mode 100644 src/Model/Fields/Address/FlatNumber.php create mode 100644 src/Model/Fields/PersonContact/Email.php create mode 100644 src/Model/Fields/PersonContact/Phone.php create mode 100644 src/Model/Objects/Common/AddressFields.php create mode 100644 src/Model/Objects/Common/AddressPropertiesTrait.php create mode 100644 src/Model/Objects/Common/PointOfSaleFields.php create mode 100644 src/Model/Objects/Common/PointOfSalePropertiesTrait.php create mode 100644 src/Model/Objects/Merchant/Address.php create mode 100644 src/Model/Objects/Merchant/ContactPerson.php create mode 100644 src/Model/Objects/Merchant/PointOfSale.php create mode 100644 src/Model/Objects/RequestBody/Merchant.php diff --git a/src/Api/Accounts/AccountsApi.php b/src/Api/Accounts/AccountsApi.php index 54d016e..3ae9355 100644 --- a/src/Api/Accounts/AccountsApi.php +++ b/src/Api/Accounts/AccountsApi.php @@ -60,12 +60,24 @@ public function getBalanceByAccountId($accountId) return $this->run(static::GET, sprintf('/accounts/%s/balance', $accountId)); } - /** @param array $fields */ + /** + * @deprecated Use createMerchant() instead + * + * @param array $fields + */ public function createAccount($fields) { return $this->run(static::POST, '/accounts', $fields, new Account()); } + /** + * @param array $fields + */ + public function createMerchant($fields) + { + return $this->run(static::POST, '/v1/accounts/merchant', $fields, new Account()); + } + public function getMcc() { return $this->run(static::GET, '/accounts/mcc'); diff --git a/src/Model/Fields/Address/FlatNumber.php b/src/Model/Fields/Address/FlatNumber.php new file mode 100644 index 0000000..934e741 --- /dev/null +++ b/src/Model/Fields/Address/FlatNumber.php @@ -0,0 +1,15 @@ + City::class, - 'country' => Country::class, - 'friendlyName' => FriendlyName::class, - 'houseNumber' => HouseNumber::class, - 'isCorrespondence' => IsCorrespondence::class, - 'isInvoice' => IsInvoice::class, - 'isMain' => IsMain::class, - 'name' => Name::class, - 'phone' => Phone::class, - 'postalCode' => PostalCode::class, - 'roomNumber' => RoomNumber::class, - 'street' => Street::class, - ]; + use AddressPropertiesTrait; - /** @var City */ - public $city; - - /** @var Country */ - public $country; - - /** @var FriendlyName */ - public $friendlyName; - - /** @var HouseNumber */ - public $houseNumber; - - /** @var IsCorrespondence */ - public $isCorrespondence; - - /** @var IsInvoice */ - public $isInvoice; - - /** @var IsMain */ - public $isMain; - - /** @var Name */ - public $name; - - /** @var Phone */ - public $phone; - - /** @var PostalCode */ - public $postalCode; + const OBJECT_FIELDS = AddressFields::COMMON_FIELDS + ['roomNumber' => RoomNumber::class]; /** @var RoomNumber */ public $roomNumber; - /** @var Street */ - public $street; - public function getRequiredFields() { return [ diff --git a/src/Model/Objects/Accounts/PointOfSale.php b/src/Model/Objects/Accounts/PointOfSale.php index 06d95ef..6fadb05 100644 --- a/src/Model/Objects/Accounts/PointOfSale.php +++ b/src/Model/Objects/Accounts/PointOfSale.php @@ -2,51 +2,25 @@ namespace Tpay\OpenApi\Model\Objects\Accounts; -use Tpay\OpenApi\Model\Fields\Address\Description; -use Tpay\OpenApi\Model\Fields\Address\FriendlyName; -use Tpay\OpenApi\Model\Fields\PointOfSale\Name; -use Tpay\OpenApi\Model\Fields\PointOfSale\Url; -use Tpay\OpenApi\Model\Identifiers\AccountId; -use Tpay\OpenApi\Model\Identifiers\PosId; +use Tpay\OpenApi\Model\Objects\Common\PointOfSaleFields; +use Tpay\OpenApi\Model\Objects\Common\PointOfSalePropertiesTrait; use Tpay\OpenApi\Model\Objects\Objects; class PointOfSale extends Objects { - const OBJECT_FIELDS = [ - 'posId' => PosId::class, - 'accountId' => AccountId::class, - 'name' => Name::class, - 'friendlyName' => FriendlyName::class, - 'description' => Description::class, - 'url' => Url::class, + use PointOfSalePropertiesTrait; + + const OBJECT_FIELDS = PointOfSaleFields::COMMON_FIELDS + [ 'date' => PointOfSaleDate::class, 'settings' => PointOfSaleSettings::class, ]; - /** @var PosId */ - public $posId; - - /** @var AccountId */ - public $accountId; - - /** @var FriendlyName */ - public $friendlyName; - - /** @var Name */ - public $name; - /** @var PointOfSaleDate */ public $date; /** @var PointOfSaleSettings */ public $settings; - /** @var Url */ - public $url; - - /** @var Description */ - public $description; - public function getRequiredFields() { return [ diff --git a/src/Model/Objects/Common/AddressFields.php b/src/Model/Objects/Common/AddressFields.php new file mode 100644 index 0000000..5790501 --- /dev/null +++ b/src/Model/Objects/Common/AddressFields.php @@ -0,0 +1,34 @@ + City::class, + 'country' => Country::class, + 'friendlyName' => FriendlyName::class, + 'houseNumber' => HouseNumber::class, + 'isCorrespondence' => IsCorrespondence::class, + 'isInvoice' => IsInvoice::class, + 'isMain' => IsMain::class, + 'name' => Name::class, + 'phone' => Phone::class, + 'postalCode' => PostalCode::class, + 'roomNumber' => RoomNumber::class, + 'street' => Street::class, + ]; +} \ No newline at end of file diff --git a/src/Model/Objects/Common/AddressPropertiesTrait.php b/src/Model/Objects/Common/AddressPropertiesTrait.php new file mode 100644 index 0000000..23ebdcb --- /dev/null +++ b/src/Model/Objects/Common/AddressPropertiesTrait.php @@ -0,0 +1,51 @@ + PosId::class, + 'accountId' => AccountId::class, + 'name' => Name::class, + 'friendlyName' => FriendlyName::class, + 'description' => Description::class, + 'url' => Url::class, + ]; +} \ No newline at end of file diff --git a/src/Model/Objects/Common/PointOfSalePropertiesTrait.php b/src/Model/Objects/Common/PointOfSalePropertiesTrait.php new file mode 100644 index 0000000..be07e7b --- /dev/null +++ b/src/Model/Objects/Common/PointOfSalePropertiesTrait.php @@ -0,0 +1,31 @@ + FlatNumber::class]; + + /** @var FlatNumber */ + public $flatNumber; + + public function getRequiredFields() + { + return [ + $this->friendlyName, + $this->name, + $this->street, + $this->houseNumber, + $this->postalCode, + $this->city, + $this->country, + ]; + } +} diff --git a/src/Model/Objects/Merchant/ContactPerson.php b/src/Model/Objects/Merchant/ContactPerson.php new file mode 100644 index 0000000..dc6284a --- /dev/null +++ b/src/Model/Objects/Merchant/ContactPerson.php @@ -0,0 +1,32 @@ + Name::class, + 'surname' => Surname::class, + 'phone' => Phone::class, + 'email' => Email::class, + ]; + + /** @var Name */ + public $name; + + /** @var Surname */ + public $surname; + + /** @var Phone */ + public $phone; + + /** @var Email */ + public $email; +} diff --git a/src/Model/Objects/Merchant/PointOfSale.php b/src/Model/Objects/Merchant/PointOfSale.php new file mode 100644 index 0000000..f354a4a --- /dev/null +++ b/src/Model/Objects/Merchant/PointOfSale.php @@ -0,0 +1,22 @@ +name, + $this->url, + ]; + } +} diff --git a/src/Model/Objects/RequestBody/Merchant.php b/src/Model/Objects/RequestBody/Merchant.php new file mode 100644 index 0000000..215f3e0 --- /dev/null +++ b/src/Model/Objects/RequestBody/Merchant.php @@ -0,0 +1,79 @@ + OfferCode::class, + 'email' => Email::class, + 'taxId' => TaxId::class, + 'regon' => Regon::class, + 'krs' => Krs::class, + 'legalForm' => LegalForm::class, + 'categoryId' => CategoryId::class, + 'address' => [Address::class], + 'website' => [PointOfSale::class], + 'contactPerson' => [ContactPerson::class], + 'merchantApiConsent' => MerchantApiConsent::class, + ]; + + /** @var OfferCode */ + public $offerCode; + + /** @var Email */ + public $email; + + /** @var TaxId */ + public $taxId; + + /** @var Regon */ + public $regon; + + /** @var Krs */ + public $krs; + + /** @var LegalForm */ + public $legalForm; + + /** @var CategoryId */ + public $categoryId; + + /** @var Address */ + public $address; + + /** @var PointOfSale */ + public $website; + + /** @var ContactPerson */ + public $contactPerson; + + /** @var MerchantApiConsent */ + public $merchantApiConsent; + + public function getRequiredFields() + { + return [ + $this->offerCode, + $this->email, + $this->taxId, + $this->legalForm, + $this->categoryId, + $this->address, + $this->website, + ]; + } +} From d2d72ec788e6a42536110ab4c37f7a5c2783991a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Wed, 1 Oct 2025 09:40:34 +0200 Subject: [PATCH 02/16] test fix --- tests/Model/ModelsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Model/ModelsTest.php b/tests/Model/ModelsTest.php index 9d5274f..73cfa98 100644 --- a/tests/Model/ModelsTest.php +++ b/tests/Model/ModelsTest.php @@ -18,7 +18,7 @@ class ModelsTest extends TestCase */ public function testModel($class) { - self::assertTrue(class_exists($class) || interface_exists($class)); + self::assertTrue(class_exists($class) || interface_exists($class) || trait_exists($class)); if (class_exists($class)) { new $class(); From f237691d0d9d295df3b1026e42ee478200e0b9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Wed, 1 Oct 2025 09:43:04 +0200 Subject: [PATCH 03/16] test fix --- src/Model/Objects/Common/AddressFields.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Model/Objects/Common/AddressFields.php b/src/Model/Objects/Common/AddressFields.php index 5790501..56bd1ff 100644 --- a/src/Model/Objects/Common/AddressFields.php +++ b/src/Model/Objects/Common/AddressFields.php @@ -28,7 +28,6 @@ class AddressFields 'name' => Name::class, 'phone' => Phone::class, 'postalCode' => PostalCode::class, - 'roomNumber' => RoomNumber::class, 'street' => Street::class, ]; } \ No newline at end of file From ec923cdb7fec33203342be5bdd7e53e18cfa4cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Wed, 1 Oct 2025 09:46:08 +0200 Subject: [PATCH 04/16] test fix --- src/Api/Accounts/AccountsApi.php | 4 +--- src/Model/Objects/Common/AddressFields.php | 3 +-- src/Model/Objects/Common/AddressPropertiesTrait.php | 2 +- src/Model/Objects/Common/PointOfSaleFields.php | 2 +- src/Model/Objects/Common/PointOfSalePropertiesTrait.php | 2 +- src/Model/Objects/Merchant/ContactPerson.php | 1 - 6 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Api/Accounts/AccountsApi.php b/src/Api/Accounts/AccountsApi.php index 3ae9355..703732f 100644 --- a/src/Api/Accounts/AccountsApi.php +++ b/src/Api/Accounts/AccountsApi.php @@ -70,9 +70,7 @@ public function createAccount($fields) return $this->run(static::POST, '/accounts', $fields, new Account()); } - /** - * @param array $fields - */ + /** @param array $fields */ public function createMerchant($fields) { return $this->run(static::POST, '/v1/accounts/merchant', $fields, new Account()); diff --git a/src/Model/Objects/Common/AddressFields.php b/src/Model/Objects/Common/AddressFields.php index 56bd1ff..4b4a3d2 100644 --- a/src/Model/Objects/Common/AddressFields.php +++ b/src/Model/Objects/Common/AddressFields.php @@ -12,7 +12,6 @@ use Tpay\OpenApi\Model\Fields\Address\Name; use Tpay\OpenApi\Model\Fields\Address\Phone; use Tpay\OpenApi\Model\Fields\Address\PostalCode; -use Tpay\OpenApi\Model\Fields\Address\RoomNumber; use Tpay\OpenApi\Model\Fields\Address\Street; class AddressFields @@ -30,4 +29,4 @@ class AddressFields 'postalCode' => PostalCode::class, 'street' => Street::class, ]; -} \ No newline at end of file +} diff --git a/src/Model/Objects/Common/AddressPropertiesTrait.php b/src/Model/Objects/Common/AddressPropertiesTrait.php index 23ebdcb..030852a 100644 --- a/src/Model/Objects/Common/AddressPropertiesTrait.php +++ b/src/Model/Objects/Common/AddressPropertiesTrait.php @@ -48,4 +48,4 @@ trait AddressPropertiesTrait /** @var Street */ public $street; -} \ No newline at end of file +} diff --git a/src/Model/Objects/Common/PointOfSaleFields.php b/src/Model/Objects/Common/PointOfSaleFields.php index 03a33db..4723970 100644 --- a/src/Model/Objects/Common/PointOfSaleFields.php +++ b/src/Model/Objects/Common/PointOfSaleFields.php @@ -19,4 +19,4 @@ class PointOfSaleFields 'description' => Description::class, 'url' => Url::class, ]; -} \ No newline at end of file +} diff --git a/src/Model/Objects/Common/PointOfSalePropertiesTrait.php b/src/Model/Objects/Common/PointOfSalePropertiesTrait.php index be07e7b..1ea9ac6 100644 --- a/src/Model/Objects/Common/PointOfSalePropertiesTrait.php +++ b/src/Model/Objects/Common/PointOfSalePropertiesTrait.php @@ -28,4 +28,4 @@ trait PointOfSalePropertiesTrait /** @var Description */ public $description; -} \ No newline at end of file +} diff --git a/src/Model/Objects/Merchant/ContactPerson.php b/src/Model/Objects/Merchant/ContactPerson.php index dc6284a..ed82296 100644 --- a/src/Model/Objects/Merchant/ContactPerson.php +++ b/src/Model/Objects/Merchant/ContactPerson.php @@ -2,7 +2,6 @@ namespace Tpay\OpenApi\Model\Objects\Merchant; - use Tpay\OpenApi\Model\Fields\Person\Name; use Tpay\OpenApi\Model\Fields\Person\Surname; use Tpay\OpenApi\Model\Fields\PersonContact\Email; From 4484f90b30de251ad4ec3b82e26289a6f4421f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Wed, 1 Oct 2025 10:59:20 +0200 Subject: [PATCH 05/16] remove common traits --- src/Model/Objects/Accounts/Address.php | 61 +++++++++++++++++-- src/Model/Objects/Accounts/PointOfSale.php | 36 +++++++++-- src/Model/Objects/Common/AddressFields.php | 32 ---------- .../Objects/Common/AddressPropertiesTrait.php | 51 ---------------- .../Objects/Common/PointOfSaleFields.php | 22 ------- .../Common/PointOfSalePropertiesTrait.php | 31 ---------- src/Model/Objects/Merchant/Address.php | 61 +++++++++++++++++-- src/Model/Objects/Merchant/PointOfSale.php | 35 +++++++++-- tests/Model/ModelsTest.php | 2 +- 9 files changed, 177 insertions(+), 154 deletions(-) delete mode 100644 src/Model/Objects/Common/AddressFields.php delete mode 100644 src/Model/Objects/Common/AddressPropertiesTrait.php delete mode 100644 src/Model/Objects/Common/PointOfSaleFields.php delete mode 100644 src/Model/Objects/Common/PointOfSalePropertiesTrait.php diff --git a/src/Model/Objects/Accounts/Address.php b/src/Model/Objects/Accounts/Address.php index 4775ea6..d7ba354 100644 --- a/src/Model/Objects/Accounts/Address.php +++ b/src/Model/Objects/Accounts/Address.php @@ -2,20 +2,73 @@ namespace Tpay\OpenApi\Model\Objects\Accounts; +use Tpay\OpenApi\Model\Fields\Address\City; +use Tpay\OpenApi\Model\Fields\Address\Country; +use Tpay\OpenApi\Model\Fields\Address\FriendlyName; +use Tpay\OpenApi\Model\Fields\Address\HouseNumber; +use Tpay\OpenApi\Model\Fields\Address\IsCorrespondence; +use Tpay\OpenApi\Model\Fields\Address\IsInvoice; +use Tpay\OpenApi\Model\Fields\Address\IsMain; +use Tpay\OpenApi\Model\Fields\Address\Name; +use Tpay\OpenApi\Model\Fields\Address\Phone; +use Tpay\OpenApi\Model\Fields\Address\PostalCode; use Tpay\OpenApi\Model\Fields\Address\RoomNumber; -use Tpay\OpenApi\Model\Objects\Common\AddressFields; -use Tpay\OpenApi\Model\Objects\Common\AddressPropertiesTrait; +use Tpay\OpenApi\Model\Fields\Address\Street; use Tpay\OpenApi\Model\Objects\Objects; class Address extends Objects { - use AddressPropertiesTrait; + const OBJECT_FIELDS = [ + 'city' => City::class, + 'country' => Country::class, + 'friendlyName' => FriendlyName::class, + 'houseNumber' => HouseNumber::class, + 'roomNumber' => RoomNumber::class, + 'isCorrespondence' => IsCorrespondence::class, + 'isInvoice' => IsInvoice::class, + 'isMain' => IsMain::class, + 'name' => Name::class, + 'phone' => Phone::class, + 'postalCode' => PostalCode::class, + 'street' => Street::class, + ]; - const OBJECT_FIELDS = AddressFields::COMMON_FIELDS + ['roomNumber' => RoomNumber::class]; + /** @var City */ + public $city; + + /** @var Country */ + public $country; + + /** @var FriendlyName */ + public $friendlyName; + + /** @var HouseNumber */ + public $houseNumber; /** @var RoomNumber */ public $roomNumber; + /** @var IsCorrespondence */ + public $isCorrespondence; + + /** @var IsInvoice */ + public $isInvoice; + + /** @var IsMain */ + public $isMain; + + /** @var Name */ + public $name; + + /** @var Phone */ + public $phone; + + /** @var PostalCode */ + public $postalCode; + + /** @var Street */ + public $street; + public function getRequiredFields() { return [ diff --git a/src/Model/Objects/Accounts/PointOfSale.php b/src/Model/Objects/Accounts/PointOfSale.php index 6fadb05..0a0382f 100644 --- a/src/Model/Objects/Accounts/PointOfSale.php +++ b/src/Model/Objects/Accounts/PointOfSale.php @@ -2,19 +2,45 @@ namespace Tpay\OpenApi\Model\Objects\Accounts; -use Tpay\OpenApi\Model\Objects\Common\PointOfSaleFields; -use Tpay\OpenApi\Model\Objects\Common\PointOfSalePropertiesTrait; +use Tpay\OpenApi\Model\Fields\Address\Description; +use Tpay\OpenApi\Model\Fields\Address\FriendlyName; +use Tpay\OpenApi\Model\Fields\PointOfSale\Name; +use Tpay\OpenApi\Model\Fields\PointOfSale\Url; +use Tpay\OpenApi\Model\Identifiers\AccountId; +use Tpay\OpenApi\Model\Identifiers\PosId; use Tpay\OpenApi\Model\Objects\Objects; class PointOfSale extends Objects { - use PointOfSalePropertiesTrait; - - const OBJECT_FIELDS = PointOfSaleFields::COMMON_FIELDS + [ + const OBJECT_FIELDS = [ + 'posId' => PosId::class, + 'accountId' => AccountId::class, + 'name' => Name::class, + 'friendlyName' => FriendlyName::class, + 'description' => Description::class, + 'url' => Url::class, 'date' => PointOfSaleDate::class, 'settings' => PointOfSaleSettings::class, ]; + /** @var PosId */ + public $posId; + + /** @var AccountId */ + public $accountId; + + /** @var FriendlyName */ + public $friendlyName; + + /** @var Name */ + public $name; + + /** @var Url */ + public $url; + + /** @var Description */ + public $description; + /** @var PointOfSaleDate */ public $date; diff --git a/src/Model/Objects/Common/AddressFields.php b/src/Model/Objects/Common/AddressFields.php deleted file mode 100644 index 4b4a3d2..0000000 --- a/src/Model/Objects/Common/AddressFields.php +++ /dev/null @@ -1,32 +0,0 @@ - City::class, - 'country' => Country::class, - 'friendlyName' => FriendlyName::class, - 'houseNumber' => HouseNumber::class, - 'isCorrespondence' => IsCorrespondence::class, - 'isInvoice' => IsInvoice::class, - 'isMain' => IsMain::class, - 'name' => Name::class, - 'phone' => Phone::class, - 'postalCode' => PostalCode::class, - 'street' => Street::class, - ]; -} diff --git a/src/Model/Objects/Common/AddressPropertiesTrait.php b/src/Model/Objects/Common/AddressPropertiesTrait.php deleted file mode 100644 index 030852a..0000000 --- a/src/Model/Objects/Common/AddressPropertiesTrait.php +++ /dev/null @@ -1,51 +0,0 @@ - PosId::class, - 'accountId' => AccountId::class, - 'name' => Name::class, - 'friendlyName' => FriendlyName::class, - 'description' => Description::class, - 'url' => Url::class, - ]; -} diff --git a/src/Model/Objects/Common/PointOfSalePropertiesTrait.php b/src/Model/Objects/Common/PointOfSalePropertiesTrait.php deleted file mode 100644 index 1ea9ac6..0000000 --- a/src/Model/Objects/Common/PointOfSalePropertiesTrait.php +++ /dev/null @@ -1,31 +0,0 @@ - City::class, + 'country' => Country::class, + 'friendlyName' => FriendlyName::class, + 'houseNumber' => HouseNumber::class, + 'flatNumber' => FlatNumber::class, + 'isCorrespondence' => IsCorrespondence::class, + 'isInvoice' => IsInvoice::class, + 'isMain' => IsMain::class, + 'name' => Name::class, + 'phone' => Phone::class, + 'postalCode' => PostalCode::class, + 'street' => Street::class, + ]; - const OBJECT_FIELDS = AddressFields::COMMON_FIELDS + ['flatNumber' => FlatNumber::class]; + /** @var City */ + public $city; + + /** @var Country */ + public $country; + + /** @var FriendlyName */ + public $friendlyName; + + /** @var HouseNumber */ + public $houseNumber; /** @var FlatNumber */ public $flatNumber; + /** @var IsCorrespondence */ + public $isCorrespondence; + + /** @var IsInvoice */ + public $isInvoice; + + /** @var IsMain */ + public $isMain; + + /** @var Name */ + public $name; + + /** @var Phone */ + public $phone; + + /** @var PostalCode */ + public $postalCode; + + /** @var Street */ + public $street; + public function getRequiredFields() { return [ diff --git a/src/Model/Objects/Merchant/PointOfSale.php b/src/Model/Objects/Merchant/PointOfSale.php index f354a4a..e87680b 100644 --- a/src/Model/Objects/Merchant/PointOfSale.php +++ b/src/Model/Objects/Merchant/PointOfSale.php @@ -2,15 +2,42 @@ namespace Tpay\OpenApi\Model\Objects\Merchant; -use Tpay\OpenApi\Model\Objects\Common\PointOfSaleFields; -use Tpay\OpenApi\Model\Objects\Common\PointOfSalePropertiesTrait; +use Tpay\OpenApi\Model\Fields\Address\Description; +use Tpay\OpenApi\Model\Fields\Address\FriendlyName; +use Tpay\OpenApi\Model\Fields\PointOfSale\Name; +use Tpay\OpenApi\Model\Fields\PointOfSale\Url; +use Tpay\OpenApi\Model\Identifiers\AccountId; +use Tpay\OpenApi\Model\Identifiers\PosId; use Tpay\OpenApi\Model\Objects\Objects; class PointOfSale extends Objects { - use PointOfSalePropertiesTrait; + const OBJECT_FIELDS = [ + 'posId' => PosId::class, + 'accountId' => AccountId::class, + 'name' => Name::class, + 'friendlyName' => FriendlyName::class, + 'description' => Description::class, + 'url' => Url::class, + ]; - const OBJECT_FIELDS = PointOfSaleFields::COMMON_FIELDS; + /** @var PosId */ + public $posId; + + /** @var AccountId */ + public $accountId; + + /** @var FriendlyName */ + public $friendlyName; + + /** @var Name */ + public $name; + + /** @var Url */ + public $url; + + /** @var Description */ + public $description; public function getRequiredFields() { diff --git a/tests/Model/ModelsTest.php b/tests/Model/ModelsTest.php index 73cfa98..9d5274f 100644 --- a/tests/Model/ModelsTest.php +++ b/tests/Model/ModelsTest.php @@ -18,7 +18,7 @@ class ModelsTest extends TestCase */ public function testModel($class) { - self::assertTrue(class_exists($class) || interface_exists($class) || trait_exists($class)); + self::assertTrue(class_exists($class) || interface_exists($class)); if (class_exists($class)) { new $class(); From 8c7520dc1e23526d10c77e5cd0b425f1079c86af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Thu, 2 Oct 2025 12:49:37 +0200 Subject: [PATCH 06/16] add unique fields validation --- src/Api/Accounts/AccountsApi.php | 3 +- src/Manager/Manager.php | 5 + src/Model/Objects/Merchant/Address.php | 13 +- src/Model/Objects/Merchant/PointOfSale.php | 20 - src/Model/Objects/Objects.php | 7 + src/Model/Objects/ObjectsValidator.php | 53 ++ src/Model/Objects/RequestBody/Merchant.php | 4 + tests/Api/Accounts/AccountsApiTest.php | 602 +++++++++++++++++++++ 8 files changed, 680 insertions(+), 27 deletions(-) create mode 100644 tests/Api/Accounts/AccountsApiTest.php diff --git a/src/Api/Accounts/AccountsApi.php b/src/Api/Accounts/AccountsApi.php index 703732f..b613f4a 100644 --- a/src/Api/Accounts/AccountsApi.php +++ b/src/Api/Accounts/AccountsApi.php @@ -4,6 +4,7 @@ use Tpay\OpenApi\Api\ApiAction; use Tpay\OpenApi\Model\Objects\RequestBody\Account; +use Tpay\OpenApi\Model\Objects\RequestBody\Merchant; class AccountsApi extends ApiAction { @@ -73,7 +74,7 @@ public function createAccount($fields) /** @param array $fields */ public function createMerchant($fields) { - return $this->run(static::POST, '/v1/accounts/merchant', $fields, new Account()); + return $this->run(static::POST, '/v1/accounts/merchant', $fields, new Merchant()); } public function getMcc() diff --git a/src/Manager/Manager.php b/src/Manager/Manager.php index 3624987..b3aa561 100644 --- a/src/Manager/Manager.php +++ b/src/Manager/Manager.php @@ -4,6 +4,7 @@ use Tpay\OpenApi\Model\Objects\Objects; use Tpay\OpenApi\Model\Objects\ObjectsValidator; +use Tpay\OpenApi\Model\Objects\RequestBody\Merchant; class Manager { @@ -29,6 +30,10 @@ public function setFields($fields, $strictCheck = true) $this->requestBody->strictCheck = $strictCheck; $this->requestBody->setObjectValues($this->requestBody, $fields); $this->ObjectsValidator->isSetRequiredFields($this->requestBody); + if ($this->requestBody instanceof Merchant) { + $this->ObjectsValidator->checkUniqueFields($this->requestBody); + + } return $this; } diff --git a/src/Model/Objects/Merchant/Address.php b/src/Model/Objects/Merchant/Address.php index db97224..2bd2cdd 100644 --- a/src/Model/Objects/Merchant/Address.php +++ b/src/Model/Objects/Merchant/Address.php @@ -5,7 +5,6 @@ use Tpay\OpenApi\Model\Fields\Address\City; use Tpay\OpenApi\Model\Fields\Address\Country; use Tpay\OpenApi\Model\Fields\Address\FlatNumber; -use Tpay\OpenApi\Model\Fields\Address\FriendlyName; use Tpay\OpenApi\Model\Fields\Address\HouseNumber; use Tpay\OpenApi\Model\Fields\Address\IsCorrespondence; use Tpay\OpenApi\Model\Fields\Address\IsInvoice; @@ -21,7 +20,6 @@ class Address extends Objects const OBJECT_FIELDS = [ 'city' => City::class, 'country' => Country::class, - 'friendlyName' => FriendlyName::class, 'houseNumber' => HouseNumber::class, 'flatNumber' => FlatNumber::class, 'isCorrespondence' => IsCorrespondence::class, @@ -39,9 +37,6 @@ class Address extends Objects /** @var Country */ public $country; - /** @var FriendlyName */ - public $friendlyName; - /** @var HouseNumber */ public $houseNumber; @@ -72,7 +67,6 @@ class Address extends Objects public function getRequiredFields() { return [ - $this->friendlyName, $this->name, $this->street, $this->houseNumber, @@ -81,4 +75,11 @@ public function getRequiredFields() $this->country, ]; } + + public function getUniqueFields() + { + return [ + 'isMain' => true + ]; + } } diff --git a/src/Model/Objects/Merchant/PointOfSale.php b/src/Model/Objects/Merchant/PointOfSale.php index e87680b..268b8e3 100644 --- a/src/Model/Objects/Merchant/PointOfSale.php +++ b/src/Model/Objects/Merchant/PointOfSale.php @@ -2,43 +2,23 @@ namespace Tpay\OpenApi\Model\Objects\Merchant; -use Tpay\OpenApi\Model\Fields\Address\Description; -use Tpay\OpenApi\Model\Fields\Address\FriendlyName; use Tpay\OpenApi\Model\Fields\PointOfSale\Name; use Tpay\OpenApi\Model\Fields\PointOfSale\Url; -use Tpay\OpenApi\Model\Identifiers\AccountId; -use Tpay\OpenApi\Model\Identifiers\PosId; use Tpay\OpenApi\Model\Objects\Objects; class PointOfSale extends Objects { const OBJECT_FIELDS = [ - 'posId' => PosId::class, - 'accountId' => AccountId::class, 'name' => Name::class, - 'friendlyName' => FriendlyName::class, - 'description' => Description::class, 'url' => Url::class, ]; - /** @var PosId */ - public $posId; - - /** @var AccountId */ - public $accountId; - - /** @var FriendlyName */ - public $friendlyName; - /** @var Name */ public $name; /** @var Url */ public $url; - /** @var Description */ - public $description; - public function getRequiredFields() { return [ diff --git a/src/Model/Objects/Objects.php b/src/Model/Objects/Objects.php index 283c9e8..bf00914 100644 --- a/src/Model/Objects/Objects.php +++ b/src/Model/Objects/Objects.php @@ -10,6 +10,8 @@ class Objects implements ObjectsInterface { const OBJECT_FIELDS = []; + const UNIQUE_FIELDS = []; + public $strictCheck = true; public function __construct() @@ -85,6 +87,11 @@ private function setObjectsInArray($object, $fieldValue, $fieldName) $this->setObjectValues($object->{$fieldName}->{$field}, $value); } if (is_array($object->{$fieldName})) { + if (!isset($object->{$fieldName}[$field])) { + $objectClass = get_class($object->{$fieldName}[0]); + $object->{$fieldName}[] = new $objectClass(); + } + $this->setObjectValues($object->{$fieldName}[$field], $value); } } else { diff --git a/src/Model/Objects/ObjectsValidator.php b/src/Model/Objects/ObjectsValidator.php index a689e53..8490cbb 100644 --- a/src/Model/Objects/ObjectsValidator.php +++ b/src/Model/Objects/ObjectsValidator.php @@ -7,6 +7,59 @@ class ObjectsValidator { + /** + * @param Objects $objectClass + * + * @return void + */ + public function checkUniqueFields($objectClass) + { + foreach ($objectClass::UNIQUE_FIELDS as $collectionName => $fieldRules) { + $collection = isset($objectClass->{$collectionName}) ? $objectClass->{$collectionName} : []; + + foreach ($fieldRules as $fieldName => $uniqueValue) { + $this->validateUniqueField($collection, $fieldName, $uniqueValue); + } + } + } + + /** + * @param Objects[] $objects + * + * @throws UnexpectedValueException + * + * @return void + */ + private function validateUniqueField(array $objects, $fieldName, $uniqueValue) + { + $count = 0; + + foreach ($objects as $object) { + if (!$object instanceof Objects) { + continue; + } + + if (!property_exists($object, $fieldName)) { + continue; + } + + $field = $object->{$fieldName}; + + if ($field instanceof Field && $field->getValue() === $uniqueValue) { + $count++; + } + + if ($count > 1) { + throw new UnexpectedValueException(sprintf( + 'Field "%s" with value "%s" must be unique across %s objects', + $fieldName, + var_export($uniqueValue, true), + $object->getName() + )); + } + } + } + /** * @param Objects $objectClass * diff --git a/src/Model/Objects/RequestBody/Merchant.php b/src/Model/Objects/RequestBody/Merchant.php index 215f3e0..d5ce4fb 100644 --- a/src/Model/Objects/RequestBody/Merchant.php +++ b/src/Model/Objects/RequestBody/Merchant.php @@ -31,6 +31,10 @@ class Merchant extends Objects 'merchantApiConsent' => MerchantApiConsent::class, ]; + const UNIQUE_FIELDS = [ + 'address' => ['isMain' => true], + ]; + /** @var OfferCode */ public $offerCode; diff --git a/tests/Api/Accounts/AccountsApiTest.php b/tests/Api/Accounts/AccountsApiTest.php new file mode 100644 index 0000000..0d26a95 --- /dev/null +++ b/tests/Api/Accounts/AccountsApiTest.php @@ -0,0 +1,602 @@ +createAccountsApiWithCurlMock('ok'); + + $result = $transactionsApi->createMerchant($merchantData); + + self::assertSame('ok', $result); + } + + /** @dataProvider invalidMerchantData */ + public function testCreatingInvalidMerchant(array $merchantData, $exception, $exceptionMessage) + { + $transactionsApi = $this->createAccountsApiWithCurlMock('error'); + + $this->expectException($exception); + $this->expectExceptionMessage($exceptionMessage); + $transactionsApi->createMerchant($merchantData); + } + + private function createAccountsApiWithCurlMock($response) + { + $accessToken = $this->createMock(AccessToken::class); + + $token = $this->createMock(Token::class); + $token->access_token = $accessToken; + + $transactionsApi = new AccountsApi($token, false); + + CurlMock::setConsecutiveReturnedTransfers(json_encode($response)); + + return $transactionsApi; + } + + public function validMerchantData() + { + yield 'One Address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + 'isInvoice' => true, + 'isCorrespondence' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example.com', + 'url' => 'https://www.example.com', + ] + ] + ] + ]; + + yield 'Different Addresses' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica1', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica2', + 'houseNumber' => '456', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => false, + 'isInvoice' => true, + ], + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica3', + 'houseNumber' => '789', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => false, + 'isCorrespondence' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example.com', + 'url' => 'https://www.example.com', + ] + ] + ] + ]; + + yield 'Many websites' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica1', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + [ + 'name' => 'www.example2.com', + 'url' => 'https://www.example2.com', + ], + [ + 'name' => 'www.example3.com', + 'url' => 'https://www.example3.com', + ] + ] + ] + ]; + } + + public function invalidMerchantData() + { + yield 'No Offer Code' => [ + [ + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + 'isInvoice' => true, + 'isCorrespondence' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example.com', + 'url' => 'https://www.example.com', + ] + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Account\OfferCode" is required in object Merchant' + ]; + + yield 'No email address' => [ + [ + 'offerCode' => 'XXXXX', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica1', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example.com', + 'url' => 'https://www.example.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Person\Email" is required in object Merchant' + ]; + + yield 'No legalForm' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@example.com', + 'taxId' => '1234567890', + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica1', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example.com', + 'url' => 'https://www.example.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Account\LegalForm" is required in object Merchant' + ]; + + yield 'No categoryId' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@example.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica1', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example.com', + 'url' => 'https://www.example.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Identifiers\CategoryId" is required in object Merchant' + ]; + + yield 'Empty address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@example.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 0, + 'address' => [ + ], + 'website' => [ + [ + 'name' => 'www.example.com', + 'url' => 'https://www.example.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Name" is required in object Address' + ]; + + yield 'No address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@example.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 0, + 'website' => [ + [ + 'name' => 'www.example.com', + 'url' => 'https://www.example.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Name" is required in object Address' + ]; + + yield 'Empty website' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@example.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 0, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica1', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\PointOfSale\Name" is required in object PointOfSale' + ]; + + yield 'No website' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@example.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 0, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'ulica1', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\PointOfSale\Name" is required in object PointOfSale' + ]; + + yield 'No street in address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Street" is required in object Address' + ]; + + yield 'No house number in address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'glowna', + 'postalCode' => '11-111', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\HouseNumber" is required in object Address' + ]; + + yield 'No postal code in address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'glowna', + 'houseNumber' => '123', + 'city' => 'Poznań', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\PostalCode" is required in object Address' + ]; + + yield 'No city in address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'glowna', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\City" is required in object Address' + ]; + + yield 'No country in address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'glowna', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Warszawa', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Country" is required in object Address' + ]; + + yield 'Too long country in address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'glowna', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Warszawa', + 'country' => 'Polska', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + ] + ], + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Value of field Tpay\OpenApi\Model\Fields\Address\Country is too long. Max allowed 2' + ]; + + yield 'Too short country in address' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'glowna', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Warszawa', + 'country' => 'P', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + ] + ], + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Value of field Tpay\OpenApi\Model\Fields\Address\Country is too short. Min required 2' + ]; + + yield 'Multi main addresses' => [ + [ + 'offerCode' => 'XXXXX', + 'email' => 'admin@exmaple.com', + 'taxId' => '1234567890', + 'legalForm' => 1, + 'categoryId' => 2, + 'address' => [ + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'glowna', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Warszawa', + 'country' => 'PL', + 'isMain' => true, + ], + [ + 'name' => 'Example Sp.z.o.o', + 'street' => 'glowna', + 'houseNumber' => '123', + 'postalCode' => '11-111', + 'city' => 'Warszawa', + 'country' => 'PL', + 'isMain' => true, + ], + ], + 'website' => [ + [ + 'name' => 'www.example1.com', + 'url' => 'https://www.example1.com', + ], + ] + ], + 'exception' => UnexpectedValueException::class, + 'exceptionMessage' => 'Field "isMain" with value "true" must be unique across Address objects' + ]; + } +} \ No newline at end of file From d0d9d7ae26cd7300bd837254f7cd30d0e058c9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Thu, 2 Oct 2025 12:55:45 +0200 Subject: [PATCH 07/16] fixer --- src/Manager/Manager.php | 5 +- src/Model/Objects/ObjectsValidator.php | 70 +++++++++++----------- src/Model/Objects/RequestBody/Merchant.php | 1 - tests/Api/Accounts/AccountsApiTest.php | 62 +++++++++---------- 4 files changed, 66 insertions(+), 72 deletions(-) diff --git a/src/Manager/Manager.php b/src/Manager/Manager.php index b3aa561..ba51732 100644 --- a/src/Manager/Manager.php +++ b/src/Manager/Manager.php @@ -30,10 +30,7 @@ public function setFields($fields, $strictCheck = true) $this->requestBody->strictCheck = $strictCheck; $this->requestBody->setObjectValues($this->requestBody, $fields); $this->ObjectsValidator->isSetRequiredFields($this->requestBody); - if ($this->requestBody instanceof Merchant) { - $this->ObjectsValidator->checkUniqueFields($this->requestBody); - - } + $this->ObjectsValidator->checkUniqueFields($this->requestBody); return $this; } diff --git a/src/Model/Objects/ObjectsValidator.php b/src/Model/Objects/ObjectsValidator.php index 8490cbb..de68e05 100644 --- a/src/Model/Objects/ObjectsValidator.php +++ b/src/Model/Objects/ObjectsValidator.php @@ -9,8 +9,6 @@ class ObjectsValidator { /** * @param Objects $objectClass - * - * @return void */ public function checkUniqueFields($objectClass) { @@ -24,11 +22,43 @@ public function checkUniqueFields($objectClass) } /** - * @param Objects[] $objects + * @param Objects $objectClass * * @throws UnexpectedValueException * - * @return void + * @return bool + */ + public function isSetRequiredFields($objectClass) + { + $requiredFields = $objectClass->getRequiredFields(); + foreach ($requiredFields as $field) { + if (is_subclass_of($field, Objects::class)) { + $this->isSetRequiredFields($field); + continue; + } + if (is_array($field)) { + foreach ($field as $value) { + $this->isSetRequiredFields($value); + } + continue; + } + /** @var Field $field */ + if (is_null($field->getValue())) { + throw new UnexpectedValueException( + sprintf('Field "%s" is required in object %s', $field->getName(), $objectClass->getName()) + ); + } + } + + return true; + } + + /** + * @param array $objects + * @param mixed $fieldName + * @param mixed $uniqueValue + * + * @throws UnexpectedValueException */ private function validateUniqueField(array $objects, $fieldName, $uniqueValue) { @@ -59,36 +89,4 @@ private function validateUniqueField(array $objects, $fieldName, $uniqueValue) } } } - - /** - * @param Objects $objectClass - * - * @throws UnexpectedValueException - * - * @return bool - */ - public function isSetRequiredFields($objectClass) - { - $requiredFields = $objectClass->getRequiredFields(); - foreach ($requiredFields as $field) { - if (is_subclass_of($field, Objects::class)) { - $this->isSetRequiredFields($field); - continue; - } - if (is_array($field)) { - foreach ($field as $value) { - $this->isSetRequiredFields($value); - } - continue; - } - /** @var Field $field */ - if (is_null($field->getValue())) { - throw new UnexpectedValueException( - sprintf('Field "%s" is required in object %s', $field->getName(), $objectClass->getName()) - ); - } - } - - return true; - } } diff --git a/src/Model/Objects/RequestBody/Merchant.php b/src/Model/Objects/RequestBody/Merchant.php index d5ce4fb..fdb9fc4 100644 --- a/src/Model/Objects/RequestBody/Merchant.php +++ b/src/Model/Objects/RequestBody/Merchant.php @@ -30,7 +30,6 @@ class Merchant extends Objects 'contactPerson' => [ContactPerson::class], 'merchantApiConsent' => MerchantApiConsent::class, ]; - const UNIQUE_FIELDS = [ 'address' => ['isMain' => true], ]; diff --git a/tests/Api/Accounts/AccountsApiTest.php b/tests/Api/Accounts/AccountsApiTest.php index 0d26a95..24e495f 100644 --- a/tests/Api/Accounts/AccountsApiTest.php +++ b/tests/Api/Accounts/AccountsApiTest.php @@ -32,20 +32,6 @@ public function testCreatingInvalidMerchant(array $merchantData, $exception, $ex $transactionsApi->createMerchant($merchantData); } - private function createAccountsApiWithCurlMock($response) - { - $accessToken = $this->createMock(AccessToken::class); - - $token = $this->createMock(Token::class); - $token->access_token = $accessToken; - - $transactionsApi = new AccountsApi($token, false); - - CurlMock::setConsecutiveReturnedTransfers(json_encode($response)); - - return $transactionsApi; - } - public function validMerchantData() { yield 'One Address' => [ @@ -189,7 +175,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Account\OfferCode" is required in object Merchant' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Account\OfferCode" is required in object Merchant', ]; yield 'No email address' => [ @@ -217,7 +203,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Person\Email" is required in object Merchant' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Person\Email" is required in object Merchant', ]; yield 'No legalForm' => [ @@ -245,7 +231,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Account\LegalForm" is required in object Merchant' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Account\LegalForm" is required in object Merchant', ]; yield 'No categoryId' => [ @@ -273,7 +259,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Identifiers\CategoryId" is required in object Merchant' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Identifiers\CategoryId" is required in object Merchant', ]; yield 'Empty address' => [ @@ -293,7 +279,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Name" is required in object Address' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Name" is required in object Address', ]; yield 'No address' => [ @@ -311,7 +297,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Name" is required in object Address' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Name" is required in object Address', ]; yield 'Empty website' => [ @@ -337,7 +323,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\PointOfSale\Name" is required in object PointOfSale' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\PointOfSale\Name" is required in object PointOfSale', ]; yield 'No website' => [ @@ -360,7 +346,7 @@ public function invalidMerchantData() ], ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\PointOfSale\Name" is required in object PointOfSale' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\PointOfSale\Name" is required in object PointOfSale', ]; yield 'No street in address' => [ @@ -388,7 +374,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Street" is required in object Address' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Street" is required in object Address', ]; yield 'No house number in address' => [ @@ -416,7 +402,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\HouseNumber" is required in object Address' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\HouseNumber" is required in object Address', ]; yield 'No postal code in address' => [ @@ -444,7 +430,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\PostalCode" is required in object Address' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\PostalCode" is required in object Address', ]; yield 'No city in address' => [ @@ -472,7 +458,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\City" is required in object Address' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\City" is required in object Address', ]; yield 'No country in address' => [ @@ -500,7 +486,7 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Country" is required in object Address' + 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Country" is required in object Address', ]; yield 'Too long country in address' => [ @@ -529,7 +515,7 @@ public function invalidMerchantData() ] ], 'exception' => InvalidArgumentException::class, - 'exceptionMessage' => 'Value of field Tpay\OpenApi\Model\Fields\Address\Country is too long. Max allowed 2' + 'exceptionMessage' => 'Value of field Tpay\OpenApi\Model\Fields\Address\Country is too long. Max allowed 2', ]; yield 'Too short country in address' => [ @@ -558,7 +544,7 @@ public function invalidMerchantData() ] ], 'exception' => InvalidArgumentException::class, - 'exceptionMessage' => 'Value of field Tpay\OpenApi\Model\Fields\Address\Country is too short. Min required 2' + 'exceptionMessage' => 'Value of field Tpay\OpenApi\Model\Fields\Address\Country is too short. Min required 2', ]; yield 'Multi main addresses' => [ @@ -596,7 +582,21 @@ public function invalidMerchantData() ] ], 'exception' => UnexpectedValueException::class, - 'exceptionMessage' => 'Field "isMain" with value "true" must be unique across Address objects' + 'exceptionMessage' => 'Field "isMain" with value "true" must be unique across Address objects', ]; } -} \ No newline at end of file + + private function createAccountsApiWithCurlMock($response) + { + $accessToken = $this->createMock(AccessToken::class); + + $token = $this->createMock(Token::class); + $token->access_token = $accessToken; + + $transactionsApi = new AccountsApi($token, false); + + CurlMock::setConsecutiveReturnedTransfers(json_encode($response)); + + return $transactionsApi; + } +} From 4e869376c1fd87919231b1d917ec39b63fba125b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Thu, 2 Oct 2025 12:59:50 +0200 Subject: [PATCH 08/16] fixer --- src/Manager/Manager.php | 1 - src/Model/Objects/Merchant/Address.php | 7 ---- src/Model/Objects/Objects.php | 1 - src/Model/Objects/ObjectsValidator.php | 8 ++-- tests/Api/Accounts/AccountsApiTest.php | 51 +++++++++++++------------- 5 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/Manager/Manager.php b/src/Manager/Manager.php index ba51732..751b551 100644 --- a/src/Manager/Manager.php +++ b/src/Manager/Manager.php @@ -4,7 +4,6 @@ use Tpay\OpenApi\Model\Objects\Objects; use Tpay\OpenApi\Model\Objects\ObjectsValidator; -use Tpay\OpenApi\Model\Objects\RequestBody\Merchant; class Manager { diff --git a/src/Model/Objects/Merchant/Address.php b/src/Model/Objects/Merchant/Address.php index 2bd2cdd..8e920d5 100644 --- a/src/Model/Objects/Merchant/Address.php +++ b/src/Model/Objects/Merchant/Address.php @@ -75,11 +75,4 @@ public function getRequiredFields() $this->country, ]; } - - public function getUniqueFields() - { - return [ - 'isMain' => true - ]; - } } diff --git a/src/Model/Objects/Objects.php b/src/Model/Objects/Objects.php index bf00914..34c624b 100644 --- a/src/Model/Objects/Objects.php +++ b/src/Model/Objects/Objects.php @@ -9,7 +9,6 @@ class Objects implements ObjectsInterface { const OBJECT_FIELDS = []; - const UNIQUE_FIELDS = []; public $strictCheck = true; diff --git a/src/Model/Objects/ObjectsValidator.php b/src/Model/Objects/ObjectsValidator.php index de68e05..e773cee 100644 --- a/src/Model/Objects/ObjectsValidator.php +++ b/src/Model/Objects/ObjectsValidator.php @@ -7,9 +7,7 @@ class ObjectsValidator { - /** - * @param Objects $objectClass - */ + /** @param Objects $objectClass */ public function checkUniqueFields($objectClass) { foreach ($objectClass::UNIQUE_FIELDS as $collectionName => $fieldRules) { @@ -55,8 +53,8 @@ public function isSetRequiredFields($objectClass) /** * @param array $objects - * @param mixed $fieldName - * @param mixed $uniqueValue + * @param mixed $fieldName + * @param mixed $uniqueValue * * @throws UnexpectedValueException */ diff --git a/tests/Api/Accounts/AccountsApiTest.php b/tests/Api/Accounts/AccountsApiTest.php index 24e495f..763b624 100644 --- a/tests/Api/Accounts/AccountsApiTest.php +++ b/tests/Api/Accounts/AccountsApiTest.php @@ -58,9 +58,9 @@ public function validMerchantData() [ 'name' => 'www.example.com', 'url' => 'https://www.example.com', - ] - ] - ] + ], + ], + ], ]; yield 'Different Addresses' => [ @@ -105,9 +105,9 @@ public function validMerchantData() [ 'name' => 'www.example.com', 'url' => 'https://www.example.com', - ] - ] - ] + ], + ], + ], ]; yield 'Many websites' => [ @@ -140,9 +140,9 @@ public function validMerchantData() [ 'name' => 'www.example3.com', 'url' => 'https://www.example3.com', - ] - ] - ] + ], + ], + ], ]; } @@ -171,8 +171,8 @@ public function invalidMerchantData() [ 'name' => 'www.example.com', 'url' => 'https://www.example.com', - ] - ] + ], + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Account\OfferCode" is required in object Merchant', @@ -200,7 +200,7 @@ public function invalidMerchantData() 'name' => 'www.example.com', 'url' => 'https://www.example.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Person\Email" is required in object Merchant', @@ -228,7 +228,7 @@ public function invalidMerchantData() 'name' => 'www.example.com', 'url' => 'https://www.example.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Account\LegalForm" is required in object Merchant', @@ -256,7 +256,7 @@ public function invalidMerchantData() 'name' => 'www.example.com', 'url' => 'https://www.example.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Identifiers\CategoryId" is required in object Merchant', @@ -276,7 +276,7 @@ public function invalidMerchantData() 'name' => 'www.example.com', 'url' => 'https://www.example.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Name" is required in object Address', @@ -294,7 +294,7 @@ public function invalidMerchantData() 'name' => 'www.example.com', 'url' => 'https://www.example.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Name" is required in object Address', @@ -319,8 +319,7 @@ public function invalidMerchantData() ], ], 'website' => [ - - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\PointOfSale\Name" is required in object PointOfSale', @@ -371,7 +370,7 @@ public function invalidMerchantData() 'name' => 'www.example1.com', 'url' => 'https://www.example1.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Street" is required in object Address', @@ -399,7 +398,7 @@ public function invalidMerchantData() 'name' => 'www.example1.com', 'url' => 'https://www.example1.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\HouseNumber" is required in object Address', @@ -427,7 +426,7 @@ public function invalidMerchantData() 'name' => 'www.example1.com', 'url' => 'https://www.example1.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\PostalCode" is required in object Address', @@ -455,7 +454,7 @@ public function invalidMerchantData() 'name' => 'www.example1.com', 'url' => 'https://www.example1.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\City" is required in object Address', @@ -483,7 +482,7 @@ public function invalidMerchantData() 'name' => 'www.example1.com', 'url' => 'https://www.example1.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "Tpay\OpenApi\Model\Fields\Address\Country" is required in object Address', @@ -512,7 +511,7 @@ public function invalidMerchantData() 'name' => 'www.example1.com', 'url' => 'https://www.example1.com', ], - ] + ], ], 'exception' => InvalidArgumentException::class, 'exceptionMessage' => 'Value of field Tpay\OpenApi\Model\Fields\Address\Country is too long. Max allowed 2', @@ -541,7 +540,7 @@ public function invalidMerchantData() 'name' => 'www.example1.com', 'url' => 'https://www.example1.com', ], - ] + ], ], 'exception' => InvalidArgumentException::class, 'exceptionMessage' => 'Value of field Tpay\OpenApi\Model\Fields\Address\Country is too short. Min required 2', @@ -579,7 +578,7 @@ public function invalidMerchantData() 'name' => 'www.example1.com', 'url' => 'https://www.example1.com', ], - ] + ], ], 'exception' => UnexpectedValueException::class, 'exceptionMessage' => 'Field "isMain" with value "true" must be unique across Address objects', From db341837343d696ccb00eb7b53b9331a59755aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Thu, 2 Oct 2025 20:51:44 +0200 Subject: [PATCH 09/16] fixer --- src/Api/Accounts/AccountsApi.php | 2 ++ src/Model/Objects/Objects.php | 41 ++++++++++++++++++++++++-- tests/Api/Accounts/AccountsApiTest.php | 7 +++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/Api/Accounts/AccountsApi.php b/src/Api/Accounts/AccountsApi.php index b613f4a..0745ac1 100644 --- a/src/Api/Accounts/AccountsApi.php +++ b/src/Api/Accounts/AccountsApi.php @@ -68,6 +68,8 @@ public function getBalanceByAccountId($accountId) */ public function createAccount($fields) { + trigger_error(sprintf('Method %s is deprecated.', __METHOD__), E_USER_DEPRECATED); + return $this->run(static::POST, '/accounts', $fields, new Account()); } diff --git a/src/Model/Objects/Objects.php b/src/Model/Objects/Objects.php index 34c624b..fab0715 100644 --- a/src/Model/Objects/Objects.php +++ b/src/Model/Objects/Objects.php @@ -5,6 +5,14 @@ use InvalidArgumentException; use ReflectionClass; use Tpay\OpenApi\Model\Fields\Field; +use Tpay\OpenApi\Model\Objects\Accounts\Address as AccountAddress; +use Tpay\OpenApi\Model\Objects\Accounts\Person; +use Tpay\OpenApi\Model\Objects\Accounts\PointOfSale as AccountPointOfSale; +use Tpay\OpenApi\Model\Objects\Merchant\Address as MerchantAddress; +use Tpay\OpenApi\Model\Objects\Merchant\ContactPerson; +use Tpay\OpenApi\Model\Objects\Merchant\PointOfSale as MerchantPointOfSale; +use Tpay\OpenApi\Model\Objects\RequestBody\Account; +use Tpay\OpenApi\Model\Objects\RequestBody\Merchant; class Objects implements ObjectsInterface { @@ -87,8 +95,7 @@ private function setObjectsInArray($object, $fieldValue, $fieldName) } if (is_array($object->{$fieldName})) { if (!isset($object->{$fieldName}[$field])) { - $objectClass = get_class($object->{$fieldName}[0]); - $object->{$fieldName}[] = new $objectClass(); + $object->{$fieldName}[] = $this->setArrayFields($object, $fieldName); } $this->setObjectValues($object->{$fieldName}[$field], $value); @@ -105,6 +112,36 @@ private function setObjectsInArray($object, $fieldValue, $fieldName) } } + private function setArrayFields($object, $fieldName) + { + if ($object instanceof Merchant) { + switch ($fieldName) { + case 'address': + return new MerchantAddress(); + case 'website': + return new MerchantPointOfSale(); + case 'contactPerson': + return new ContactPerson(); + case 'default': + throw new InvalidArgumentException(sprintf('Field %s as array is not supported', $fieldName)); + } + } + if ($object instanceof Account) { + switch ($fieldName) { + case 'address': + return new AccountAddress(); + case 'website': + return new AccountPointOfSale(); + case 'person': + return new Person(); + case 'default': + throw new InvalidArgumentException(sprintf('Field %s as array is not supported', $fieldName)); + } + } + + throw new InvalidArgumentException(sprintf('Field %s as array is not supported', $fieldName)); + } + /** * @param object|string $class * diff --git a/tests/Api/Accounts/AccountsApiTest.php b/tests/Api/Accounts/AccountsApiTest.php index 763b624..de14ae1 100644 --- a/tests/Api/Accounts/AccountsApiTest.php +++ b/tests/Api/Accounts/AccountsApiTest.php @@ -32,6 +32,13 @@ public function testCreatingInvalidMerchant(array $merchantData, $exception, $ex $transactionsApi->createMerchant($merchantData); } + public function testXX() + { + $transactionsApi = $this->createAccountsApiWithCurlMock('error'); + + $transactionsApi->createAccount([]); + } + public function validMerchantData() { yield 'One Address' => [ From 70c7eb46b8fcdf567304ecacbfd7bc3d2b2e73a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Thu, 2 Oct 2025 20:54:13 +0200 Subject: [PATCH 10/16] fixer --- tests/Api/Accounts/AccountsApiTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/Api/Accounts/AccountsApiTest.php b/tests/Api/Accounts/AccountsApiTest.php index de14ae1..763b624 100644 --- a/tests/Api/Accounts/AccountsApiTest.php +++ b/tests/Api/Accounts/AccountsApiTest.php @@ -32,13 +32,6 @@ public function testCreatingInvalidMerchant(array $merchantData, $exception, $ex $transactionsApi->createMerchant($merchantData); } - public function testXX() - { - $transactionsApi = $this->createAccountsApiWithCurlMock('error'); - - $transactionsApi->createAccount([]); - } - public function validMerchantData() { yield 'One Address' => [ From 85609f549f7554b5fc0a73c44b0b0835b0cb9720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Thu, 2 Oct 2025 21:06:53 +0200 Subject: [PATCH 11/16] fixer --- examples/AccountsApi/AccountsApiExample.php | 43 +++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/examples/AccountsApi/AccountsApiExample.php b/examples/AccountsApi/AccountsApiExample.php index 282504b..dca6034 100644 --- a/examples/AccountsApi/AccountsApiExample.php +++ b/examples/AccountsApi/AccountsApiExample.php @@ -105,6 +105,15 @@ public function createAccount() return $this; } + public function createMerchant() + { + $merchantConfig = $this->getNewMerchantConfig(); + $newMerchant = $this->TpayApi->accounts()->createMerchant($merchantConfig); + var_dump($newMerchant); + + return $this; + } + private function getNewAccountConfig() { $offerCode = 'PTON8'; @@ -148,6 +157,40 @@ private function getNewAccountConfig() 'notifyByEmail' => true, ]; } + + private function getNewMerchantConfig() + { + $offerCode = 'PTON8'; + $pos = [ + 'name' => 'Przykladowe Zakupy Online', + 'url' => 'https://przykladowezakupy.pl', + ]; + $address1 = [ + 'name' => 'Example Sp. z o.o.', + 'street' => 'Ul. Jelenia', + 'houseNumber' => '123', + 'postalCode' => '54-134', + 'city' => 'Warszawa', + 'country' => 'PL', + ]; + $contactPerson = [ + 'name' => 'Jan', + 'surname' => 'Kowalski', + 'phone' => '(0) 111222333', + 'email' => 'jan.kowalski@example.com', + ]; + + return [ + 'offerCode' => $offerCode, + 'email' => 'merchant@example.com', + 'taxId' => '7773061579', + 'legalForm' => 3, + 'categoryId' => 62, + 'website' => [$pos], + 'address' => [$address1], + 'person' => [$contactPerson], + ]; + } } (new AccountsApiExample())->runAllExamples(); From 384ea97bf91cca25f9a909dff202d4b6b1a018ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Fri, 3 Oct 2025 09:11:42 +0200 Subject: [PATCH 12/16] fixer --- src/Factory/ArrayObjectFactory.php | 52 +++++++++++ src/Model/Objects/Objects.php | 45 ++-------- tests/Factory/ArrayObjectFactoryTest.php | 110 +++++++++++++++++++++++ 3 files changed, 168 insertions(+), 39 deletions(-) create mode 100644 src/Factory/ArrayObjectFactory.php create mode 100644 tests/Factory/ArrayObjectFactoryTest.php diff --git a/src/Factory/ArrayObjectFactory.php b/src/Factory/ArrayObjectFactory.php new file mode 100644 index 0000000..5484e5e --- /dev/null +++ b/src/Factory/ArrayObjectFactory.php @@ -0,0 +1,52 @@ +getName())); + } +} \ No newline at end of file diff --git a/src/Model/Objects/Objects.php b/src/Model/Objects/Objects.php index fab0715..67d2464 100644 --- a/src/Model/Objects/Objects.php +++ b/src/Model/Objects/Objects.php @@ -4,15 +4,8 @@ use InvalidArgumentException; use ReflectionClass; +use Tpay\OpenApi\Factory\ArrayObjectFactory; use Tpay\OpenApi\Model\Fields\Field; -use Tpay\OpenApi\Model\Objects\Accounts\Address as AccountAddress; -use Tpay\OpenApi\Model\Objects\Accounts\Person; -use Tpay\OpenApi\Model\Objects\Accounts\PointOfSale as AccountPointOfSale; -use Tpay\OpenApi\Model\Objects\Merchant\Address as MerchantAddress; -use Tpay\OpenApi\Model\Objects\Merchant\ContactPerson; -use Tpay\OpenApi\Model\Objects\Merchant\PointOfSale as MerchantPointOfSale; -use Tpay\OpenApi\Model\Objects\RequestBody\Account; -use Tpay\OpenApi\Model\Objects\RequestBody\Merchant; class Objects implements ObjectsInterface { @@ -21,9 +14,13 @@ class Objects implements ObjectsInterface public $strictCheck = true; + /** @var ArrayObjectFactory */ + private $factory; + public function __construct() { $this->injectObjectFields(static::OBJECT_FIELDS); + $this->factory = new ArrayObjectFactory(); } /** @return array */ @@ -95,7 +92,7 @@ private function setObjectsInArray($object, $fieldValue, $fieldName) } if (is_array($object->{$fieldName})) { if (!isset($object->{$fieldName}[$field])) { - $object->{$fieldName}[] = $this->setArrayFields($object, $fieldName); + $object->{$fieldName}[] = $this->factory->create($fieldName, $object); } $this->setObjectValues($object->{$fieldName}[$field], $value); @@ -112,36 +109,6 @@ private function setObjectsInArray($object, $fieldValue, $fieldName) } } - private function setArrayFields($object, $fieldName) - { - if ($object instanceof Merchant) { - switch ($fieldName) { - case 'address': - return new MerchantAddress(); - case 'website': - return new MerchantPointOfSale(); - case 'contactPerson': - return new ContactPerson(); - case 'default': - throw new InvalidArgumentException(sprintf('Field %s as array is not supported', $fieldName)); - } - } - if ($object instanceof Account) { - switch ($fieldName) { - case 'address': - return new AccountAddress(); - case 'website': - return new AccountPointOfSale(); - case 'person': - return new Person(); - case 'default': - throw new InvalidArgumentException(sprintf('Field %s as array is not supported', $fieldName)); - } - } - - throw new InvalidArgumentException(sprintf('Field %s as array is not supported', $fieldName)); - } - /** * @param object|string $class * diff --git a/tests/Factory/ArrayObjectFactoryTest.php b/tests/Factory/ArrayObjectFactoryTest.php new file mode 100644 index 0000000..de7d726 --- /dev/null +++ b/tests/Factory/ArrayObjectFactoryTest.php @@ -0,0 +1,110 @@ +create($fieldName, $object); + + $this->assertInstanceOf($expectedResult, $result); + } + + /** @dataProvider invalidObjectProvider */ + public function testInvalidCreate($fieldName, $object, $exception, $exceptionMessage) + { + $factory = new ArrayObjectFactory(); + + $this->expectException($exception); + $this->expectExceptionMessage($exceptionMessage); + + $factory->create($fieldName, $object); + } + + public function validObjectProvider() + { + yield 'merchant Address' => [ + 'fieldName' => 'address', + 'object' => new Merchant(), + 'expectedResult' => MerchantAddress::class, + ]; + + yield 'merchant POS' => [ + 'fieldName' => 'website', + 'object' => new Merchant(), + 'expectedResult' => MerchantPointOfSale::class, + ]; + + yield 'merchant contactPerson' => [ + 'fieldName' => 'contactPerson', + 'object' => new Merchant(), + 'expectedResult' => ContactPerson::class, + ]; + + yield 'account Address' => [ + 'fieldName' => 'address', + 'object' => new Account(), + 'expectedResult' => AccountAddress::class, + ]; + + yield 'account POS' => [ + 'fieldName' => 'website', + 'object' => new Account(), + 'expectedResult' => AccountPointOfSale::class, + ]; + + yield 'account contactPerson' => [ + 'fieldName' => 'person', + 'object' => new Account(), + 'expectedResult' => Person::class, + ]; + } + + public function invalidObjectProvider() + { + yield 'merchant non array field' => [ + 'fieldName' => 'email', + 'object' => new Merchant(), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Field email as array is not supported in Merchant object', + ]; + + yield 'account non array field' => [ + 'fieldName' => 'taxId', + 'object' => new Account(), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Field taxId as array is not supported in Account object', + ]; + + yield 'unsupported object' => [ + 'fieldName' => 'amount', + 'object' => new Refund(), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Field amount as array is not supported in Refund object', + ]; + + yield 'invalid object type' => [ + 'fieldName' => 'amount', + 'object' => new StdClass(), + 'exception' => InvalidArgumentException::class, + 'exceptionMessage' => 'Parent object must extend Tpay\OpenApi\Model\Objects\Objects, got stdClass', + ]; + } +} \ No newline at end of file From 267584bb30d8e1639946d6e81c87540acafc6a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Fri, 3 Oct 2025 09:12:48 +0200 Subject: [PATCH 13/16] fixer --- src/Factory/ArrayObjectFactory.php | 2 +- tests/Factory/ArrayObjectFactoryTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Factory/ArrayObjectFactory.php b/src/Factory/ArrayObjectFactory.php index 5484e5e..2759079 100644 --- a/src/Factory/ArrayObjectFactory.php +++ b/src/Factory/ArrayObjectFactory.php @@ -49,4 +49,4 @@ public function create($fieldName, $parentObject) throw new InvalidArgumentException(sprintf('Field %s as array is not supported in %s object', $fieldName, $parentObject->getName())); } -} \ No newline at end of file +} diff --git a/tests/Factory/ArrayObjectFactoryTest.php b/tests/Factory/ArrayObjectFactoryTest.php index de7d726..12911b1 100644 --- a/tests/Factory/ArrayObjectFactoryTest.php +++ b/tests/Factory/ArrayObjectFactoryTest.php @@ -107,4 +107,4 @@ public function invalidObjectProvider() 'exceptionMessage' => 'Parent object must extend Tpay\OpenApi\Model\Objects\Objects, got stdClass', ]; } -} \ No newline at end of file +} From 080531fe75223d30e7e02844eee8616389c65b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Fri, 3 Oct 2025 09:53:51 +0200 Subject: [PATCH 14/16] fixer --- examples/AccountsApi/AccountsApiExample.php | 1 + src/Factory/ArrayObjectFactory.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/examples/AccountsApi/AccountsApiExample.php b/examples/AccountsApi/AccountsApiExample.php index dca6034..15f97ca 100644 --- a/examples/AccountsApi/AccountsApiExample.php +++ b/examples/AccountsApi/AccountsApiExample.php @@ -22,6 +22,7 @@ public function __construct() public function runAllExamples() { $this + ->createMerchant() ->createAccount() ->getAccounts() ->getCategories() diff --git a/src/Factory/ArrayObjectFactory.php b/src/Factory/ArrayObjectFactory.php index 2759079..983d97c 100644 --- a/src/Factory/ArrayObjectFactory.php +++ b/src/Factory/ArrayObjectFactory.php @@ -33,6 +33,8 @@ public function create($fieldName, $parentObject) return new MerchantPointOfSale(); case 'contactPerson': return new ContactPerson(); + default: + throw new InvalidArgumentException(sprintf('Unsupported field "%s" in %s', $fieldName, $parentObject->getName())); } } @@ -44,6 +46,8 @@ public function create($fieldName, $parentObject) return new AccountPointOfSale(); case 'person': return new Person(); + default: + throw new InvalidArgumentException(sprintf('Unsupported field "%s" in %s', $fieldName, $parentObject->getName())); } } From 9d6076b91578dcf1299639877c007202096f06b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Fri, 3 Oct 2025 09:55:23 +0200 Subject: [PATCH 15/16] fixer --- tests/Factory/ArrayObjectFactoryTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Factory/ArrayObjectFactoryTest.php b/tests/Factory/ArrayObjectFactoryTest.php index 12911b1..2c958a0 100644 --- a/tests/Factory/ArrayObjectFactoryTest.php +++ b/tests/Factory/ArrayObjectFactoryTest.php @@ -83,14 +83,14 @@ public function invalidObjectProvider() 'fieldName' => 'email', 'object' => new Merchant(), 'exception' => InvalidArgumentException::class, - 'exceptionMessage' => 'Field email as array is not supported in Merchant object', + 'exceptionMessage' => 'Unsupported field "email" in Merchant', ]; yield 'account non array field' => [ 'fieldName' => 'taxId', 'object' => new Account(), 'exception' => InvalidArgumentException::class, - 'exceptionMessage' => 'Field taxId as array is not supported in Account object', + 'exceptionMessage' => 'Unsupported field "taxId" in Account', ]; yield 'unsupported object' => [ From 2d59f470829dbe908aacbfd60b04db88774162b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksander=20K=C4=85kol?= Date: Fri, 3 Oct 2025 12:09:08 +0200 Subject: [PATCH 16/16] fix example --- examples/AccountsApi/AccountsApiExample.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/AccountsApi/AccountsApiExample.php b/examples/AccountsApi/AccountsApiExample.php index 15f97ca..03735b4 100644 --- a/examples/AccountsApi/AccountsApiExample.php +++ b/examples/AccountsApi/AccountsApiExample.php @@ -173,6 +173,9 @@ private function getNewMerchantConfig() 'postalCode' => '54-134', 'city' => 'Warszawa', 'country' => 'PL', + 'isInvoice' => true, + 'isMain' => true, + 'isCorrespondence' => true, ]; $contactPerson = [ 'name' => 'Jan', @@ -189,7 +192,7 @@ private function getNewMerchantConfig() 'categoryId' => 62, 'website' => [$pos], 'address' => [$address1], - 'person' => [$contactPerson], + 'contactPerson' => [$contactPerson], ]; } }