diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index d6cab5a1..5780e448 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -20,9 +20,9 @@ jobs: - lowest - highest php-version: - - "7.4" - - "8.0" - "8.1" + - "8.2" + - "8.3" steps: - name: Checkout uses: actions/checkout@v2 @@ -75,10 +75,6 @@ jobs: composer remove guzzlehttp/guzzle --dev composer run acceptance-tests -- --filter "retrieves merchant accounts" - composer require guzzlehttp/guzzle --dev - composer remove symfony/http-client --dev - composer run acceptance-tests -- --filter "retrieves merchant accounts" - composer require php-http/curl-client --dev composer remove guzzlehttp/guzzle --dev composer run acceptance-tests -- --filter "retrieves merchant accounts" diff --git a/CHANGELOG.md b/CHANGELOG.md index 487c51ca..47c76175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.0] - 2024-03-26 + +### Changed + +- Removed Illuminate dependencies +- Removed input validation and `TrueLayer\Exception\ValidationException` +- Minimum PHP version supported is 8.1 + ## [1.7.0] - 2024-02-13 ### Changed diff --git a/README.md b/README.md index 984fbc49..bc7fc458 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,11 @@ This package simplifies working with the TrueLayer API, by: -1. Handling authentication, including token expiry, invalidation and caching +1. Handling authentication (including token expiry) and caching 2. Signing requests 3. Managing idempotency keys, including retrying on conflicts 4. Retrying failed requests, where it makes sense to do so -5. Validating your data -6. Providing type-hinted methods and classes to work with +5. Providing type-hinted methods and classes to work with @@ -1205,16 +1204,6 @@ Thrown if the request data cannot be json encoded prior to calling the APIs. \TrueLayer\Exceptions\ApiRequestJsonSerializationException ``` -### ValidationException - -Thrown if the data you provide to the client library or the API response data is invalid. - -```php -\TrueLayer\Exceptions\ValidationException - -$e->getErrors(); // Get the validation errors as an array -``` - ### InvalidArgumentException Thrown when a provided argument is invalid, for example an invalid beneficiary type diff --git a/composer.json b/composer.json index aca49ec9..8e27fcf8 100644 --- a/composer.json +++ b/composer.json @@ -30,18 +30,16 @@ }, "prefer-stable": true, "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "ext-json": "*", "ext-openssl": "*", "psr/http-client-implementation": "^1.0", "psr/http-factory-implementation": "*", "psr/http-message-implementation": "^1.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "truelayer/signing": "^0.1.0", + "truelayer/signing": "^1.0.0", "ramsey/uuid": "^3.7|^4.1", - "illuminate/validation": "^v6.0|^v7.0|^v8.0|^v9.0", - "illuminate/support": "^v6.0|^v7.0|^v8.0|^v9.0", - "illuminate/encryption": "^v6.0|^v7.0|^v8.0|^v9.0", + "nesbot/carbon": "^2.62.1|^3.0.0", "php-http/discovery": "^1.15.1" }, "suggest": { diff --git a/src/Entities/AccountIdentifier/AccountIdentifierBuilder.php b/src/Entities/AccountIdentifier/AccountIdentifierBuilder.php index 94214754..79879423 100644 --- a/src/Entities/AccountIdentifier/AccountIdentifierBuilder.php +++ b/src/Entities/AccountIdentifier/AccountIdentifierBuilder.php @@ -6,7 +6,6 @@ use TrueLayer\Entities\EntityBuilder; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\AccountIdentifier\AccountIdentifierBuilderInterface; use TrueLayer\Interfaces\AccountIdentifier\AccountIdentifierInterface; use TrueLayer\Interfaces\AccountIdentifier\IbanInterface; @@ -16,7 +15,6 @@ final class AccountIdentifierBuilder extends EntityBuilder implements AccountIde { /** * @throws InvalidArgumentException - * @throws ValidationException * * @return ScanInterface */ @@ -27,7 +25,6 @@ public function sortCodeAccountNumber(): ScanInterface /** * @throws InvalidArgumentException - * @throws ValidationException * * @return IbanInterface */ @@ -40,7 +37,6 @@ public function iban(): IbanInterface * @param mixed[] $data * * @throws InvalidArgumentException - * @throws ValidationException * * @return AccountIdentifierInterface */ diff --git a/src/Entities/AccountIdentifier/Bban.php b/src/Entities/AccountIdentifier/Bban.php index 4975f439..f13ebf0f 100644 --- a/src/Entities/AccountIdentifier/Bban.php +++ b/src/Entities/AccountIdentifier/Bban.php @@ -23,13 +23,6 @@ final class Bban extends Entity implements BbanInterface 'bban', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'bban' => 'required|alpha_num|max:30', - ]; - /** * @return string */ diff --git a/src/Entities/AccountIdentifier/Iban.php b/src/Entities/AccountIdentifier/Iban.php index b3d1b61b..a7ba293e 100644 --- a/src/Entities/AccountIdentifier/Iban.php +++ b/src/Entities/AccountIdentifier/Iban.php @@ -23,13 +23,6 @@ final class Iban extends Entity implements IbanInterface 'iban', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'iban' => 'required|alpha_num|max:34|min:4', - ]; - /** * @return string */ diff --git a/src/Entities/AccountIdentifier/Nrb.php b/src/Entities/AccountIdentifier/Nrb.php index bfc2e0bb..41e8dbd8 100644 --- a/src/Entities/AccountIdentifier/Nrb.php +++ b/src/Entities/AccountIdentifier/Nrb.php @@ -23,13 +23,6 @@ final class Nrb extends Entity implements NrbInterface 'nrb', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'nrb' => 'required|numeric|digits:26', - ]; - /** * @return string */ diff --git a/src/Entities/AccountIdentifier/Scan.php b/src/Entities/AccountIdentifier/Scan.php index 589915b0..756a2d1a 100644 --- a/src/Entities/AccountIdentifier/Scan.php +++ b/src/Entities/AccountIdentifier/Scan.php @@ -29,14 +29,6 @@ final class Scan extends Entity implements ScanInterface 'account_number', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'sort_code' => 'required|numeric|digits:6', - 'account_number' => 'required|numeric|digits:8', - ]; - /** * @return string */ diff --git a/src/Entities/Address.php b/src/Entities/Address.php index 00afc20f..6c20f51c 100644 --- a/src/Entities/Address.php +++ b/src/Entities/Address.php @@ -50,18 +50,6 @@ class Address extends Entity implements AddressInterface 'country_code', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'address_line1' => 'string|required', - 'address_line2' => 'string|nullable', - 'city' => 'string|required', - 'state' => 'string|nullable', - 'zip' => 'string|required', - 'country_code' => 'string|required', - ]; - /** * @return string|null */ diff --git a/src/Entities/Beneficiary/BeneficiaryBuilder.php b/src/Entities/Beneficiary/BeneficiaryBuilder.php index 7d81564f..fb03707a 100644 --- a/src/Entities/Beneficiary/BeneficiaryBuilder.php +++ b/src/Entities/Beneficiary/BeneficiaryBuilder.php @@ -6,7 +6,6 @@ use TrueLayer\Entities\EntityBuilder; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\Beneficiary\BeneficiaryBuilderInterface; use TrueLayer\Interfaces\Beneficiary\BeneficiaryInterface; use TrueLayer\Interfaces\Beneficiary\ExternalAccountBeneficiaryInterface; @@ -17,7 +16,6 @@ final class BeneficiaryBuilder extends EntityBuilder implements BeneficiaryBuild { /** * @throws InvalidArgumentException - * @throws ValidationException * * @return ExternalAccountBeneficiaryInterface */ @@ -30,7 +28,6 @@ public function externalAccount(): ExternalAccountBeneficiaryInterface * @param MerchantAccountInterface|null $merchantAccount * * @throws InvalidArgumentException - * @throws ValidationException * * @return MerchantBeneficiaryInterface */ @@ -49,7 +46,6 @@ public function merchantAccount(MerchantAccountInterface $merchantAccount = null * @param mixed[] $data * * @throws InvalidArgumentException - * @throws ValidationException * * @return BeneficiaryInterface */ diff --git a/src/Entities/Beneficiary/ExternalAccountBeneficiary.php b/src/Entities/Beneficiary/ExternalAccountBeneficiary.php index a36c6d7b..be67aceb 100644 --- a/src/Entities/Beneficiary/ExternalAccountBeneficiary.php +++ b/src/Entities/Beneficiary/ExternalAccountBeneficiary.php @@ -8,7 +8,6 @@ use TrueLayer\Entities\Entity; use TrueLayer\Interfaces\AccountIdentifier\AccountIdentifierInterface; use TrueLayer\Interfaces\Beneficiary\ExternalAccountBeneficiaryInterface; -use TrueLayer\Validation\ValidType; final class ExternalAccountBeneficiary extends Entity implements ExternalAccountBeneficiaryInterface { @@ -44,18 +43,6 @@ final class ExternalAccountBeneficiary extends Entity implements ExternalAccount 'type', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'account_holder_name' => 'nullable|string', - 'reference' => 'required|string', - 'account_identifier' => ['required', ValidType::of(AccountIdentifierInterface::class)], - ]; - } - /** * @return string|null */ diff --git a/src/Entities/Beneficiary/MerchantBeneficiary.php b/src/Entities/Beneficiary/MerchantBeneficiary.php index bfea0b75..fad6abd9 100644 --- a/src/Entities/Beneficiary/MerchantBeneficiary.php +++ b/src/Entities/Beneficiary/MerchantBeneficiary.php @@ -35,15 +35,6 @@ final class MerchantBeneficiary extends Entity implements MerchantBeneficiaryInt 'type', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'merchant_account_id' => 'required|string', - 'account_holder_name' => 'nullable|string', - 'reference' => 'nullable|string', - ]; - /** * @return string|null */ diff --git a/src/Entities/Entity.php b/src/Entities/Entity.php index 6d5c0afe..9f166ff1 100644 --- a/src/Entities/Entity.php +++ b/src/Entities/Entity.php @@ -4,19 +4,15 @@ namespace TrueLayer\Entities; -use Illuminate\Contracts\Validation\Factory as ValidatorFactory; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\ArrayableInterface; use TrueLayer\Interfaces\Factories\EntityFactoryInterface; use TrueLayer\Interfaces\HasAttributesInterface; use TrueLayer\Traits\ArrayableAttributes; use TrueLayer\Traits\CastsAttributes; -use TrueLayer\Traits\ValidatesAttributes; abstract class Entity implements ArrayableInterface, HasAttributesInterface { - use ValidatesAttributes; use CastsAttributes; use ArrayableAttributes; @@ -26,22 +22,17 @@ abstract class Entity implements ArrayableInterface, HasAttributesInterface protected EntityFactoryInterface $entityFactory; /** - * @param ValidatorFactory $validatorFactory * @param EntityFactoryInterface $entityFactory */ public function __construct( - ValidatorFactory $validatorFactory, EntityFactoryInterface $entityFactory ) { - $this->validatorFactory = $validatorFactory; $this->entityFactory = $entityFactory; } /** * @param mixed[] $data * - * @throws ValidationException - * @throws InvalidArgumentException * @throws InvalidArgumentException * * @return $this @@ -49,7 +40,6 @@ public function __construct( public function fill(array $data): self { $data = $this->castData($data); - $this->validateData($data); $this->setValues($data); return $this; @@ -61,8 +51,6 @@ public function fill(array $data): self * @param class-string $abstract * @param mixed[]|null $data * - * @throws ValidationException - * @throws InvalidArgumentException * @throws InvalidArgumentException * * @return T @@ -79,7 +67,6 @@ protected function make(string $abstract, array $data = null) * @param mixed[]|null $data * * @throws InvalidArgumentException - * @throws ValidationException * * @return T[] */ diff --git a/src/Entities/Hpp.php b/src/Entities/Hpp.php index ff4a5d78..6769d17d 100644 --- a/src/Entities/Hpp.php +++ b/src/Entities/Hpp.php @@ -4,9 +4,8 @@ namespace TrueLayer\Entities; -use Illuminate\Support\Str; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\HppInterface; +use TrueLayer\Services\Util\Str; final class Hpp extends Entity implements HppInterface { @@ -58,19 +57,6 @@ final class Hpp extends Entity implements HppInterface 'c_tertiary' => 'tertiary_colour', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'base_url' => 'required|url', - 'payment_id' => 'required|string', - 'resource_token' => 'required|string', - 'return_uri' => 'required|url', - 'c_primary' => 'regex:/^([0-9A-F]{3}){1,2}$/i', - 'c_secondary' => 'regex:/^([0-9A-F]{3}){1,2}$/i', - 'c_tertiary' => 'regex:/^([0-9A-F]{3}){1,2}$/i', - ]; - /** * @param string $baseUrl * @@ -212,13 +198,11 @@ public function getTertiaryColour(): ?string } /** - * @throws ValidationException - * * @return string */ public function toUrl(): string { - $params = $this->validate()->toArray(); + $params = $this->toArray(); unset($params['base_url']); return $this->baseUrl . '#' . \http_build_query( @@ -227,8 +211,6 @@ public function toUrl(): string } /** - * @throws ValidationException - * * @return string */ public function __toString(): string diff --git a/src/Entities/MerchantAccount/MerchantAccount.php b/src/Entities/MerchantAccount/MerchantAccount.php index ee173517..3b2942fb 100644 --- a/src/Entities/MerchantAccount/MerchantAccount.php +++ b/src/Entities/MerchantAccount/MerchantAccount.php @@ -7,7 +7,6 @@ use TrueLayer\Entities\Entity; use TrueLayer\Interfaces\AccountIdentifier\AccountIdentifierInterface; use TrueLayer\Interfaces\MerchantAccount\MerchantAccountInterface; -use TrueLayer\Validation\ValidType; final class MerchantAccount extends Entity implements MerchantAccountInterface { @@ -57,22 +56,6 @@ final class MerchantAccount extends Entity implements MerchantAccountInterface 'account_holder_name', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'required|string', - 'currency' => 'required|string', - 'account_identifiers' => 'required|array', - 'account_identifiers.*' => [ValidType::of(AccountIdentifierInterface::class)], - 'available_balance_in_minor' => 'required|int', - 'current_balance_in_minor' => 'required|int', - 'account_holder_name' => 'required|string', - ]; - } - /** * @return string|null */ diff --git a/src/Entities/Payment/AuthorizationFlow/Action/ProviderSelectionAction.php b/src/Entities/Payment/AuthorizationFlow/Action/ProviderSelectionAction.php index 48bec800..5c875d2e 100644 --- a/src/Entities/Payment/AuthorizationFlow/Action/ProviderSelectionAction.php +++ b/src/Entities/Payment/AuthorizationFlow/Action/ProviderSelectionAction.php @@ -8,7 +8,6 @@ use TrueLayer\Entities\Payment\AuthorizationFlow\Action; use TrueLayer\Interfaces\Payment\AuthorizationFlow\Action\ProviderSelectionActionInterface; use TrueLayer\Interfaces\Provider\ProviderInterface; -use TrueLayer\Validation\ValidType; class ProviderSelectionAction extends Action implements ProviderSelectionActionInterface { @@ -32,16 +31,6 @@ class ProviderSelectionAction extends Action implements ProviderSelectionActionI 'providers.*' => ProviderInterface::class, ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'providers.*' => [ValidType::of(ProviderInterface::class)], - ]; - } - /** * @return ProviderInterface[] */ diff --git a/src/Entities/Payment/AuthorizationFlow/Action/RedirectAction.php b/src/Entities/Payment/AuthorizationFlow/Action/RedirectAction.php index bb1e27dc..d71e57fd 100644 --- a/src/Entities/Payment/AuthorizationFlow/Action/RedirectAction.php +++ b/src/Entities/Payment/AuthorizationFlow/Action/RedirectAction.php @@ -8,7 +8,6 @@ use TrueLayer\Entities\Payment\AuthorizationFlow\Action; use TrueLayer\Interfaces\Payment\AuthorizationFlow\Action\RedirectActionInterface; use TrueLayer\Interfaces\Provider\ProviderInterface; -use TrueLayer\Validation\ValidType; class RedirectAction extends Action implements RedirectActionInterface { @@ -38,17 +37,6 @@ class RedirectAction extends Action implements RedirectActionInterface 'metadata' => 'provider', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'uri' => 'required|url', - 'metadata' => ['nullable', ValidType::of(ProviderInterface::class)], - ]; - } - /** * @return string */ diff --git a/src/Entities/Payment/AuthorizationFlow/AuthorizationFlow.php b/src/Entities/Payment/AuthorizationFlow/AuthorizationFlow.php index d540b514..7bb2c793 100644 --- a/src/Entities/Payment/AuthorizationFlow/AuthorizationFlow.php +++ b/src/Entities/Payment/AuthorizationFlow/AuthorizationFlow.php @@ -8,7 +8,6 @@ use TrueLayer\Interfaces\Payment\AuthorizationFlow\ActionInterface; use TrueLayer\Interfaces\Payment\AuthorizationFlow\AuthorizationFlowInterface; use TrueLayer\Interfaces\Payment\AuthorizationFlow\ConfigurationInterface; -use TrueLayer\Validation\ValidType; final class AuthorizationFlow extends Entity implements AuthorizationFlowInterface { @@ -32,17 +31,6 @@ final class AuthorizationFlow extends Entity implements AuthorizationFlowInterfa 'configuration' => 'configuration', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'actions.next' => ['nullable', ValidType::of(ActionInterface::class)], - 'configuration' => ['nullable', ValidType::of(ConfigurationInterface::class)], - ]; - } - /** * @return ConfigurationInterface|null */ diff --git a/src/Entities/Payment/AuthorizationFlow/AuthorizationFlowAuthorizationFailed.php b/src/Entities/Payment/AuthorizationFlow/AuthorizationFlowAuthorizationFailed.php index 7cce9af0..63fbb97c 100644 --- a/src/Entities/Payment/AuthorizationFlow/AuthorizationFlowAuthorizationFailed.php +++ b/src/Entities/Payment/AuthorizationFlow/AuthorizationFlowAuthorizationFailed.php @@ -26,17 +26,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'failure_stage' => 'required|string', - 'failure_reason' => 'nullable|string', - ]); - } - /** * @return string */ diff --git a/src/Entities/Payment/AuthorizationFlow/AuthorizationFlowResponse.php b/src/Entities/Payment/AuthorizationFlow/AuthorizationFlowResponse.php index d0a633ae..be920069 100644 --- a/src/Entities/Payment/AuthorizationFlow/AuthorizationFlowResponse.php +++ b/src/Entities/Payment/AuthorizationFlow/AuthorizationFlowResponse.php @@ -4,13 +4,10 @@ namespace TrueLayer\Entities\Payment\AuthorizationFlow; -use TrueLayer\Constants\AuthorizationFlowStatusTypes; use TrueLayer\Entities\Entity; use TrueLayer\Interfaces\Payment\AuthorizationFlow\ActionInterface; use TrueLayer\Interfaces\Payment\AuthorizationFlow\AuthorizationFlowInterface; use TrueLayer\Interfaces\Payment\AuthorizationFlow\AuthorizationFlowResponseInterface; -use TrueLayer\Validation\AllowedConstant; -use TrueLayer\Validation\ValidType; abstract class AuthorizationFlowResponse extends Entity implements AuthorizationFlowResponseInterface { @@ -39,17 +36,6 @@ abstract class AuthorizationFlowResponse extends Entity implements Authorization 'authorization_flow', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'status' => ['required', AllowedConstant::in(AuthorizationFlowStatusTypes::class)], - 'authorization_flow' => ['nullable', ValidType::of(AuthorizationFlowInterface::class)], - ]; - } - /** * @return ActionInterface|null */ diff --git a/src/Entities/Payment/AuthorizationFlow/Configuration.php b/src/Entities/Payment/AuthorizationFlow/Configuration.php index b65a6256..b7a54080 100644 --- a/src/Entities/Payment/AuthorizationFlow/Configuration.php +++ b/src/Entities/Payment/AuthorizationFlow/Configuration.php @@ -21,13 +21,6 @@ class Configuration extends Entity implements ConfigurationInterface 'redirect.return_uri' => 'redirect_return_uri', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'redirect.return_uri' => 'required_if:redirect.status,supported', - ]; - /** * @return string|null */ diff --git a/src/Entities/Payment/AuthorizationFlow/StartAuthorizationFlowRequest.php b/src/Entities/Payment/AuthorizationFlow/StartAuthorizationFlowRequest.php index 86aa49ed..aa33635c 100644 --- a/src/Entities/Payment/AuthorizationFlow/StartAuthorizationFlowRequest.php +++ b/src/Entities/Payment/AuthorizationFlow/StartAuthorizationFlowRequest.php @@ -10,12 +10,10 @@ use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\HasApiFactoryInterface; use TrueLayer\Interfaces\Payment\AuthorizationFlow\AuthorizationFlowResponseInterface; use TrueLayer\Interfaces\Payment\StartAuthorizationFlowRequestInterface; use TrueLayer\Traits\ProvidesApiFactory; -use TrueLayer\Validation\ValidType; final class StartAuthorizationFlowRequest extends Entity implements StartAuthorizationFlowRequestInterface, HasApiFactoryInterface { @@ -65,22 +63,6 @@ final class StartAuthorizationFlowRequest extends Entity implements StartAuthori 'form.input_types' => 'formInputTypes', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'user_account_selection' => ['nullable', ValidType::of(\ArrayObject::class)], - 'provider_selection' => ['nullable', ValidType::of(\ArrayObject::class)], - 'scheme_selection' => ['nullable', ValidType::of(\ArrayObject::class)], - 'redirect.return_uri' => ['required', 'string'], - 'redirect.direct_return_uri' => ['nullable', 'string'], - 'form.input_types' => ['nullable', 'array'], - 'form.input_types.*' => ['string'], - ]; - } - /** * @param string $paymentId * @@ -176,11 +158,10 @@ public function formInputTypes(array $types): StartAuthorizationFlowRequestInter } /** - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException + * @throws ApiRequestJsonSerializationException * * @return AuthorizationFlowResponseInterface */ @@ -188,7 +169,7 @@ public function start(): AuthorizationFlowResponseInterface { $data = $this->getApiFactory()->paymentsApi()->startAuthorizationFlow( $this->paymentId, - $this->validate()->toArray(), + $this->toArray(), ); return $this->make(AuthorizationFlowResponseInterface::class, $data); diff --git a/src/Entities/Payment/PaymentCreated.php b/src/Entities/Payment/PaymentCreated.php index cf39238c..a33c49bf 100644 --- a/src/Entities/Payment/PaymentCreated.php +++ b/src/Entities/Payment/PaymentCreated.php @@ -9,7 +9,6 @@ use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\HasApiFactoryInterface; use TrueLayer\Interfaces\HppInterface; use TrueLayer\Interfaces\Payment\AuthorizationFlow\AuthorizationFlowAuthorizingInterface; @@ -46,15 +45,6 @@ final class PaymentCreated extends Entity implements PaymentCreatedInterface, Ha 'user.id' => 'user_id', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'id' => 'required|string', - 'user.id' => 'required|string', - 'resource_token' => 'required|string', - ]; - /** * @return string */ @@ -80,7 +70,6 @@ public function getUserId(): string } /** - * @throws ValidationException * @throws InvalidArgumentException * * @return HppInterface @@ -95,11 +84,10 @@ public function hostedPaymentsPage(): HppInterface /** * @param string $returnUri * - * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException + * @throws InvalidArgumentException * * @return AuthorizationFlowAuthorizingInterface * @@ -117,7 +105,6 @@ public function startAuthorization(string $returnUri): AuthorizationFlowAuthoriz /** * @throws InvalidArgumentException - * @throws ValidationException * * @return StartAuthorizationFlowRequestInterface */ @@ -128,11 +115,10 @@ public function authorizationFlow(): StartAuthorizationFlowRequestInterface } /** - * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException + * @throws InvalidArgumentException * * @return PaymentRetrievedInterface */ diff --git a/src/Entities/Payment/PaymentMethod/BankTransferPaymentMethod.php b/src/Entities/Payment/PaymentMethod/BankTransferPaymentMethod.php index 02392165..4bdc7ceb 100644 --- a/src/Entities/Payment/PaymentMethod/BankTransferPaymentMethod.php +++ b/src/Entities/Payment/PaymentMethod/BankTransferPaymentMethod.php @@ -7,12 +7,10 @@ use TrueLayer\Constants\PaymentMethods; use TrueLayer\Entities\Entity; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\Beneficiary\BeneficiaryInterface; use TrueLayer\Interfaces\PaymentMethod\BankTransferPaymentMethodInterface; use TrueLayer\Interfaces\Provider\ProviderSelectionInterface; use TrueLayer\Interfaces\Provider\UserSelectedProviderSelectionInterface; -use TrueLayer\Validation\ValidType; class BankTransferPaymentMethod extends Entity implements BankTransferPaymentMethodInterface { @@ -48,17 +46,6 @@ class BankTransferPaymentMethod extends Entity implements BankTransferPaymentMet 'provider_selection', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'beneficiary' => ['required', ValidType::of(BeneficiaryInterface::class)], - 'provider_selection' => ['nullable', ValidType::of(ProviderSelectionInterface::class)], - ]; - } - /** * @param BeneficiaryInterface $beneficiary * @@ -93,7 +80,6 @@ public function providerSelection(ProviderSelectionInterface $providerSelection) /** * @throws InvalidArgumentException - * @throws ValidationException * * @return ProviderSelectionInterface */ diff --git a/src/Entities/Payment/PaymentMethod/PaymentMethodBuilder.php b/src/Entities/Payment/PaymentMethod/PaymentMethodBuilder.php index 8fd6934d..05e829de 100644 --- a/src/Entities/Payment/PaymentMethod/PaymentMethodBuilder.php +++ b/src/Entities/Payment/PaymentMethod/PaymentMethodBuilder.php @@ -6,7 +6,6 @@ use TrueLayer\Entities\EntityBuilder; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\PaymentMethod\BankTransferPaymentMethodInterface; use TrueLayer\Interfaces\PaymentMethod\PaymentMethodBuilderInterface; @@ -14,7 +13,6 @@ class PaymentMethodBuilder extends EntityBuilder implements PaymentMethodBuilder { /** * @throws InvalidArgumentException - * @throws ValidationException * * @return BankTransferPaymentMethodInterface */ diff --git a/src/Entities/Payment/PaymentRequest.php b/src/Entities/Payment/PaymentRequest.php index 1446690a..102ec2be 100644 --- a/src/Entities/Payment/PaymentRequest.php +++ b/src/Entities/Payment/PaymentRequest.php @@ -9,7 +9,6 @@ use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\HasApiFactoryInterface; use TrueLayer\Interfaces\Payment\PaymentCreatedInterface; use TrueLayer\Interfaces\Payment\PaymentRequestInterface; @@ -17,7 +16,6 @@ use TrueLayer\Interfaces\RequestOptionsInterface; use TrueLayer\Interfaces\UserInterface; use TrueLayer\Traits\ProvidesApiFactory; -use TrueLayer\Validation\ValidType; final class PaymentRequest extends Entity implements PaymentRequestInterface, HasApiFactoryInterface { @@ -72,20 +70,6 @@ final class PaymentRequest extends Entity implements PaymentRequestInterface, Ha 'user', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'amount_in_minor' => 'required|int|min:1', - 'currency' => ['required', 'string'], - 'metadata' => 'nullable|array', - 'payment_method' => ['required', ValidType::of(PaymentMethodInterface::class)], - 'user' => ['required', ValidType::of(UserInterface::class)], - ]; - } - /** * @param int $amount * @@ -159,18 +143,17 @@ public function requestOptions(RequestOptionsInterface $requestOptions): Payment } /** - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException - * @throws ValidationException * @throws SignerException + * @throws ApiRequestJsonSerializationException * * @return PaymentCreatedInterface */ public function create(): PaymentCreatedInterface { $data = $this->getApiFactory()->paymentsApi()->create( - $this->validate()->toArray(), + $this->toArray(), $this->requestOptions ); diff --git a/src/Entities/Payment/PaymentRetrieved.php b/src/Entities/Payment/PaymentRetrieved.php index 19bb75b5..6784463c 100644 --- a/src/Entities/Payment/PaymentRetrieved.php +++ b/src/Entities/Payment/PaymentRetrieved.php @@ -8,7 +8,6 @@ use TrueLayer\Entities\Entity; use TrueLayer\Interfaces\Payment\PaymentRetrievedInterface; use TrueLayer\Interfaces\PaymentMethod\PaymentMethodInterface; -use TrueLayer\Validation\ValidType; class PaymentRetrieved extends Entity implements PaymentRetrievedInterface { @@ -74,23 +73,6 @@ class PaymentRetrieved extends Entity implements PaymentRetrievedInterface 'payment_method', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'required|string', - 'status' => 'required|string', - 'created_at' => 'required|date', - 'amount_in_minor' => 'required|int|min:1', - 'currency' => 'required|string', - 'metadata' => 'nullable|array', - 'payment_method' => ['required', ValidType::of(PaymentMethodInterface::class)], - 'user.id' => 'required|string', - ]; - } - /** * @return string */ diff --git a/src/Entities/Payment/PaymentRetrieved/PaymentExecuted.php b/src/Entities/Payment/PaymentRetrieved/PaymentExecuted.php index b241707b..cd46a6c0 100644 --- a/src/Entities/Payment/PaymentRetrieved/PaymentExecuted.php +++ b/src/Entities/Payment/PaymentRetrieved/PaymentExecuted.php @@ -33,16 +33,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'executed_at' => 'required|date', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Payment/PaymentRetrieved/PaymentFailed.php b/src/Entities/Payment/PaymentRetrieved/PaymentFailed.php index 51729e45..b5358011 100644 --- a/src/Entities/Payment/PaymentRetrieved/PaymentFailed.php +++ b/src/Entities/Payment/PaymentRetrieved/PaymentFailed.php @@ -4,9 +4,7 @@ namespace TrueLayer\Entities\Payment\PaymentRetrieved; -use TrueLayer\Constants\PaymentStatus; use TrueLayer\Interfaces\Payment\PaymentFailedInterface; -use TrueLayer\Validation\AllowedConstant; final class PaymentFailed extends _PaymentWithAuthorizationConfig implements PaymentFailedInterface { @@ -47,18 +45,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'failed_at' => 'required|date', - 'failure_stage' => ['required', AllowedConstant::in(PaymentStatus::class)], - 'failure_reason' => 'nullable|string', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Payment/PaymentRetrieved/PaymentSettled.php b/src/Entities/Payment/PaymentRetrieved/PaymentSettled.php index 336a1403..88a18b77 100644 --- a/src/Entities/Payment/PaymentRetrieved/PaymentSettled.php +++ b/src/Entities/Payment/PaymentRetrieved/PaymentSettled.php @@ -8,14 +8,12 @@ use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\HasApiFactoryInterface; use TrueLayer\Interfaces\Payment\PaymentSettledInterface; use TrueLayer\Interfaces\Payment\PaymentSourceInterface; use TrueLayer\Interfaces\Payment\RefundRequestInterface; use TrueLayer\Interfaces\Payment\RefundRetrievedInterface; use TrueLayer\Traits\ProvidesApiFactory; -use TrueLayer\Validation\ValidType; final class PaymentSettled extends _PaymentWithAuthorizationConfig implements PaymentSettledInterface, HasApiFactoryInterface { @@ -48,18 +46,6 @@ protected function casts(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'payment_source' => [ValidType::of(PaymentSourceInterface::class)], - 'executed_at' => 'required|date', - 'settled_at' => 'required|date', - ]); - } - /** * @return mixed[] */ @@ -97,7 +83,6 @@ public function getSettledAt(): \DateTimeInterface } /** - * @throws ValidationException * @throws InvalidArgumentException * * @return RefundRequestInterface @@ -111,11 +96,10 @@ public function refund(): RefundRequestInterface /** * @param string $refundId * - * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException + * @throws ApiResponseUnsuccessfulException * * @return RefundRetrievedInterface */ @@ -127,11 +111,10 @@ public function getRefund(string $refundId): RefundRetrievedInterface } /** - * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException + * @throws ApiResponseUnsuccessfulException * * @return RefundRetrievedInterface[] */ diff --git a/src/Entities/Payment/PaymentRetrieved/PaymentSource.php b/src/Entities/Payment/PaymentRetrieved/PaymentSource.php index 4fb2de6c..e25c8617 100644 --- a/src/Entities/Payment/PaymentRetrieved/PaymentSource.php +++ b/src/Entities/Payment/PaymentRetrieved/PaymentSource.php @@ -7,7 +7,6 @@ use TrueLayer\Entities\Entity; use TrueLayer\Interfaces\AccountIdentifier\AccountIdentifierInterface; use TrueLayer\Interfaces\Payment\PaymentSourceInterface; -use TrueLayer\Validation\ValidType; final class PaymentSource extends Entity implements PaymentSourceInterface { @@ -42,19 +41,6 @@ final class PaymentSource extends Entity implements PaymentSourceInterface 'account_holder_name', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'nullable|string', - 'account_holder_name' => 'nullable|string', - 'account_identifiers' => 'nullable|array', - 'account_identifiers.*' => ValidType::of(AccountIdentifierInterface::class), - ]; - } - /** * @return string|null */ diff --git a/src/Entities/Payment/PaymentRetrieved/_PaymentWithAuthorizationConfig.php b/src/Entities/Payment/PaymentRetrieved/_PaymentWithAuthorizationConfig.php index 030fac60..9fa17280 100644 --- a/src/Entities/Payment/PaymentRetrieved/_PaymentWithAuthorizationConfig.php +++ b/src/Entities/Payment/PaymentRetrieved/_PaymentWithAuthorizationConfig.php @@ -7,7 +7,6 @@ use TrueLayer\Entities\Payment\PaymentRetrieved; use TrueLayer\Interfaces\Payment\AuthorizationFlow\AuthorizationFlowInterface; use TrueLayer\Interfaces\Payment\AuthorizationFlow\ConfigurationInterface; -use TrueLayer\Validation\ValidType; class _PaymentWithAuthorizationConfig extends PaymentRetrieved { @@ -36,16 +35,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'authorization_flow' => ['nullable', ValidType::of(AuthorizationFlowInterface::class)], - ]); - } - /** * @return AuthorizationFlowInterface|null */ diff --git a/src/Entities/Payment/Refund/RefundCreated.php b/src/Entities/Payment/Refund/RefundCreated.php index f7af5967..7b98fcda 100644 --- a/src/Entities/Payment/Refund/RefundCreated.php +++ b/src/Entities/Payment/Refund/RefundCreated.php @@ -21,16 +21,6 @@ final class RefundCreated extends Entity implements RefundCreatedInterface 'id', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'required|string', - ]; - } - /** * @return string */ diff --git a/src/Entities/Payment/Refund/RefundExecuted.php b/src/Entities/Payment/Refund/RefundExecuted.php index 640ead0a..c6e6aaaa 100644 --- a/src/Entities/Payment/Refund/RefundExecuted.php +++ b/src/Entities/Payment/Refund/RefundExecuted.php @@ -33,16 +33,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'executed_at' => 'required|date', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Payment/Refund/RefundFailed.php b/src/Entities/Payment/Refund/RefundFailed.php index a84c63e2..867ad9fc 100644 --- a/src/Entities/Payment/Refund/RefundFailed.php +++ b/src/Entities/Payment/Refund/RefundFailed.php @@ -39,17 +39,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'failed_at' => 'required|date', - 'failure_reason' => 'nullable|string', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Payment/Refund/RefundRequest.php b/src/Entities/Payment/Refund/RefundRequest.php index b9a5a703..0c551d73 100644 --- a/src/Entities/Payment/Refund/RefundRequest.php +++ b/src/Entities/Payment/Refund/RefundRequest.php @@ -9,7 +9,6 @@ use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\HasApiFactoryInterface; use TrueLayer\Interfaces\Payment\PaymentCreatedInterface; use TrueLayer\Interfaces\Payment\PaymentRetrievedInterface; @@ -52,18 +51,6 @@ final class RefundRequest extends Entity implements RefundRequestInterface, HasA 'reference', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'payment_id' => 'required|string', - 'amount_in_minor' => 'required|int|min:1', - 'reference' => 'required|string', - ]; - } - /** * @param string|PaymentRetrievedInterface|PaymentCreatedInterface $payment * @@ -115,11 +102,10 @@ public function requestOptions(RequestOptionsInterface $requestOptions): RefundR } /** - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException - * @throws ValidationException * @throws SignerException + * @throws ApiRequestJsonSerializationException * * @return RefundCreatedInterface */ @@ -127,7 +113,7 @@ public function create(): RefundCreatedInterface { $data = $this->getApiFactory()->paymentsApi()->createRefund( $this->paymentId, - $this->validate()->toArray(), + $this->toArray(), $this->requestOptions ); diff --git a/src/Entities/Payment/Refund/RefundRetrieved.php b/src/Entities/Payment/Refund/RefundRetrieved.php index d2a01b8a..b17883a0 100644 --- a/src/Entities/Payment/Refund/RefundRetrieved.php +++ b/src/Entities/Payment/Refund/RefundRetrieved.php @@ -59,21 +59,6 @@ class RefundRetrieved extends Entity implements RefundRetrievedInterface 'created_at', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'required|string', - 'amount_in_minor' => 'required|int|min:1', - 'currency' => 'required|string', - 'reference' => 'required|string', - 'status' => 'required|string', - 'created_at' => 'required|date', - ]; - } - /** * @return string */ diff --git a/src/Entities/Payout/BeneficiaryBuilder.php b/src/Entities/Payout/BeneficiaryBuilder.php index fe886991..a9c268b0 100644 --- a/src/Entities/Payout/BeneficiaryBuilder.php +++ b/src/Entities/Payout/BeneficiaryBuilder.php @@ -6,7 +6,6 @@ use TrueLayer\Entities\EntityBuilder; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\Beneficiary\ExternalAccountBeneficiaryInterface; use TrueLayer\Interfaces\Payout\BeneficiaryBuilderInterface; use TrueLayer\Interfaces\Payout\PaymentSourceBeneficiaryInterface; @@ -16,7 +15,6 @@ final class BeneficiaryBuilder extends EntityBuilder implements BeneficiaryBuild { /** * @throws InvalidArgumentException - * @throws ValidationException * * @return ExternalAccountBeneficiaryInterface */ @@ -26,7 +24,6 @@ public function externalAccount(): ExternalAccountBeneficiaryInterface } /** - * @throws ValidationException * @throws InvalidArgumentException * * @return PaymentSourceBeneficiaryInterface @@ -40,7 +37,6 @@ public function paymentSource(): PaymentSourceBeneficiaryInterface * @param mixed[] $data * * @throws InvalidArgumentException - * @throws ValidationException * * @return PayoutBeneficiaryInterface */ diff --git a/src/Entities/Payout/PaymentSourceBeneficiary.php b/src/Entities/Payout/PaymentSourceBeneficiary.php index a5cbdcd9..7dfae3ce 100644 --- a/src/Entities/Payout/PaymentSourceBeneficiary.php +++ b/src/Entities/Payout/PaymentSourceBeneficiary.php @@ -34,18 +34,6 @@ final class PaymentSourceBeneficiary extends Entity implements PaymentSourceBene 'type', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'payment_source_id' => 'required|string', - 'user_id' => 'nullable|string', - 'reference' => 'nullable|string', - ]; - } - /** * @return string|null */ diff --git a/src/Entities/Payout/PayoutCreated.php b/src/Entities/Payout/PayoutCreated.php index a620b560..e9b57308 100644 --- a/src/Entities/Payout/PayoutCreated.php +++ b/src/Entities/Payout/PayoutCreated.php @@ -21,16 +21,6 @@ final class PayoutCreated extends Entity implements PayoutCreatedInterface 'id', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'required|string', - ]; - } - /** * @return string */ diff --git a/src/Entities/Payout/PayoutRequest.php b/src/Entities/Payout/PayoutRequest.php index 5d86e10d..8c686cbb 100644 --- a/src/Entities/Payout/PayoutRequest.php +++ b/src/Entities/Payout/PayoutRequest.php @@ -9,7 +9,6 @@ use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\Beneficiary\BeneficiaryInterface; use TrueLayer\Interfaces\Beneficiary\ExternalAccountBeneficiaryInterface; use TrueLayer\Interfaces\HasApiFactoryInterface; @@ -18,7 +17,6 @@ use TrueLayer\Interfaces\Payout\PayoutRequestInterface; use TrueLayer\Interfaces\RequestOptionsInterface; use TrueLayer\Traits\ProvidesApiFactory; -use TrueLayer\Validation\ValidType; final class PayoutRequest extends Entity implements PayoutRequestInterface, HasApiFactoryInterface { @@ -66,19 +64,6 @@ final class PayoutRequest extends Entity implements PayoutRequestInterface, HasA 'beneficiary', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'merchant_account_id' => 'required|string', - 'amount_in_minor' => 'required|int|min:1', - 'currency' => 'required|string', - 'beneficiary' => ['required', ValidType::of(PayoutBeneficiaryInterface::class)], - ]; - } - /** * @param int $amount * @@ -140,18 +125,17 @@ public function requestOptions(RequestOptionsInterface $requestOptions): PayoutR } /** - * @throws SignerException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException - * @throws ValidationException + * @throws SignerException * * @return PayoutCreatedInterface */ public function create(): PayoutCreatedInterface { $data = $this->getApiFactory()->payoutsApi()->create( - $this->validate()->toArray(), + $this->toArray(), $this->requestOptions ); diff --git a/src/Entities/Payout/PayoutRetrieved.php b/src/Entities/Payout/PayoutRetrieved.php index 6503a6d7..f0480539 100644 --- a/src/Entities/Payout/PayoutRetrieved.php +++ b/src/Entities/Payout/PayoutRetrieved.php @@ -7,7 +7,6 @@ use TrueLayer\Entities\Entity; use TrueLayer\Interfaces\Payout\PayoutBeneficiaryInterface; use TrueLayer\Interfaces\Payout\PayoutRetrievedInterface; -use TrueLayer\Validation\ValidType; abstract class PayoutRetrieved extends Entity implements PayoutRetrievedInterface { @@ -67,22 +66,6 @@ abstract class PayoutRetrieved extends Entity implements PayoutRetrievedInterfac 'created_at', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'required|string', - 'merchant_account_id' => 'required|string', - 'amount_in_minor' => 'required|int|min:1', - 'currency' => 'required|string', - 'beneficiary' => ['required', ValidType::of(PayoutBeneficiaryInterface::class)], - 'status' => 'required|string', - 'created_at' => 'required|date', - ]; - } - /** * @return string */ diff --git a/src/Entities/Payout/PayoutRetrieved/PayoutExecuted.php b/src/Entities/Payout/PayoutRetrieved/PayoutExecuted.php index c612848c..d9c97d34 100644 --- a/src/Entities/Payout/PayoutRetrieved/PayoutExecuted.php +++ b/src/Entities/Payout/PayoutRetrieved/PayoutExecuted.php @@ -34,16 +34,6 @@ protected function casts(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'executed_at' => 'required|date', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Payout/PayoutRetrieved/PayoutFailed.php b/src/Entities/Payout/PayoutRetrieved/PayoutFailed.php index d1f1abc1..b5a533bd 100644 --- a/src/Entities/Payout/PayoutRetrieved/PayoutFailed.php +++ b/src/Entities/Payout/PayoutRetrieved/PayoutFailed.php @@ -40,17 +40,6 @@ protected function casts(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'failed_at' => 'required|date', - 'failure_reason' => 'nullable|string', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Provider/Provider.php b/src/Entities/Provider/Provider.php index 2316d631..9ad70a78 100644 --- a/src/Entities/Provider/Provider.php +++ b/src/Entities/Provider/Provider.php @@ -51,21 +51,6 @@ final class Provider extends Entity implements ProviderInterface 'country_code', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'string', - 'display_name' => 'string', - 'icon_uri' => 'url', - 'logo_uri' => 'url', - 'bg_color' => 'regex:/^#[a-fA-F0-9]{6}$/', - 'country_code' => 'string', - ]; - } - /** * @return string|null */ diff --git a/src/Entities/Provider/ProviderSelection/ProviderFilter.php b/src/Entities/Provider/ProviderSelection/ProviderFilter.php index 925155c4..877127d7 100644 --- a/src/Entities/Provider/ProviderSelection/ProviderFilter.php +++ b/src/Entities/Provider/ProviderSelection/ProviderFilter.php @@ -45,20 +45,6 @@ class ProviderFilter extends Entity implements ProviderFilterInterface 'excludes.provider_ids' => 'excludes_provider_ids', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'countries.*' => 'string', - 'release_channel' => 'string', - 'customer_segments.*' => 'string', - 'provider_ids.*' => 'string', - 'excludes.provider_ids.*' => 'string', - ]; - } - /** * @param string[] $countries * diff --git a/src/Entities/Provider/ProviderSelection/ProviderSelectionBuilder.php b/src/Entities/Provider/ProviderSelection/ProviderSelectionBuilder.php index 0b7e9af7..5faa17f0 100644 --- a/src/Entities/Provider/ProviderSelection/ProviderSelectionBuilder.php +++ b/src/Entities/Provider/ProviderSelection/ProviderSelectionBuilder.php @@ -6,7 +6,6 @@ use TrueLayer\Entities\EntityBuilder; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\Provider\ProviderSelectionBuilderInterface; use TrueLayer\Interfaces\Provider\UserSelectedProviderSelectionInterface; @@ -14,7 +13,6 @@ class ProviderSelectionBuilder extends EntityBuilder implements ProviderSelectio { /** * @throws InvalidArgumentException - * @throws ValidationException * * @return UserSelectedProviderSelectionInterface */ diff --git a/src/Entities/Provider/ProviderSelection/UserSelectedProviderSelection.php b/src/Entities/Provider/ProviderSelection/UserSelectedProviderSelection.php index db75c84a..5ec4fae6 100644 --- a/src/Entities/Provider/ProviderSelection/UserSelectedProviderSelection.php +++ b/src/Entities/Provider/ProviderSelection/UserSelectedProviderSelection.php @@ -8,7 +8,6 @@ use TrueLayer\Entities\Entity; use TrueLayer\Interfaces\Provider\ProviderFilterInterface; use TrueLayer\Interfaces\Provider\UserSelectedProviderSelectionInterface; -use TrueLayer\Validation\ValidType; final class UserSelectedProviderSelection extends Entity implements UserSelectedProviderSelectionInterface { @@ -32,16 +31,6 @@ final class UserSelectedProviderSelection extends Entity implements UserSelected 'filter', ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'filter' => ['nullable', ValidType::of(ProviderFilterInterface::class)], - ]; - } - /** * @return ProviderFilterInterface|null */ diff --git a/src/Entities/RequestOptions.php b/src/Entities/RequestOptions.php index 96688d46..fe790227 100644 --- a/src/Entities/RequestOptions.php +++ b/src/Entities/RequestOptions.php @@ -20,13 +20,6 @@ final class RequestOptions extends Entity implements RequestOptionsInterface 'idempotency_key', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'idempotency_key' => 'nullable|string', - ]; - /** * @param string $idempotencyKey * diff --git a/src/Entities/User.php b/src/Entities/User.php index 5f19b71c..c1550924 100644 --- a/src/Entities/User.php +++ b/src/Entities/User.php @@ -5,10 +5,8 @@ namespace TrueLayer\Entities; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\AddressInterface; use TrueLayer\Interfaces\UserInterface; -use TrueLayer\Validation\ValidType; final class User extends Entity implements UserInterface { @@ -61,21 +59,6 @@ final class User extends Entity implements UserInterface 'address' => AddressInterface::class, ]; - /** - * @return mixed[] - */ - protected function rules(): array - { - return [ - 'id' => 'string|nullable', - 'name' => 'string|nullable|required_without:id', - 'email' => 'string|nullable|email|required_without_all:phone,id', - 'phone' => 'string|nullable|required_without_all:email,id', - 'address' => ['nullable', ValidType::of(AddressInterface::class)], - 'date_of_birth' => 'string|nullable|date', - ]; - } - /** * @return string|null */ @@ -167,7 +150,6 @@ public function getAddress(): ?AddressInterface /** * @param AddressInterface|null $address * - * @throws ValidationException * @throws InvalidArgumentException * * @return AddressInterface diff --git a/src/Entities/Webhook/Beneficiary/Beneficiary.php b/src/Entities/Webhook/Beneficiary/Beneficiary.php index 34a185e7..391028c5 100644 --- a/src/Entities/Webhook/Beneficiary/Beneficiary.php +++ b/src/Entities/Webhook/Beneficiary/Beneficiary.php @@ -21,13 +21,6 @@ class Beneficiary extends Entity implements BeneficiaryInterface 'type', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'type' => 'required|string', - ]; - /** * @return string */ diff --git a/src/Entities/Webhook/Beneficiary/PaymentSourceBeneficiary.php b/src/Entities/Webhook/Beneficiary/PaymentSourceBeneficiary.php index 04bd4073..b6a7d830 100644 --- a/src/Entities/Webhook/Beneficiary/PaymentSourceBeneficiary.php +++ b/src/Entities/Webhook/Beneficiary/PaymentSourceBeneficiary.php @@ -29,14 +29,6 @@ protected function arrayFields(): array ]); } - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'payment_source_id' => 'required|string', - 'user_id' => 'required|string', - ]); - } - /** * @return string */ diff --git a/src/Entities/Webhook/Event.php b/src/Entities/Webhook/Event.php index ffa7fc2e..2292782b 100644 --- a/src/Entities/Webhook/Event.php +++ b/src/Entities/Webhook/Event.php @@ -53,18 +53,6 @@ class Event extends Entity implements EventInterface 'event_version', ]; - /** - * @var string[] - */ - protected array $rules = [ - 'timestamp' => 'required|date', - 'signature' => 'required|string', - 'type' => 'required|string', - 'event_id' => 'required|string', - 'event_version' => 'required|int', - 'body' => 'required|string', - ]; - /** * @var string[] */ diff --git a/src/Entities/Webhook/PaymentEvent.php b/src/Entities/Webhook/PaymentEvent.php index df0eb6af..3d714ee5 100644 --- a/src/Entities/Webhook/PaymentEvent.php +++ b/src/Entities/Webhook/PaymentEvent.php @@ -6,7 +6,6 @@ use TrueLayer\Interfaces\Webhook\PaymentEventInterface; use TrueLayer\Interfaces\Webhook\PaymentMethod\PaymentMethodInterface; -use TrueLayer\Validation\ValidType; class PaymentEvent extends Event implements PaymentEventInterface { @@ -41,17 +40,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'payment_id' => 'required|string', - 'payment_method' => [ValidType::of(PaymentMethodInterface::class)], - ]); - } - /** * @return string */ diff --git a/src/Entities/Webhook/PaymentExecutedEvent.php b/src/Entities/Webhook/PaymentExecutedEvent.php index 6d37767a..b27cc689 100644 --- a/src/Entities/Webhook/PaymentExecutedEvent.php +++ b/src/Entities/Webhook/PaymentExecutedEvent.php @@ -39,18 +39,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'executed_at' => 'required|date', - 'settlement_risk' => 'nullable|array', - 'settlement_risk.category' => 'nullable|string', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Webhook/PaymentFailedEvent.php b/src/Entities/Webhook/PaymentFailedEvent.php index 91695809..8a583d31 100644 --- a/src/Entities/Webhook/PaymentFailedEvent.php +++ b/src/Entities/Webhook/PaymentFailedEvent.php @@ -45,18 +45,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'failed_at' => 'required|date', - 'failure_stage' => 'required|string', - 'failure_reason' => 'nullable|string', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Webhook/PaymentMethod/BankTransferPaymentMethod.php b/src/Entities/Webhook/PaymentMethod/BankTransferPaymentMethod.php index e3f5c6db..c43d8b01 100644 --- a/src/Entities/Webhook/PaymentMethod/BankTransferPaymentMethod.php +++ b/src/Entities/Webhook/PaymentMethod/BankTransferPaymentMethod.php @@ -33,12 +33,6 @@ class BankTransferPaymentMethod extends Entity implements BankTransferPaymentMet 'scheme_id', ]; - protected array $rules = [ - 'type' => 'required|string', - 'provider_id' => 'required|string', - 'scheme_id' => 'required|string', - ]; - /** * @return string */ diff --git a/src/Entities/Webhook/PaymentMethod/MandatePaymentMethod.php b/src/Entities/Webhook/PaymentMethod/MandatePaymentMethod.php index c8f29d3f..25029af6 100644 --- a/src/Entities/Webhook/PaymentMethod/MandatePaymentMethod.php +++ b/src/Entities/Webhook/PaymentMethod/MandatePaymentMethod.php @@ -27,11 +27,6 @@ class MandatePaymentMethod extends Entity implements MandatePaymentMethodInterfa 'mandate_id', ]; - protected array $rules = [ - 'type' => 'required|string', - 'mandate_id' => 'required|string', - ]; - /** * @return string */ diff --git a/src/Entities/Webhook/PaymentSettledEvent.php b/src/Entities/Webhook/PaymentSettledEvent.php index abcd7e1b..89dbe17d 100644 --- a/src/Entities/Webhook/PaymentSettledEvent.php +++ b/src/Entities/Webhook/PaymentSettledEvent.php @@ -6,7 +6,6 @@ use TrueLayer\Interfaces\Payment\PaymentSourceInterface; use TrueLayer\Interfaces\Webhook\PaymentSettledEventInterface; -use TrueLayer\Validation\ValidType; class PaymentSettledEvent extends PaymentEvent implements PaymentSettledEventInterface { @@ -36,18 +35,6 @@ protected function casts(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'settled_at' => 'required|date', - 'settlement_risk.category' => 'nullable|string', - 'payment_source' => [ValidType::of(PaymentSourceInterface::class)], - ]); - } - /** * @return mixed[] */ diff --git a/src/Entities/Webhook/PayoutEvent.php b/src/Entities/Webhook/PayoutEvent.php index 940f5b13..51ef4e46 100644 --- a/src/Entities/Webhook/PayoutEvent.php +++ b/src/Entities/Webhook/PayoutEvent.php @@ -6,7 +6,6 @@ use TrueLayer\Interfaces\Webhook\Beneficiary\BeneficiaryInterface; use TrueLayer\Interfaces\Webhook\PayoutEventInterface; -use TrueLayer\Validation\ValidType; class PayoutEvent extends Event implements PayoutEventInterface { @@ -38,17 +37,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'payout_id' => 'required|string', - 'beneficiary' => [ValidType::of(BeneficiaryInterface::class)], - ]); - } - /** * @return string */ diff --git a/src/Entities/Webhook/PayoutExecutedEvent.php b/src/Entities/Webhook/PayoutExecutedEvent.php index 2fb2e7ca..e41c1698 100644 --- a/src/Entities/Webhook/PayoutExecutedEvent.php +++ b/src/Entities/Webhook/PayoutExecutedEvent.php @@ -33,16 +33,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'executed_at' => 'required|date', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Webhook/PayoutFailedEvent.php b/src/Entities/Webhook/PayoutFailedEvent.php index 89cdf6d0..369d0a93 100644 --- a/src/Entities/Webhook/PayoutFailedEvent.php +++ b/src/Entities/Webhook/PayoutFailedEvent.php @@ -39,17 +39,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'failed_at' => 'required|date', - 'failure_reason' => 'nullable|string', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Webhook/RefundEvent.php b/src/Entities/Webhook/RefundEvent.php index ee814d10..82e5cdfc 100644 --- a/src/Entities/Webhook/RefundEvent.php +++ b/src/Entities/Webhook/RefundEvent.php @@ -29,17 +29,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'payment_id' => 'required|string', - 'refund_id' => 'required|string', - ]); - } - /** * @return string */ diff --git a/src/Entities/Webhook/RefundExecutedEvent.php b/src/Entities/Webhook/RefundExecutedEvent.php index c9d88f19..088de7ac 100644 --- a/src/Entities/Webhook/RefundExecutedEvent.php +++ b/src/Entities/Webhook/RefundExecutedEvent.php @@ -33,16 +33,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'executed_at' => 'required|date', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Entities/Webhook/RefundFailedEvent.php b/src/Entities/Webhook/RefundFailedEvent.php index 9e51d3d1..40feaf64 100644 --- a/src/Entities/Webhook/RefundFailedEvent.php +++ b/src/Entities/Webhook/RefundFailedEvent.php @@ -39,17 +39,6 @@ protected function arrayFields(): array ]); } - /** - * @return mixed[] - */ - protected function rules(): array - { - return \array_merge(parent::rules(), [ - 'failed_at' => 'required|date', - 'failure_reason' => 'nullable|string', - ]); - } - /** * @return \DateTimeInterface */ diff --git a/src/Exceptions/ValidationException.php b/src/Exceptions/ValidationException.php deleted file mode 100644 index f3ad8758..00000000 --- a/src/Exceptions/ValidationException.php +++ /dev/null @@ -1,32 +0,0 @@ -validator = $validator; - } - - /** - * @return mixed[] - */ - public function getErrors(): array - { - return $this->validator->errors()->messages(); - } -} diff --git a/src/Factories/ClientFactory.php b/src/Factories/ClientFactory.php index 078737fe..3a518282 100644 --- a/src/Factories/ClientFactory.php +++ b/src/Factories/ClientFactory.php @@ -4,7 +4,6 @@ namespace TrueLayer\Factories; -use Illuminate\Contracts\Validation\Factory as ValidatorFactory; use TrueLayer\Constants\Endpoints; use TrueLayer\Exceptions\MissingHttpImplementationException; use TrueLayer\Exceptions\SignerException; @@ -20,16 +19,10 @@ use TrueLayer\Services\Client\ClientConfig; use TrueLayer\Signing\Signer; use TrueLayer\Traits\HttpClient; -use TrueLayer\Traits\MakeValidatorFactory; final class ClientFactory implements ClientFactoryInterface { - use MakeValidatorFactory, HttpClient; - - /** - * @var ValidatorFactory - */ - private ValidatorFactory $validatorFactory; + use HttpClient; /** * @var AccessTokenInterface @@ -44,19 +37,18 @@ final class ClientFactory implements ClientFactoryInterface /** * @param ClientConfigInterface $config * - * @throws SignerException * @throws MissingHttpImplementationException + * @throws SignerException * * @return ClientInterface */ public function make(ClientConfigInterface $config): ClientInterface { - $this->validatorFactory = $this->makeValidatorFactory(); $this->makeAuthToken($config); $this->makeApiClient($config); $apiFactory = new ApiFactory($this->apiClient); - $entityFactory = new EntityFactory($this->validatorFactory, $config, $apiFactory); + $entityFactory = new EntityFactory($config, $apiFactory); return new Client( $this->apiClient, @@ -92,7 +84,6 @@ private function makeAuthToken(ClientConfigInterface $config): void $this->authToken = new AccessToken( $authClient, $config->getCache(), - $this->validatorFactory, $config->getClientId(), $config->getClientSecret(), $config->getScopes(), @@ -101,7 +92,7 @@ private function makeAuthToken(ClientConfigInterface $config): void /** * Build the API client - * Handles API calls, including signing, validation & error handling. + * Handles API calls, including signing & error handling. * * @param ClientConfigInterface $config * diff --git a/src/Factories/EntityFactory.php b/src/Factories/EntityFactory.php index 495c92de..62a40fbc 100644 --- a/src/Factories/EntityFactory.php +++ b/src/Factories/EntityFactory.php @@ -4,22 +4,15 @@ namespace TrueLayer\Factories; -use Illuminate\Contracts\Validation\Factory as ValidatorFactory; -use Illuminate\Support\Arr; use TrueLayer\Constants\Endpoints; use TrueLayer\Entities; use TrueLayer\Entities\Hpp; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces; +use TrueLayer\Services\Util\Arr; final class EntityFactory implements Interfaces\Factories\EntityFactoryInterface { - /** - * @var ValidatorFactory - */ - private ValidatorFactory $validatorFactory; - /** * @var Interfaces\Factories\ApiFactoryInterface|null */ @@ -41,16 +34,13 @@ final class EntityFactory implements Interfaces\Factories\EntityFactoryInterface private array $discriminations; /** - * @param ValidatorFactory $validatorFactory * @param Interfaces\Configuration\ConfigInterface $sdkConfig * @param Interfaces\Factories\ApiFactoryInterface|null $apiFactory */ public function __construct( - ValidatorFactory $validatorFactory, Interfaces\Configuration\ConfigInterface $sdkConfig, Interfaces\Factories\ApiFactoryInterface $apiFactory = null ) { - $this->validatorFactory = $validatorFactory; $this->sdkConfig = $sdkConfig; $this->apiFactory = $apiFactory; @@ -66,7 +56,6 @@ public function __construct( * @param mixed[]|null $data * * @throws InvalidArgumentException - * @throws ValidationException * * @return T * @return T implements @@ -104,7 +93,6 @@ public function make(string $abstract, array $data = null) * @param class-string $abstract * @param mixed[] $data * - * @throws ValidationException * @throws InvalidArgumentException * * @return T[] @@ -149,9 +137,7 @@ public function makeConcrete(string $concrete) // is_subclass_of so we need to rely on the instanceof operator. $instance = null; - if (\is_subclass_of($concrete, Entities\Entity::class)) { - $instance = new $concrete($this->validatorFactory, $this); - } elseif (\is_subclass_of($concrete, Entities\EntityBuilder::class)) { + if (\is_subclass_of($concrete, Entities\Entity::class) || \is_subclass_of($concrete, Entities\EntityBuilder::class)) { $instance = new $concrete($this); } diff --git a/src/Factories/WebhookFactory.php b/src/Factories/WebhookFactory.php index 3149567e..11afad9b 100644 --- a/src/Factories/WebhookFactory.php +++ b/src/Factories/WebhookFactory.php @@ -4,7 +4,6 @@ namespace TrueLayer\Factories; -use Illuminate\Contracts\Validation\Factory as ValidatorFactory; use TrueLayer\Constants\Endpoints; use TrueLayer\Exceptions\MissingHttpImplementationException; use TrueLayer\Interfaces\Configuration\ConfigInterface; @@ -20,11 +19,10 @@ use TrueLayer\Services\Webhooks\WebhookHandlerManager; use TrueLayer\Services\Webhooks\WebhookVerifier; use TrueLayer\Traits\HttpClient; -use TrueLayer\Traits\MakeValidatorFactory; class WebhookFactory implements WebhookVerifierFactoryInterface { - use MakeValidatorFactory, HttpClient; + use HttpClient; /** * @param ConfigInterface $config @@ -35,10 +33,9 @@ class WebhookFactory implements WebhookVerifierFactoryInterface */ public function make(ConfigInterface $config): WebhookInterface { - $validatorFactory = $this->makeValidatorFactory(); - $entityFactory = new EntityFactory($validatorFactory, $config); + $entityFactory = new EntityFactory($config); - $jwksManager = $this->makeJwks($config, $validatorFactory); + $jwksManager = $this->makeJwks($config); $verifier = new WebhookVerifier($jwksManager); $handlerManager = new WebhookHandlerManager(); @@ -47,14 +44,13 @@ public function make(ConfigInterface $config): WebhookInterface } /** - * @param ConfigInterface $config - * @param ValidatorFactory $validatorFactory + * @param ConfigInterface $config * * @throws MissingHttpImplementationException * * @return JwksManagerInterface */ - private function makeJwks(ConfigInterface $config, ValidatorFactory $validatorFactory): JwksManagerInterface + private function makeJwks(ConfigInterface $config): JwksManagerInterface { $webhooksBaseUri = $config->shouldUseProduction() ? Endpoints::WEBHOOKS_PROD_URL @@ -68,7 +64,7 @@ private function makeJwks(ConfigInterface $config, ValidatorFactory $validatorFa $jwksClient = new Decorators\ExponentialBackoffDecorator($jwksClient); - return new JwksManager($jwksClient, $config->getCache(), $validatorFactory); + return new JwksManager($jwksClient, $config->getCache()); } /** diff --git a/src/Interfaces/ArrayableInterface.php b/src/Interfaces/ArrayableInterface.php index d5583eb7..fe331fe2 100644 --- a/src/Interfaces/ArrayableInterface.php +++ b/src/Interfaces/ArrayableInterface.php @@ -4,11 +4,12 @@ namespace TrueLayer\Interfaces; -use Illuminate\Contracts\Support\Arrayable; - -/** - * @extends Arrayable - */ -interface ArrayableInterface extends Arrayable +interface ArrayableInterface { + /** + * Get the instance as an array. + * + * @return mixed[] + */ + public function toArray(): array; } diff --git a/src/Interfaces/Beneficiary/BeneficiaryBuilderInterface.php b/src/Interfaces/Beneficiary/BeneficiaryBuilderInterface.php index e3488e4e..08173d7e 100644 --- a/src/Interfaces/Beneficiary/BeneficiaryBuilderInterface.php +++ b/src/Interfaces/Beneficiary/BeneficiaryBuilderInterface.php @@ -5,7 +5,6 @@ namespace TrueLayer\Interfaces\Beneficiary; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\MerchantAccount\MerchantAccountInterface; interface BeneficiaryBuilderInterface @@ -28,7 +27,6 @@ public function merchantAccount(MerchantAccountInterface $merchantAccount = null * @param mixed[] $data * * @throws InvalidArgumentException - * @throws ValidationException * * @return BeneficiaryInterface */ diff --git a/src/Interfaces/Client/ClientInterface.php b/src/Interfaces/Client/ClientInterface.php index c77d8d87..58d1c108 100644 --- a/src/Interfaces/Client/ClientInterface.php +++ b/src/Interfaces/Client/ClientInterface.php @@ -9,7 +9,6 @@ use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Exceptions\MissingHttpImplementationException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\AccountIdentifier\AccountIdentifierBuilderInterface; use TrueLayer\Interfaces\ApiClient\ApiClientInterface; use TrueLayer\Interfaces\Beneficiary\BeneficiaryBuilderInterface; @@ -77,10 +76,9 @@ public function payment(): PaymentRequestInterface; /** * @param string $id * - * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException + * @throws SignerException * * @return PaymentRetrievedInterface */ @@ -90,11 +88,10 @@ public function getPayment(string $id): PaymentRetrievedInterface; * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * @param string $returnUri * - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException + * @throws ApiRequestJsonSerializationException * * @return AuthorizationFlowAuthorizingInterface * @@ -106,7 +103,6 @@ public function startPaymentAuthorization($payment, string $returnUri): Authoriz * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * * @throws InvalidArgumentException - * @throws ValidationException * * @return StartAuthorizationFlowRequestInterface */ @@ -116,18 +112,16 @@ public function paymentAuthorizationFlow($payment): StartAuthorizationFlowReques * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * @param string|ProviderInterface $provider * - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException + * @throws ApiRequestJsonSerializationException * * @return AuthorizationFlowResponseInterface */ public function submitPaymentProvider($payment, $provider): AuthorizationFlowResponseInterface; /** - * @throws ValidationException * @throws InvalidArgumentException * * @return RefundRequestInterface @@ -138,11 +132,10 @@ public function refund(): RefundRequestInterface; * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * @param string $refundId * - * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException + * @throws SignerException * * @return RefundRetrievedInterface */ @@ -151,11 +144,10 @@ public function getRefund($payment, string $refundId): RefundRetrievedInterface; /** * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * - * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException + * @throws SignerException * * @return mixed[] */ @@ -179,11 +171,10 @@ public function payoutBeneficiary(): Payout\BeneficiaryBuilderInterface; public function getPayout(string $id): Payout\PayoutRetrievedInterface; /** - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException + * @throws ApiRequestJsonSerializationException * * @return MerchantAccountInterface[] */ @@ -192,11 +183,10 @@ public function getMerchantAccounts(): array; /** * @param string $id * - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException + * @throws ApiRequestJsonSerializationException * * @return MerchantAccountInterface */ @@ -216,7 +206,6 @@ public function hostedPaymentsPage(): HppInterface; /** * @throws InvalidArgumentException - * @throws ValidationException * * @return RequestOptionsInterface */ diff --git a/src/Interfaces/Factories/EntityFactoryInterface.php b/src/Interfaces/Factories/EntityFactoryInterface.php index 7f28bfc9..995980fe 100644 --- a/src/Interfaces/Factories/EntityFactoryInterface.php +++ b/src/Interfaces/Factories/EntityFactoryInterface.php @@ -5,7 +5,6 @@ namespace TrueLayer\Interfaces\Factories; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; interface EntityFactoryInterface { @@ -15,7 +14,6 @@ interface EntityFactoryInterface * @param class-string $abstract * @param mixed[]|null $data * - * @throws ValidationException * @throws InvalidArgumentException * * @return T @@ -39,7 +37,6 @@ public function makeConcrete(string $concrete); * @param class-string $abstract * @param mixed[] $data * - * @throws ValidationException * @throws InvalidArgumentException * * @return T[] diff --git a/src/Interfaces/HasAttributesInterface.php b/src/Interfaces/HasAttributesInterface.php index 5ee686af..0f48efaa 100644 --- a/src/Interfaces/HasAttributesInterface.php +++ b/src/Interfaces/HasAttributesInterface.php @@ -5,7 +5,6 @@ namespace TrueLayer\Interfaces; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; interface HasAttributesInterface extends ArrayableInterface { @@ -13,7 +12,6 @@ interface HasAttributesInterface extends ArrayableInterface * @param mixed[] $data * * @throws InvalidArgumentException - * @throws ValidationException * * @return $this */ diff --git a/src/Interfaces/HasValidationInterface.php b/src/Interfaces/HasValidationInterface.php deleted file mode 100644 index f5a59413..00000000 --- a/src/Interfaces/HasValidationInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -|null $scopes */ public function __construct(ApiClientInterface $api, ?EncryptedCacheInterface $cache, - ValidatorFactory $validatorFactory, string $clientId, string $clientSecret, ?array $scopes = []) { $this->api = $api; $this->cache = $cache; - $this->validatorFactory = $validatorFactory; $this->clientId = $clientId; $this->clientSecret = $clientSecret; $this->scopes = $scopes ?? []; @@ -89,7 +79,6 @@ public function __construct(ApiClientInterface $api, /** * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException - * @throws ValidationException * * @return string|null */ @@ -161,13 +150,11 @@ public function clear(): AccessTokenInterface * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws SignerException - * @throws ValidationException */ private function retrieve(): void { /** @var array{access_token: string, expires_in: int} $data */ $data = (new AccessTokenApi($this->api))->retrieve($this->clientId, $this->clientSecret, $this->scopes); - $this->validate($data); $this->accessToken = $data['access_token']; $this->expiresIn = $data['expires_in']; @@ -178,25 +165,6 @@ private function retrieve(): void } } - /** - * @param mixed[] $data - * - * @throws ValidationException - */ - private function validate(array $data): void - { - $validator = $this->validatorFactory->make($data, [ - 'access_token' => 'required|string', - 'expires_in' => 'required|int', - ]); - - try { - $validator->validate(); - } catch (\Illuminate\Validation\ValidationException $e) { - throw new ValidationException($validator); - } - } - /** * @return mixed[] */ diff --git a/src/Services/Client/Client.php b/src/Services/Client/Client.php index 15ca5f96..75f88723 100644 --- a/src/Services/Client/Client.php +++ b/src/Services/Client/Client.php @@ -9,7 +9,6 @@ use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Factories\WebhookFactory; use TrueLayer\Interfaces\AccountIdentifier\AccountIdentifierBuilderInterface; use TrueLayer\Interfaces\ApiClient\ApiClientInterface; @@ -89,7 +88,6 @@ public function getApiClient(): ApiClientInterface /** * @throws Exceptions\InvalidArgumentException - * @throws Exceptions\ValidationException * @throws Exceptions\InvalidArgumentException * * @return UserInterface @@ -101,7 +99,6 @@ public function user(): UserInterface /** * @throws Exceptions\InvalidArgumentException - * @throws Exceptions\ValidationException * @throws Exceptions\InvalidArgumentException * * @return AccountIdentifierBuilderInterface @@ -113,7 +110,6 @@ public function accountIdentifier(): AccountIdentifierBuilderInterface /** * @throws Exceptions\InvalidArgumentException - * @throws Exceptions\ValidationException * @throws Exceptions\InvalidArgumentException * * @return BeneficiaryBuilderInterface @@ -125,7 +121,6 @@ public function beneficiary(): BeneficiaryBuilderInterface /** * @throws Exceptions\InvalidArgumentException - * @throws Exceptions\ValidationException * @throws Exceptions\InvalidArgumentException * * @return ProviderFilterInterface @@ -137,7 +132,6 @@ public function providerFilter(): ProviderFilterInterface /** * @throws Exceptions\InvalidArgumentException - * @throws Exceptions\ValidationException * @throws Exceptions\InvalidArgumentException * * @return ProviderSelectionBuilderInterface @@ -149,7 +143,6 @@ public function providerSelection(): ProviderSelectionBuilderInterface /** * @throws Exceptions\InvalidArgumentException - * @throws Exceptions\ValidationException * @throws Exceptions\InvalidArgumentException * * @return PaymentMethodBuilderInterface @@ -161,7 +154,6 @@ public function paymentMethod(): PaymentMethodBuilderInterface /** * @throws Exceptions\InvalidArgumentException - * @throws Exceptions\ValidationException * @throws Exceptions\InvalidArgumentException * * @return PaymentRequestInterface @@ -174,12 +166,11 @@ public function payment(): PaymentRequestInterface /** * @param string $id * - * @throws Exceptions\ApiRequestJsonSerializationException * @throws Exceptions\ApiResponseUnsuccessfulException * @throws Exceptions\InvalidArgumentException * @throws Exceptions\InvalidArgumentException * @throws Exceptions\SignerException - * @throws Exceptions\ValidationException + * @throws Exceptions\ApiRequestJsonSerializationException * * @return PaymentRetrievedInterface */ @@ -199,7 +190,6 @@ public function getPayment(string $id): PaymentRetrievedInterface * @throws InvalidArgumentException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException * * @return AuthorizationFlowAuthorizingInterface * @@ -220,7 +210,6 @@ public function startPaymentAuthorization($payment, string $returnUri): Authoriz * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * * @throws InvalidArgumentException - * @throws ValidationException * * @return StartAuthorizationFlowRequestInterface */ @@ -234,12 +223,11 @@ public function paymentAuthorizationFlow($payment): StartAuthorizationFlowReques * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * @param string|ProviderInterface $provider * - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException * @throws InvalidArgumentException * @throws SignerException - * @throws ValidationException + * @throws ApiRequestJsonSerializationException * * @return AuthorizationFlowResponseInterface */ @@ -261,7 +249,6 @@ public function submitPaymentProvider($payment, $provider): AuthorizationFlowRes } /** - * @throws ValidationException * @throws InvalidArgumentException * * @return RefundRequestInterface @@ -275,11 +262,10 @@ public function refund(): RefundRequestInterface * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * @param string $refundId * - * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException + * @throws SignerException * * @return RefundRetrievedInterface */ @@ -295,11 +281,10 @@ public function getRefund($payment, string $refundId): RefundRetrievedInterface /** * @param string|PaymentCreatedInterface|PaymentRetrievedInterface $payment * - * @throws SignerException - * @throws ValidationException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws InvalidArgumentException + * @throws SignerException * * @return mixed[] */ @@ -313,7 +298,6 @@ public function getRefunds($payment): array } /** - * @throws Exceptions\ValidationException * @throws Exceptions\InvalidArgumentException * @throws Exceptions\InvalidArgumentException */ @@ -323,9 +307,7 @@ public function hostedPaymentsPage(): HppInterface } /** - * @throws ValidationException * @throws InvalidArgumentException - * @throws ValidationException * * @return Payout\PayoutRequestInterface */ @@ -335,9 +317,7 @@ public function payout(): Payout\PayoutRequestInterface } /** - * @throws ValidationException * @throws InvalidArgumentException - * @throws ValidationException * * @return Payout\BeneficiaryBuilderInterface */ @@ -354,12 +334,11 @@ public function getPayout(string $id): PayoutRetrievedInterface } /** - * @throws Exceptions\ApiRequestJsonSerializationException * @throws Exceptions\ApiResponseUnsuccessfulException * @throws Exceptions\InvalidArgumentException * @throws Exceptions\InvalidArgumentException * @throws Exceptions\SignerException - * @throws Exceptions\ValidationException + * @throws Exceptions\ApiRequestJsonSerializationException * * @return MerchantAccountInterface[] */ @@ -373,12 +352,11 @@ public function getMerchantAccounts(): array /** * @param string $id * - * @throws Exceptions\ApiRequestJsonSerializationException * @throws Exceptions\ApiResponseUnsuccessfulException * @throws Exceptions\InvalidArgumentException * @throws Exceptions\InvalidArgumentException * @throws Exceptions\SignerException - * @throws Exceptions\ValidationException + * @throws Exceptions\ApiRequestJsonSerializationException * * @return MerchantAccountInterface */ @@ -401,7 +379,6 @@ public function webhook(): WebhookInterface /** * @throws InvalidArgumentException - * @throws ValidationException * * @return RequestOptionsInterface */ diff --git a/src/Services/Configuration/Config.php b/src/Services/Configuration/Config.php index 3eaef168..ee23301c 100644 --- a/src/Services/Configuration/Config.php +++ b/src/Services/Configuration/Config.php @@ -4,7 +4,6 @@ namespace TrueLayer\Services\Configuration; -use Illuminate\Encryption\Encrypter; use Psr\Http\Client\ClientInterface as HttpClientInterface; use Psr\Http\Message\RequestFactoryInterface; use Psr\SimpleCache\CacheInterface; @@ -13,6 +12,7 @@ use TrueLayer\Interfaces\Configuration\ConfigInterface; use TrueLayer\Interfaces\EncryptedCacheInterface; use TrueLayer\Services\Util\EncryptedCache; +use TrueLayer\Services\Util\Encryption\Encrypter; abstract class Config implements ConfigInterface { diff --git a/src/Services/Util/Arr.php b/src/Services/Util/Arr.php new file mode 100644 index 00000000..04bbf0a6 --- /dev/null +++ b/src/Services/Util/Arr.php @@ -0,0 +1,194 @@ +|mixed[] $array + * @param string|int|float $key + * + * @return bool + */ + public static function exists($array, $key) + { + if ($array instanceof \ArrayAccess) { + return $array->offsetExists($key); + } + + if (\is_float($key)) { + $key = (string)$key; + } + + return \array_key_exists($key, $array); + } + + /** + * Return the first element in an array passing a given truth test. + * + * @param mixed[] $array + * @param callable|null $callback + * @param mixed $default + * @return mixed + */ + public static function first($array, callable $callback = null, $default = null) + { + if (is_null($callback)) { + if (empty($array)) { + return $default; + } + + foreach ($array as $item) { + return $item; + } + } + + foreach ($array as $key => $value) { + if ($callback($value, $key)) { + return $value; + } + } + + return $default; + } + + /** + * Flatten a multi-dimensional array into a single level. + * + * @param iterable $array + * @param int $depth + * + * @return array + */ + public static function flatten($array, $depth = INF) // @phpstan-ignore-line + { + $result = []; + + foreach ($array as $item) { + if (!\is_array($item)) { + $result[] = $item; + } else { + $values = $depth === 1 + ? \array_values($item) + : static::flatten($item, $depth - 1); + + foreach ($values as $value) { + $result[] = $value; + } + } + } + + return $result; + } + + /** + * Get an item from an array using "dot" notation. + * + * @param \ArrayAccess|mixed[] $array + * @param string|int|null $key + * @param mixed $default + * + * @return mixed + */ + public static function get($array, $key, $default = null) + { + if (!static::accessible($array)) { + return $default; + } + + if (\is_null($key)) { + return $array; + } + + if (static::exists($array, $key)) { + return $array[$key]; + } + + if (!\str_contains((string)$key, '.')) { + return $array[$key] ?? $default; + } + + foreach (\explode('.', (string)$key) as $segment) { + if (static::accessible($array) && static::exists($array, $segment)) { + $array = $array[$segment]; + } else { + return $default; + } + } + + return $array; + } + + /** + * Determines if an array is associative. + * + * An array is "associative" if it doesn't have sequential numerical keys beginning with zero. + * + * @param mixed[] $array + * + * @return bool + */ + public static function isAssoc($array) + { + $keys = \array_keys($array); + + return \array_keys($keys) !== $keys; + } + + /** + * Set an array item to a given value using "dot" notation. + * + * If no key is given to the method, the entire array will be replaced. + * + * @param mixed[] $array + * @param string|int|null $key + * @param mixed $value + * + * @return mixed[]|mixed + */ + public static function set(&$array, $key, $value) + { + if (\is_null($key)) { + return $array = $value; + } + + $keys = \explode('.', (string)$key); + + foreach ($keys as $i => $key) { + if (\count($keys) === 1) { + break; + } + + unset($keys[$i]); + + // If the key doesn't exist at this depth, we will just create an empty array + // to hold the next value, allowing us to create the arrays to hold final + // values at the correct depth. Then we'll keep digging into the array. + if (!isset($array[$key]) || !\is_array($array[$key])) { + $array[$key] = []; + } + + $array = &$array[$key]; + } + + $array[\array_shift($keys)] = $value; + + return $array; + } +} diff --git a/src/Services/Util/EncryptedCache.php b/src/Services/Util/EncryptedCache.php index 25ffc140..5f9b4e17 100644 --- a/src/Services/Util/EncryptedCache.php +++ b/src/Services/Util/EncryptedCache.php @@ -4,12 +4,12 @@ namespace TrueLayer\Services\Util; -use Illuminate\Encryption\Encrypter; use Psr\SimpleCache\CacheInterface; use TrueLayer\Exceptions\DecryptException; use TrueLayer\Exceptions\EncryptException; use TrueLayer\Exceptions\InvalidArgumentException; use TrueLayer\Interfaces\EncryptedCacheInterface; +use TrueLayer\Services\Util\Encryption\Encrypter; final class EncryptedCache implements EncryptedCacheInterface { @@ -37,24 +37,23 @@ public function __construct(CacheInterface $cache, Encrypter $encrypter) * @param string $key * @param null $default * - * @throws InvalidArgumentException - * @throws DecryptException + * @throws DecryptException|InvalidArgumentException * * @return mixed */ public function get(string $key, $default = null) { - $encryptedValue = $this->cache->get($key, $default); + try { + $encryptedValue = $this->cache->get($key, $default); + } catch (\Psr\SimpleCache\InvalidArgumentException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e->getPrevious()); + } if (!\is_string($encryptedValue)) { throw new InvalidArgumentException('The cached value must be string.'); } - try { - return $this->encrypter->decrypt($encryptedValue); - } catch (\Illuminate\Contracts\Encryption\DecryptException $e) { - throw new DecryptException($e->getMessage(), $e->getCode(), $e->getPrevious()); - } + return $this->encrypter->decrypt($encryptedValue); } /** @@ -62,8 +61,8 @@ public function get(string $key, $default = null) * @param mixed $value * @param int|null $ttl * - * @throws InvalidArgumentException * @throws EncryptException + * @throws InvalidArgumentException * * @return bool */ @@ -73,8 +72,6 @@ public function set(string $key, $value, ?int $ttl = null): bool $encryptedValue = $this->encrypter->encrypt($value); return $this->cache->set($key, $encryptedValue, $ttl); - } catch (\Illuminate\Contracts\Encryption\EncryptException $e) { - throw new EncryptException($e->getMessage(), $e->getCode(), $e->getPrevious()); } catch (\Psr\SimpleCache\InvalidArgumentException $e) { throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e->getPrevious()); } @@ -89,7 +86,11 @@ public function set(string $key, $value, ?int $ttl = null): bool */ public function delete(string $key): bool { - return $this->cache->delete($key); + try { + return $this->cache->delete($key); + } catch (\Psr\SimpleCache\InvalidArgumentException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e->getPrevious()); + } } /** @@ -97,6 +98,10 @@ public function delete(string $key): bool */ public function has($key): bool { - return $this->cache->has($key); + try { + return $this->cache->has($key); + } catch (\Psr\SimpleCache\InvalidArgumentException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e->getPrevious()); + } } } diff --git a/src/Services/Util/Encryption/Encrypter.php b/src/Services/Util/Encryption/Encrypter.php new file mode 100644 index 00000000..a1f47d1a --- /dev/null +++ b/src/Services/Util/Encryption/Encrypter.php @@ -0,0 +1,354 @@ + + */ + private static array $supportedCiphers = [ + 'aes-128-cbc' => ['size' => 16, 'aead' => false], + 'aes-256-cbc' => ['size' => 32, 'aead' => false], + 'aes-128-gcm' => ['size' => 16, 'aead' => true], + 'aes-256-gcm' => ['size' => 32, 'aead' => true], + ]; + + /** + * Create a new encrypter instance. + * + * @param string $key + * @param string $cipher + * + * @return void + * @throws \RuntimeException + * + */ + public function __construct(string $key, string $cipher = 'aes-128-cbc') + { + $key = (string)$key; + + if (!static::supported($key, $cipher)) { + $ciphers = \implode(', ', \array_keys(self::$supportedCiphers)); + + throw new \RuntimeException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}."); + } + + $this->key = $key; + $this->cipher = $cipher; + } + + /** + * Determine if the given key and cipher combination is valid. + * + * @param string $key + * @param string $cipher + * + * @return bool + */ + public static function supported(string $key, string $cipher): bool + { + if (!isset(self::$supportedCiphers[\strtolower($cipher)])) { + return false; + } + + return \mb_strlen($key, '8bit') === self::$supportedCiphers[\strtolower($cipher)]['size']; + } + + /** + * Create a new encryption key for the given cipher. + * + * @param string $cipher + * + * @return string + * @throws \Exception + * + */ + public static function generateKey(string $cipher): string + { + return \random_bytes(self::$supportedCiphers[\strtolower($cipher)]['size'] ?? 32); + } + + /** + * Encrypt the given value. + * + * @param mixed $value + * + * @return string + * @throws EncryptException + * + */ + public function encrypt(mixed $value): string + { + $iv = \random_bytes(\max(1, \openssl_cipher_iv_length(\strtolower($this->cipher)))); + + $value = \openssl_encrypt( + \serialize($value), + \strtolower($this->cipher), $this->key, 0, $iv, $tag + ); + + if ($value === false) { + throw new EncryptException('Could not encrypt the data.'); + } + + $iv = \base64_encode($iv); + $tag = \base64_encode($tag ?? ''); + + $mac = self::$supportedCiphers[\strtolower($this->cipher)]['aead'] + ? '' // For AEAD-algorithms, the tag / MAC is returned by openssl_encrypt... + : $this->hash($iv, $value, $this->key); + + $json = \json_encode(\compact('iv', 'value', 'mac', 'tag'), JSON_UNESCAPED_SLASHES); + + if (\json_last_error() !== JSON_ERROR_NONE || $json === false) { + throw new EncryptException('Could not encrypt the data.'); + } + + return \base64_encode($json); + } + + /** + * Decrypt the given value. + * + * @param string $payload + * @param bool $unserialize + * + * @return mixed + * @throws DecryptException + * + */ + public function decrypt(string $payload, bool $unserialize = true): mixed + { + $payload = $this->getJsonPayload($payload); + + $iv = \base64_decode($payload['iv']); + + $this->ensureTagIsValid( + $tag = empty($payload['tag']) ? null : \base64_decode($payload['tag']) + ); + + $decrypted = false; + + // Here we will decrypt the value. If we are able to successfully decrypt it + // we will then unserialize it and return it out to the caller. If we are + // unable to decrypt this value we will throw out an exception message. + foreach ($this->getAllKeys() as $key) { + $decrypted = \openssl_decrypt( + $payload['value'], \strtolower($this->cipher), $key, 0, $iv, $tag ?? '' + ); + + if ($decrypted !== false) { + break; + } + } + + if ($decrypted === false) { + throw new DecryptException('Could not decrypt the data.'); + } + + return $unserialize ? \unserialize($decrypted) : $decrypted; + } + + /** + * Create a MAC for the given value. + * + * @param string $iv + * @param mixed $value + * @param string $key + * + * @return string + */ + protected function hash(string $iv, mixed $value, string $key): string + { + return \hash_hmac('sha256', $iv . $value, $key); + } + + /** + * Get the JSON array from the given payload. + * + * @param string $payload + * + * @return array{'iv':string, 'value':string, 'mac':string, 'tag':string} + * @throws DecryptException + * + */ + protected function getJsonPayload(string $payload): array + { + if (!\is_string($payload)) { + throw new DecryptException('The payload is invalid.'); + } + + $payload = \json_decode(\base64_decode($payload), true); + + // If the payload is not valid JSON or does not have the proper keys set we will + // assume it is invalid and bail out of the routine since we will not be able + // to decrypt the given value. We'll also check the MAC for this encryption. + if (!$this->validPayload($payload) || !\is_array($payload)) { + throw new DecryptException('The payload is invalid.'); + } + + if (!self::$supportedCiphers[\strtolower($this->cipher)]['aead'] && !$this->validMac($payload)) { + throw new DecryptException('The MAC is invalid.'); + } + + // @phpstan-ignore-next-line + return $payload; + } + + /** + * Verify that the encryption payload is valid. + * + * @param mixed $payload + * + * @return bool + */ + protected function validPayload(mixed $payload): bool + { + if (!\is_array($payload)) { + return false; + } + + foreach (['iv', 'value', 'mac'] as $item) { + if (!isset($payload[$item]) || !\is_string($payload[$item])) { + return false; + } + } + + if (isset($payload['tag']) && !\is_string($payload['tag'])) { + return false; + } + + $decoded = \base64_decode($payload['iv'], true); + if ($decoded === false) { + return false; + } + + return \strlen($decoded) === \openssl_cipher_iv_length(\strtolower($this->cipher)); + } + + /** + * Determine if the MAC for the given payload is valid. + * + * @param mixed[] $payload + * + * @return bool + */ + protected function validMac(array $payload): bool + { + if (!isset($payload['iv']) || !\is_string($payload['iv']) || !\is_string($payload['mac'])) { + return false; + } + + foreach ($this->getAllKeys() as $key) { + $valid = \hash_equals( + $this->hash($payload['iv'], $payload['value'], $key), $payload['mac'] + ); + + if ($valid === true) { + return true; + } + } + + return false; + } + + /** + * Ensure the given tag is a valid tag given the selected cipher. + * + * @param string|null $tag + * + * @return void + * @throws DecryptException + * + */ + protected function ensureTagIsValid(?string $tag): void + { + if (self::$supportedCiphers[\strtolower($this->cipher)]['aead'] && ($tag === null || \strlen($tag) !== 16)) { + throw new DecryptException('Could not decrypt the data.'); + } + + if (!self::$supportedCiphers[\strtolower($this->cipher)]['aead'] && \is_string($tag)) { + throw new DecryptException('Unable to use tag because the cipher algorithm does not support AEAD.'); + } + } + + /** + * Get the encryption key that the encrypter is currently using. + * + * @return string + */ + public function getKey(): string + { + return $this->key; + } + + /** + * Get the current encryption key and all previous encryption keys. + * + * @return string[] + */ + public function getAllKeys(): array + { + return [$this->key, ...$this->previousKeys]; + } + + /** + * Get the previous encryption keys. + * + * @return string[] + */ + public function getPreviousKeys(): array + { + return $this->previousKeys; + } + + /** + * Set the previous / legacy encryption keys that should be utilized if decryption fails. + * + * @param string[] $keys + * + * @return $this + */ + public function previousKeys(array $keys): self + { + foreach ($keys as $key) { + if (!static::supported($key, $this->cipher)) { + $ciphers = \implode(', ', \array_keys(self::$supportedCiphers)); + + throw new \RuntimeException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}."); + } + } + + $this->previousKeys = $keys; + + return $this; + } +} diff --git a/src/Services/Util/Encryption/LICENSE.md b/src/Services/Util/Encryption/LICENSE.md new file mode 100644 index 00000000..79810c84 --- /dev/null +++ b/src/Services/Util/Encryption/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Taylor Otwell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Services/Util/Encryption/README.md b/src/Services/Util/Encryption/README.md new file mode 100644 index 00000000..a6a9f847 --- /dev/null +++ b/src/Services/Util/Encryption/README.md @@ -0,0 +1,2 @@ +Pull request # adds a local copy of the [illuminate/encryption](https://github.com/illuminate/encryption) package in +order to reduce the number of dependencies and the underlying contraints. diff --git a/src/Services/Util/Str.php b/src/Services/Util/Str.php new file mode 100644 index 00000000..3ad41e48 --- /dev/null +++ b/src/Services/Util/Str.php @@ -0,0 +1,121 @@ + $needles + * + * @return bool + */ + public static function endsWith($haystack, $needles) + { + if (!\is_iterable($needles)) { + $needles = (array) $needles; + } + + foreach ($needles as $needle) { + if ((string) $needle !== '' && \str_ends_with($haystack, $needle)) { + return true; + } + } + + return false; + } + + /** + * Convert a value to studly caps case. + * + * @param string $value + * + * @return string + */ + public static function studly($value) + { + $key = $value; + + if (isset(static::$studlyCache[$key])) { + return static::$studlyCache[$key]; + } + + $words = \explode(' ', \str_replace(['-', '_'], ' ', $value)); + + $studlyWords = \array_map(function (string $word) { + $encoding = 'UTF-8'; + $firstChar = \mb_substr($word, 0, 1, $encoding); + $then = \mb_substr($word, 1, null, $encoding); + + return \mb_strtoupper($firstChar, $encoding) . $then; + }, $words); + + return static::$studlyCache[$key] = \implode($studlyWords); + } +} diff --git a/src/Services/Webhooks/JwksManager.php b/src/Services/Webhooks/JwksManager.php index 23ff0b5c..1c18d057 100644 --- a/src/Services/Webhooks/JwksManager.php +++ b/src/Services/Webhooks/JwksManager.php @@ -4,14 +4,12 @@ namespace TrueLayer\Services\Webhooks; -use Illuminate\Contracts\Validation\Factory as ValidatorFactory; -use Illuminate\Support\Carbon; +use Carbon\Carbon; use TrueLayer\Constants\CacheKeys; use TrueLayer\Exceptions\ApiRequestJsonSerializationException; use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\SignerException; use TrueLayer\Exceptions\TLPublicKeysNotFound; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Interfaces\ApiClient\ApiClientInterface; use TrueLayer\Interfaces\EncryptedCacheInterface; use TrueLayer\Interfaces\Webhook\JwksManagerInterface; @@ -31,11 +29,6 @@ class JwksManager implements JwksManagerInterface */ private ?EncryptedCacheInterface $cache; - /** - * @var ValidatorFactory - */ - private ValidatorFactory $validatorFactory; - /** * @var mixed[]|null */ @@ -49,23 +42,18 @@ class JwksManager implements JwksManagerInterface /** * @param ApiClientInterface $api * @param EncryptedCacheInterface|null $cache - * @param ValidatorFactory $validatorFactory */ - public function __construct(ApiClientInterface $api, - ?EncryptedCacheInterface $cache, - ValidatorFactory $validatorFactory) + public function __construct(ApiClientInterface $api, ?EncryptedCacheInterface $cache) { $this->api = $api; $this->cache = $cache; - $this->validatorFactory = $validatorFactory; } /** - * @throws ValidationException - * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException * @throws TLPublicKeysNotFound * @throws SignerException + * @throws ApiRequestJsonSerializationException * * @return mixed[] */ @@ -134,12 +122,10 @@ public function clear(): JwksManagerInterface * @throws ApiResponseUnsuccessfulException * @throws ApiRequestJsonSerializationException * @throws SignerException - * @throws ValidationException */ public function retrieve(): void { $data = (new WebhooksApi($this->api))->jwks(); - $this->validate($data); $this->keys = (array) $data['keys']; $this->retrievedAt = (int) Carbon::now()->timestamp; @@ -149,26 +135,6 @@ public function retrieve(): void } } - /** - * @param mixed[] $data - * - * @throws ValidationException - */ - private function validate(array $data): void - { - $validator = $this->validatorFactory->make($data, [ - 'keys.*.kty' => 'required|string|in:RSA,EC', - 'keys.*.alg' => 'required|string|in:RS512,ES512', - 'keys.*.kid' => 'required|string', - ]); - - try { - $validator->validate(); - } catch (\Illuminate\Validation\ValidationException $e) { - throw new ValidationException($validator); - } - } - /** * @return mixed[] */ diff --git a/src/Services/Webhooks/Webhook.php b/src/Services/Webhooks/Webhook.php index b8a9f257..4ec00c2e 100644 --- a/src/Services/Webhooks/Webhook.php +++ b/src/Services/Webhooks/Webhook.php @@ -7,7 +7,6 @@ use TrueLayer\Constants\CustomHeaders; use TrueLayer\Entities\Webhook\Event; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Exceptions\WebhookHandlerException; use TrueLayer\Exceptions\WebhookHandlerInvalidArgumentException; use TrueLayer\Exceptions\WebhookVerificationFailedException; @@ -65,9 +64,9 @@ public function __construct(WebhookVerifierInterface $verifier, EntityFactoryInt /** * @param callable|class-string $handler * - * @throws \ReflectionException * @throws WebhookHandlerInvalidArgumentException * @throws WebhookHandlerException + * @throws \ReflectionException * * @return WebhookInterface */ @@ -81,9 +80,9 @@ public function handler($handler): WebhookInterface /** * @param callable|class-string ...$handlers * - * @throws \ReflectionException * @throws WebhookHandlerInvalidArgumentException * @throws WebhookHandlerException + * @throws \ReflectionException * * @return WebhookInterface */ @@ -132,7 +131,6 @@ public function headers(array $headers): WebhookInterface /** * @throws InvalidArgumentException - * @throws ValidationException * @throws WebhookHandlerInvalidArgumentException * @throws WebhookVerificationFailedException */ @@ -185,11 +183,10 @@ private function getHeaders(): array } /** - * @throws InvalidArgumentException - * @throws ValidationException * @throws WebhookHandlerInvalidArgumentException + * @throws InvalidArgumentException * - * s * @return EventInterface + * @return EventInterface */ private function getEventEntity(): EventInterface { @@ -205,7 +202,7 @@ private function getEventEntity(): EventInterface } catch (\Exception $e) { // If we do not recognise the data structure as valid for any of the existing entities, // We create the base event entity which will be passed to the default handler. - if ($e instanceof ValidationException || $e instanceof InvalidArgumentException) { + if ($e instanceof InvalidArgumentException) { return $this->entityFactory->makeConcrete(Event::class)->fill($data); } throw $e; diff --git a/src/Services/Webhooks/WebhookHandlerManager.php b/src/Services/Webhooks/WebhookHandlerManager.php index 7fc395ea..25166420 100644 --- a/src/Services/Webhooks/WebhookHandlerManager.php +++ b/src/Services/Webhooks/WebhookHandlerManager.php @@ -4,11 +4,11 @@ namespace TrueLayer\Services\Webhooks; -use Illuminate\Support\Arr; use TrueLayer\Exceptions\WebhookHandlerException; use TrueLayer\Exceptions\WebhookHandlerInvalidArgumentException; use TrueLayer\Interfaces\Webhook\EventInterface; use TrueLayer\Interfaces\Webhook\WebhookHandlerManagerInterface; +use TrueLayer\Services\Util\Arr; class WebhookHandlerManager implements WebhookHandlerManagerInterface { @@ -45,9 +45,9 @@ public function add($handler): void /** * @param callable|class-string ...$handlers * - * @throws WebhookHandlerException * @throws WebhookHandlerInvalidArgumentException * @throws \ReflectionException + * @throws WebhookHandlerException * * @return void */ @@ -91,8 +91,8 @@ private function getFor(EventInterface $event): array /** * @param \Closure $handler * - * @throws WebhookHandlerInvalidArgumentException * @throws \ReflectionException + * @throws WebhookHandlerInvalidArgumentException * * @return class-string */ @@ -121,8 +121,8 @@ private function getHandlerParameterType(\Closure $handler): string * * @param class-string $class * - * @throws WebhookHandlerException * @throws \ReflectionException + * @throws WebhookHandlerException * * @return mixed */ diff --git a/src/Services/Webhooks/WebhookVerifier.php b/src/Services/Webhooks/WebhookVerifier.php index 6e253180..0578f66e 100644 --- a/src/Services/Webhooks/WebhookVerifier.php +++ b/src/Services/Webhooks/WebhookVerifier.php @@ -8,7 +8,6 @@ use TrueLayer\Exceptions\ApiRequestJsonSerializationException; use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Exceptions\SignerException; -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Exceptions\WebhookHandlerInvalidArgumentException; use TrueLayer\Exceptions\WebhookVerificationFailedException; use TrueLayer\Interfaces\Webhook\JwksManagerInterface; @@ -73,7 +72,6 @@ public function verify(string $path, array $headers, string $body): void * @throws RequestPathNotFoundException * @throws RequiredHeaderMissingException * @throws SignerException - * @throws ValidationException * @throws WebhookHandlerInvalidArgumentException */ private function verifyWithRetry(string $path, array $headers, string $body): void diff --git a/src/Traits/ArrayableAttributes.php b/src/Traits/ArrayableAttributes.php index bfa4a943..b3828118 100644 --- a/src/Traits/ArrayableAttributes.php +++ b/src/Traits/ArrayableAttributes.php @@ -4,10 +4,10 @@ namespace TrueLayer\Traits; -use Illuminate\Support\Arr; -use Illuminate\Support\Str; use TrueLayer\Constants\DateTime; use TrueLayer\Interfaces\ArrayableInterface; +use TrueLayer\Services\Util\Arr; +use TrueLayer\Services\Util\Str; trait ArrayableAttributes { diff --git a/src/Traits/CastsAttributes.php b/src/Traits/CastsAttributes.php index c33db295..96c14b71 100644 --- a/src/Traits/CastsAttributes.php +++ b/src/Traits/CastsAttributes.php @@ -4,11 +4,10 @@ namespace TrueLayer\Traits; -use Illuminate\Support\Arr; -use Illuminate\Support\Carbon; -use Illuminate\Support\Str; +use Carbon\Carbon; use TrueLayer\Exceptions\InvalidArgumentException; -use TrueLayer\Exceptions\ValidationException; +use TrueLayer\Services\Util\Arr; +use TrueLayer\Services\Util\Str; // TODO: Refactor castData trait CastsAttributes @@ -30,7 +29,6 @@ protected function casts(): array * @param mixed[] $data * @param mixed[]|null $casts * - * @throws ValidationException * @throws InvalidArgumentException * * @return mixed[] @@ -102,17 +100,6 @@ protected function toDateTime(string $dateTime): ?\DateTimeInterface try { return Carbon::parse($dateTime); } catch (\Exception $e) { - // php 7.4 will not parse strings with nanoseconds - // we downgrade to microseconds and retry - $subsecond = Str::after($dateTime, '.'); - $subsecond = Str::before($subsecond, 'Z'); - - if (Str::length($subsecond) > 6) { - $dateTime = \substr_replace($dateTime, '', -1, 3); - - return $this->toDateTime($dateTime); - } - return null; } } @@ -123,7 +110,6 @@ protected function toDateTime(string $dateTime): ?\DateTimeInterface * @param class-string $abstract * @param mixed[]|null $data * - * @throws ValidationException * @throws InvalidArgumentException * * @return T diff --git a/src/Traits/MakeValidatorFactory.php b/src/Traits/MakeValidatorFactory.php deleted file mode 100644 index 0e7afd37..00000000 --- a/src/Traits/MakeValidatorFactory.php +++ /dev/null @@ -1,29 +0,0 @@ -addNamespace('lang', $langPath); - $loader->load('en', 'validation', 'lang'); - $translationFactory = new Translator($loader, 'en'); - - return new Factory($translationFactory); - } -} diff --git a/src/Traits/ValidatesAttributes.php b/src/Traits/ValidatesAttributes.php deleted file mode 100644 index 35631f89..00000000 --- a/src/Traits/ValidatesAttributes.php +++ /dev/null @@ -1,91 +0,0 @@ -rules; - } - - /** - * @throws \TrueLayer\Exceptions\ValidationException - * - * @return self - */ - public function validate(): self - { - $this->validateData(); - - return $this; - } - - /** - * @return bool - */ - public function isValid(): bool - { - return !$this->validator()->fails(); - } - - /** - * @return mixed[] - */ - public function errors(): array - { - return $this->validator()->errors()->toArray(); - } - - /** - * @param mixed[]|null $data - * - * @throws \TrueLayer\Exceptions\ValidationException - * - * @return $this - */ - protected function validateData(array $data = null): self - { - $validator = $this->validator($data); - - try { - $validator->validate(); - - return $this; - } catch (ValidationException $e) { - throw new \TrueLayer\Exceptions\ValidationException($validator); - } - } - - /** - * @param mixed[]|null $data - * - * @return Validator - */ - protected function validator(array $data = null): Validator - { - return $this->validatorFactory->make( - $data ?: $this->all(), - $this->rules() - ); - } -} diff --git a/src/Validation/AllowedConstant.php b/src/Validation/AllowedConstant.php deleted file mode 100644 index 9fb7c938..00000000 --- a/src/Validation/AllowedConstant.php +++ /dev/null @@ -1,56 +0,0 @@ -class = $class; - } - - /** - * @param string $attribute - * @param mixed $value - * - * @throws \ReflectionException - * - * @return bool - */ - public function passes($attribute, $value): bool - { - $constants = (new \ReflectionClass($this->class))->getConstants(); - - return \in_array($value, \array_values($constants)); - } - - /** - * @return string - */ - public function message(): string - { - return 'The provided :attribute value is not allowed.'; - } - - /** - * @param class-string $class - * - * @return AllowedConstant - */ - public static function in(string $class): AllowedConstant - { - return new self($class); - } -} diff --git a/src/Validation/ValidType.php b/src/Validation/ValidType.php deleted file mode 100644 index 33537815..00000000 --- a/src/Validation/ValidType.php +++ /dev/null @@ -1,79 +0,0 @@ -classes = $classes; - } - - /** - * @param string $attribute - * @param mixed $value - * - * @throws ValidationException - * - * @return bool - */ - public function passes($attribute, $value): bool - { - if (!$this->instanceOf($value)) { - return false; - } - - if (\is_object($value) && \method_exists($value, 'validate')) { - $value->validate(); - } - - return true; - } - - /** - * @return string - */ - public function message(): string - { - return 'The provided :attribute value is not valid.'; - } - - /** - * @param mixed $value - * - * @return bool - */ - private function instanceOf($value): bool - { - foreach ($this->classes as $class) { - if ($value instanceof $class) { - return true; - } - } - - return false; - } - - /** - * @param class-string ...$class - * - * @return ValidType - */ - public static function of(string ...$class): ValidType - { - return new self($class); - } -} diff --git a/tests/acceptance/Payment/MerchantAccountPaymentAuthorizationTest.php b/tests/acceptance/Payment/MerchantAccountPaymentAuthorizationTest.php index ec85d2d5..3f4b8d1f 100644 --- a/tests/acceptance/Payment/MerchantAccountPaymentAuthorizationTest.php +++ b/tests/acceptance/Payment/MerchantAccountPaymentAuthorizationTest.php @@ -2,7 +2,6 @@ declare(strict_types=1); -use Illuminate\Support\Arr; use Ramsey\Uuid\Uuid; use TrueLayer\Constants\AuthorizationFlowActionTypes; use TrueLayer\Constants\AuthorizationFlowStatusTypes; @@ -17,13 +16,14 @@ use TrueLayer\Interfaces\Payment\PaymentSourceInterface; use TrueLayer\Interfaces\PaymentMethod\BankTransferPaymentMethodInterface; use TrueLayer\Interfaces\Provider\ProviderInterface; +use TrueLayer\Services\Util\Arr; \it('creates a merchant payment', function () { $helper = \paymentHelper(); $account = Arr::first( $helper->client()->getMerchantAccounts(), - fn (MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' + fn(MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' ); $merchantBeneficiary = $helper->merchantBeneficiary($account); @@ -170,17 +170,6 @@ \expect($fetched->getId())->toBeString(); }); -\it('throws exception when creating payment with invalid user date of birth', function () { - $helper = \paymentHelper(); - - $helper->client()->payment() - ->paymentMethod($helper->bankTransferMethod($helper->sortCodeBeneficiary())) - ->amountInMinor(10) - ->currency('GBP') - ->user($helper->userWithDateOfBirth('invalid date')) - ->create(); -})->throws(TrueLayer\Exceptions\ValidationException::class); - \it('creates payment with idempotency key', function () { $helper = \paymentHelper(); diff --git a/tests/acceptance/PayoutTest.php b/tests/acceptance/PayoutTest.php index 40711c2b..e97e1116 100644 --- a/tests/acceptance/PayoutTest.php +++ b/tests/acceptance/PayoutTest.php @@ -2,7 +2,6 @@ declare(strict_types=1); -use Illuminate\Support\Arr; use Ramsey\Uuid\Uuid; use TrueLayer\Constants\Currencies; use TrueLayer\Interfaces\Beneficiary\ExternalAccountBeneficiaryInterface; @@ -11,13 +10,14 @@ use TrueLayer\Interfaces\Payment\PaymentSettledInterface; use TrueLayer\Interfaces\Payout\PaymentSourceBeneficiaryInterface; use TrueLayer\Interfaces\Payout\PayoutRetrievedInterface; +use TrueLayer\Services\Util\Arr; \it('creates a closed loop payout', function () { $helper = \paymentHelper(); $account = Arr::first( $helper->client()->getMerchantAccounts(), - fn (MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' + fn(MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' ); $merchantBeneficiary = $helper->merchantBeneficiary($account); @@ -75,7 +75,7 @@ $account = Arr::first( $helper->client()->getMerchantAccounts(), - fn (MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' + fn(MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' ); $merchantBeneficiary = $helper->merchantBeneficiary($account); @@ -138,7 +138,7 @@ $account = Arr::first( $client->getMerchantAccounts(), - fn (MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' + fn(MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' ); $payoutBeneficiary = $client->payoutBeneficiary()->externalAccount() diff --git a/tests/acceptance/Pest.php b/tests/acceptance/Pest.php index 0907186c..cbe198d7 100644 --- a/tests/acceptance/Pest.php +++ b/tests/acceptance/Pest.php @@ -2,21 +2,21 @@ declare(strict_types=1); -use Illuminate\Support\Str; use Symfony\Component\Dotenv\Dotenv; use TrueLayer\Client; use TrueLayer\Constants\Endpoints; use TrueLayer\Exceptions\SignerException; use TrueLayer\Interfaces\Client\ClientInterface; +use TrueLayer\Services\Util\Str; use TrueLayer\Tests\Acceptance\Payment\CreatePayment; $dotenv = new Dotenv(); $dotenv->load(__DIR__ . '/../../.env'); /** + * @return ClientInterface * @throws SignerException * - * @return ClientInterface */ function client(): ClientInterface { @@ -29,9 +29,9 @@ function client(): ClientInterface } /** + * @return CreatePayment * @throws SignerException * - * @return CreatePayment */ function paymentHelper(): CreatePayment { @@ -45,7 +45,7 @@ function bankAction(string $redirectUri, string $action): void $id = Str::before($id, '#token'); $token = Str::after($redirectUri, '#token='); - $result = (new \GuzzleHttp\Client())->post("{$url}/api/single-immediate-payments/{$id}/action", [ + $result = (new GuzzleHttp\Client())->post("{$url}/api/single-immediate-payments/{$id}/action", [ 'headers' => [ 'authorization' => "Bearer {$token}", ], diff --git a/tests/acceptance/RefundTest.php b/tests/acceptance/RefundTest.php index 45d56b24..b47742a8 100644 --- a/tests/acceptance/RefundTest.php +++ b/tests/acceptance/RefundTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -use Illuminate\Support\Arr; use Ramsey\Uuid\Uuid; use TrueLayer\Interfaces\MerchantAccount\MerchantAccountInterface; use TrueLayer\Interfaces\Payment\PaymentCreatedInterface; use TrueLayer\Interfaces\Payment\PaymentSettledInterface; use TrueLayer\Interfaces\Payment\RefundRetrievedInterface; +use TrueLayer\Services\Util\Arr; function assertRefundCommonAcceptance(RefundRetrievedInterface $refund) { @@ -27,7 +27,7 @@ function assertRefundCommonAcceptance(RefundRetrievedInterface $refund) $account = Arr::first( $helper->client()->getMerchantAccounts(), - fn (MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' + fn(MerchantAccountInterface $account) => $account->getCurrency() === 'GBP' ); $merchantBeneficiary = $helper->merchantBeneficiary($account); @@ -54,7 +54,7 @@ function assertRefundCommonAcceptance(RefundRetrievedInterface $refund) \expect($response->getId())->toBeString(); return $created; - } catch (\TrueLayer\Exceptions\ApiResponseUnsuccessfulException $e) { + } catch (TrueLayer\Exceptions\ApiResponseUnsuccessfulException $e) { throw $e; } }); diff --git a/tests/integration/ApiClient/AccessTokenTest.php b/tests/integration/ApiClient/AccessTokenTest.php index 3f958977..5ba363ab 100644 --- a/tests/integration/ApiClient/AccessTokenTest.php +++ b/tests/integration/ApiClient/AccessTokenTest.php @@ -2,8 +2,8 @@ declare(strict_types=1); +use Carbon\Carbon; use GuzzleHttp\Psr7\Response; -use Illuminate\Support\Carbon; use TrueLayer\Tests\Integration\Mocks; \it('appends access token', function () { @@ -61,7 +61,7 @@ Mocks\AuthResponse::success(), // Retrieve the access token Mocks\ErrorResponse::unauthenticated(), // Reject the access token in the api call Mocks\AuthResponse::success('_SECOND_'), // Retrieve new access token - new Response(200), ] // Accept the access token in the api call + new Response(200),] // Accept the access token in the api call ) ->create(); @@ -77,15 +77,15 @@ \it('reuses cached access token across requests', function () { $okResponse = new Response(200); - $encrypter = new \Illuminate\Encryption\Encrypter(\hex2bin('31c8d81a110849f83131541b9f67c3cba9c7e0bb103bc4dd19377f0fdf2d924b'), \TrueLayer\Constants\Encryption::ALGORITHM); + $encrypter = new TrueLayer\Services\Util\Encryption\Encrypter(\hex2bin('31c8d81a110849f83131541b9f67c3cba9c7e0bb103bc4dd19377f0fdf2d924b'), TrueLayer\Constants\Encryption::ALGORITHM); - $cacheMock = Mockery::mock(\Psr\SimpleCache\CacheInterface::class); + $cacheMock = Mockery::mock(Psr\SimpleCache\CacheInterface::class); $cacheMock->shouldReceive('has')->andReturnTrue(); $cacheMock->shouldReceive('set')->andReturnTrue(); $cacheMock->shouldReceive('get')->andReturn($encrypter->encrypt([ 'access_token' => Mocks\AuthResponse::ACCESS_TOKEN, 'expires_in' => 3600, - 'retrieved_at' => (int) Carbon::now()->timestamp, + 'retrieved_at' => (int)Carbon::now()->timestamp, ])); $client1 = \rawClient([Mocks\AuthResponse::success(), $okResponse, $okResponse]) ->cache($cacheMock, '31c8d81a110849f83131541b9f67c3cba9c7e0bb103bc4dd19377f0fdf2d924b') @@ -108,15 +108,15 @@ function () { \it('fetches a new token if the cached one is expired', function () { $okResponse = new Response(200); - $encrypter = new \Illuminate\Encryption\Encrypter(\hex2bin('31c8d81a110849f83131541b9f67c3cba9c7e0bb103bc4dd19377f0fdf2d924b'), \TrueLayer\Constants\Encryption::ALGORITHM); + $encrypter = new TrueLayer\Services\Util\Encryption\Encrypter(\hex2bin('31c8d81a110849f83131541b9f67c3cba9c7e0bb103bc4dd19377f0fdf2d924b'), TrueLayer\Constants\Encryption::ALGORITHM); - $cacheMock = Mockery::mock(\Psr\SimpleCache\CacheInterface::class); + $cacheMock = Mockery::mock(Psr\SimpleCache\CacheInterface::class); $cacheMock->shouldReceive('has')->andReturnTrue(); $cacheMock->shouldReceive('set')->andReturnTrue(); $cacheMock->shouldReceive('get')->andReturn($encrypter->encrypt([ 'access_token' => 'expired-token', 'expires_in' => 3600, - 'retrieved_at' => (int) Carbon::now()->timestamp - 5000, + 'retrieved_at' => (int)Carbon::now()->timestamp - 5000, ])); $client = \rawClient([Mocks\AuthResponse::success(), $okResponse, $okResponse]) @@ -136,7 +136,7 @@ function () { $client->getApiClient()->request()->uri('/test')->post(); $requestedScope = \getRequestPayload(0)['scope']; - \expect($requestedScope)->toBe(\TrueLayer\Constants\Scopes::DEFAULT); + \expect($requestedScope)->toBe(TrueLayer\Constants\Scopes::DEFAULT); }); \it('uses custom scopes if provided', function () { diff --git a/tests/integration/ApiClient/IdempotencyKeyTest.php b/tests/integration/ApiClient/IdempotencyKeyTest.php index 9f2ec46f..40d706d3 100644 --- a/tests/integration/ApiClient/IdempotencyKeyTest.php +++ b/tests/integration/ApiClient/IdempotencyKeyTest.php @@ -3,7 +3,6 @@ declare(strict_types=1); use GuzzleHttp\Psr7\Response; -use Illuminate\Support\Collection; use TrueLayer\Constants\CustomHeaders; use TrueLayer\Exceptions\ApiResponseUnsuccessfulException; use TrueLayer\Tests\Integration\Mocks\ErrorResponse; @@ -23,29 +22,23 @@ \request($responses)->post(); - $sentRequests = Collection::make(\getSentHttpRequests()); - $sentRequests->shift(); // Remove access token request + $sentRequests = \getSentHttpRequests(); + \array_shift($sentRequests); + $idempotencyKeys = array_map(fn($r) => $r->getHeaderLine(CustomHeaders::IDEMPOTENCY_KEY), $sentRequests); + $idempotencyKeys = array_unique($idempotencyKeys); - $idempotencyKeys = $sentRequests - ->map(fn ($r) => $r->getHeaderLine(CustomHeaders::IDEMPOTENCY_KEY)) - ->unique() - ->count(); - - \expect($idempotencyKeys)->toBe(1); + \expect(count($idempotencyKeys))->toBe(1); }); \it('regenerates idempotency key on reuse error', function () { \request([ErrorResponse::idempotencyKeyReuse(), new Response(200)])->post(); - $sentRequests = Collection::make(\getSentHttpRequests()); - $sentRequests->shift(); // Remove access token request - - $idempotencyKeys = $sentRequests - ->map(fn ($r) => $r->getHeaderLine(CustomHeaders::IDEMPOTENCY_KEY)) - ->unique() - ->count(); + $sentRequests = \getSentHttpRequests(); + \array_shift($sentRequests); + $idempotencyKeys = array_map(fn($r) => $r->getHeaderLine(CustomHeaders::IDEMPOTENCY_KEY), $sentRequests); + $idempotencyKeys = array_unique($idempotencyKeys); - \expect($idempotencyKeys)->toBe(2); + \expect(count($idempotencyKeys))->toBe(2); }); \it('regenerates idempotency key only once', function () { @@ -81,15 +74,12 @@ ->requestOptions($requestOptions) ->post(); - $sentRequests = Collection::make(\getSentHttpRequests()); - $sentRequests->shift(); // Remove access token request - - $idempotencyKeys = $sentRequests - ->map(fn ($r) => $r->getHeaderLine(CustomHeaders::IDEMPOTENCY_KEY)) - ->unique() - ->count(); + $sentRequests = \getSentHttpRequests(); + \array_shift($sentRequests); + $idempotencyKeys = array_map(fn($r) => $r->getHeaderLine(CustomHeaders::IDEMPOTENCY_KEY), $sentRequests); + $idempotencyKeys = array_unique($idempotencyKeys); - \expect($idempotencyKeys)->toBe(1); + \expect(count($idempotencyKeys))->toBe(1); }); \it('does not retry on key reuse error', function () { diff --git a/tests/integration/HppTest.php b/tests/integration/HppTest.php index b4330b68..d8fd0c30 100644 --- a/tests/integration/HppTest.php +++ b/tests/integration/HppTest.php @@ -2,7 +2,6 @@ declare(strict_types=1); -use TrueLayer\Exceptions\ValidationException; use TrueLayer\Tests\Integration\Mocks\CreatePayment; use TrueLayer\Tests\Integration\Mocks\PaymentResponse; @@ -36,24 +35,3 @@ '#payment_id=5a2a0a0d-d3ad-4740-860b-45a01bcc17ac&resource_token=the-token&return_uri=http%3A%2F%2Fwww.return.com&c_primary=111&c_secondary=222222&c_tertiary=333333' ); }); - -\it('validates input', function () { - try { - \client()->hostedPaymentsPage() - ->primaryColour('1st') - ->secondaryColour('2nd') - ->tertiaryColour('3rd') - ->toUrl(); - } catch (ValidationException $e) { - \expect($e->getErrors())->toHaveKeys([ - 'payment_id', - 'resource_token', - 'return_uri', - 'c_primary', - 'c_secondary', - 'c_tertiary', - ]); - - throw $e; - } -})->throws(ValidationException::class); diff --git a/tests/integration/PaymentCreateTest.php b/tests/integration/PaymentCreateTest.php index dbcd07e0..2df1ba3d 100644 --- a/tests/integration/PaymentCreateTest.php +++ b/tests/integration/PaymentCreateTest.php @@ -201,14 +201,6 @@ ]); }); -\it('should throw when sending an invalid user date of birth', function () { - $factory = CreatePayment::responses([ - PaymentResponse::created(), - ]); - - $factory->payment($factory->newUserWithDateOfBirth('invalid data'), $factory->bankTransferMethod($factory->sortCodeBeneficiary()))->create(); -})->throws(TrueLayer\Exceptions\ValidationException::class); - \it('parses payment creation response correctly', function () { $factory = CreatePayment::responses([PaymentResponse::created()]); $payment = $factory->payment($factory->newUser(), $factory->bankTransferMethod($factory->sortCodeBeneficiary()))->create(); diff --git a/tests/integration/Pest.php b/tests/integration/Pest.php index 5b89fb04..241b84f8 100644 --- a/tests/integration/Pest.php +++ b/tests/integration/Pest.php @@ -34,13 +34,9 @@ * * @param array $mockResponses The responses returned by the 'server' * - * @throws \TrueLayer\Exceptions\ApiRequestValidationException - * @throws ApiResponseUnsuccessfulException - * @throws \TrueLayer\Exceptions\ApiResponseValidationException - * @throws \TrueLayer\Exceptions\InvalidArgumentException - * @throws ApiRequestJsonSerializationException + * @return TrueLayer\Interfaces\Configuration\ClientConfigInterface + * @throws SignerException * - * @return \TrueLayer\Interfaces\Configuration\ClientConfigInterface */ function rawClient(array $mockResponses = []) { @@ -50,11 +46,11 @@ function rawClient(array $mockResponses = []) $handlerStack = HandlerStack::create(new MockHandler($mockResponses)); - $handlerStack->push(\GuzzleHttp\Middleware::history($httpTransactions)); + $handlerStack->push(GuzzleHttp\Middleware::history($httpTransactions)); $mockClient = new HttpClient(['handler' => $handlerStack]); - return \TrueLayer\Client::configure() + return TrueLayer\Client::configure() ->clientId('client_id') ->clientSecret('client_secret') ->keyId('123') @@ -67,12 +63,9 @@ function rawClient(array $mockResponses = []) * * @param array $mockResponses The responses returned by the 'server' * + * @return TrueLayer\Interfaces\Client\ClientInterface * @throws SignerException - * @throws ApiRequestJsonSerializationException - * @throws ApiResponseUnsuccessfulException - * @throws \TrueLayer\Exceptions\InvalidArgumentException * - * @return \TrueLayer\Interfaces\Client\ClientInterface */ function client($mockResponses = []) { @@ -92,16 +85,11 @@ function client($mockResponses = []) * @param array $mockResponses * * @throws SignerException - * @throws ApiRequestJsonSerializationException - * @throws ApiResponseUnsuccessfulException - * @throws \TrueLayer\Exceptions\InvalidArgumentException - * - * @return \TrueLayer\Interfaces\ApiClient\ApiRequestInterface */ function request($mockResponses = []): TrueLayer\Interfaces\ApiClient\ApiRequestInterface { if (empty($mockResponses)) { - $mockResponses = new \GuzzleHttp\Psr7\Response(200, [], 'OK'); + $mockResponses = new GuzzleHttp\Psr7\Response(200, [], 'OK'); } return \client($mockResponses)->getApiClient()->request() @@ -115,11 +103,11 @@ function getSentHttpRequests(): array { global $httpTransactions; - return \Illuminate\Support\Arr::pluck($httpTransactions, 'request'); + return array_map(fn($transaction) => $transaction['request'], $httpTransactions); } /** - * @param int $requestIndex + * @param int $requestIndex * @param bool $asArray * * @return mixed @@ -135,7 +123,7 @@ function getRequestPayload(int $requestIndex, bool $asArray = true) } /** - * @param int $requestIndex + * @param int $requestIndex * @param string $name * * @return string[] @@ -158,14 +146,14 @@ function getRequestIdempotencyKey(int $requestIndex): string /** * @param string $body * - * @throws \TrueLayer\Exceptions\InvalidArgumentException - * @throws SignerException + * @return WebhookInterface * @throws WebhookHandlerInvalidArgumentException - * @throws \TrueLayer\Signing\Exceptions\InvalidArgumentException + * @throws TrueLayer\Signing\Exceptions\InvalidArgumentException * @throws ApiRequestJsonSerializationException * @throws ApiResponseUnsuccessfulException + * @throws TrueLayer\Exceptions\InvalidArgumentException * - * @return WebhookInterface + * @throws SignerException */ function webhook(string $body): WebhookInterface { diff --git a/tests/integration/ValidationTest.php b/tests/integration/ValidationTest.php deleted file mode 100644 index 7ffad480..00000000 --- a/tests/integration/ValidationTest.php +++ /dev/null @@ -1,16 +0,0 @@ -payment()->create(); - } catch (ValidationException $e) { - $errors = $e->getErrors(); - \expect($errors['amount_in_minor'][0])->toBe('The amount in minor field is required.'); - - throw $e; - } -})->throws(ValidationException::class); diff --git a/tests/integration/WebhookCacheTest.php b/tests/integration/WebhookCacheTest.php index 07835cec..9214300b 100644 --- a/tests/integration/WebhookCacheTest.php +++ b/tests/integration/WebhookCacheTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); +use Carbon\Carbon; use GuzzleHttp\Psr7\Response; -use Illuminate\Encryption\Encrypter; -use Illuminate\Support\Carbon; use Jose\Component\KeyManagement\JWKFactory; use TrueLayer\Constants\Encryption; use TrueLayer\Exceptions\WebhookVerificationFailedException; +use TrueLayer\Services\Util\Encryption\Encrypter; use TrueLayer\Tests\Integration\Mocks\Signing; use TrueLayer\Tests\Integration\Mocks\WebhookPayload; @@ -19,7 +19,7 @@ $cacheData['retrieved_at'] = Carbon::now()->timestamp; $cacheData = $encrypter->encrypt($cacheData); - $cache = Mockery::mock(\Psr\SimpleCache\CacheInterface::class); + $cache = Mockery::mock(Psr\SimpleCache\CacheInterface::class); $cache->shouldReceive('has')->andReturnTrue(); $cache->shouldReceive('set')->andReturnTrue(); $cache->shouldReceive('get')->andReturn($cacheData); @@ -47,7 +47,7 @@ $cacheData['retrieved_at'] = Carbon::now()->subDay()->timestamp; $cacheData = $encrypter->encrypt($cacheData); - $cache = Mockery::mock(\Psr\SimpleCache\CacheInterface::class); + $cache = Mockery::mock(Psr\SimpleCache\CacheInterface::class); $cache->shouldReceive('has')->andReturnTrue(); $cache->shouldReceive('set')->andReturnTrue(); $cache->shouldReceive('get')->andReturn($cacheData); @@ -69,7 +69,7 @@ }); \it('fetches keys if keys are not cached', function () { - $cache = Mockery::mock(\Psr\SimpleCache\CacheInterface::class); + $cache = Mockery::mock(Psr\SimpleCache\CacheInterface::class); $cache->shouldReceive('has')->andReturnFalse(); $cache->shouldReceive('set')->andReturnTrue(); @@ -102,7 +102,7 @@ ]; $cacheData = $encrypter->encrypt($cacheData); - $cache = Mockery::mock(\Psr\SimpleCache\CacheInterface::class); + $cache = Mockery::mock(Psr\SimpleCache\CacheInterface::class); $cache->shouldReceive('has')->andReturnTrue(); $cache->shouldReceive('set')->andReturnTrue(); $cache->shouldReceive('get')->andReturn($cacheData); @@ -141,7 +141,7 @@ ]; $cacheData = $encrypter->encrypt($cacheData); - $cache = Mockery::mock(\Psr\SimpleCache\CacheInterface::class); + $cache = Mockery::mock(Psr\SimpleCache\CacheInterface::class); $cache->shouldReceive('has')->andReturnTrue(); $cache->shouldReceive('set')->andReturnTrue(); $cache->shouldReceive('get')->andReturn($cacheData);