diff --git a/.github/workflows/run-phpunit.yaml b/.github/workflows/run-phpunit.yaml deleted file mode 100644 index b052022..0000000 --- a/.github/workflows/run-phpunit.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Run PHPUnit - -on: - push: - -jobs: - run-phpunit: - runs-on: ubuntu-latest - strategy: - matrix: - php-version: ['7.3', '7.4', '8.0', '8.1', latest] - steps: - - uses: actions/checkout@v3 - - - name: Run composer install - uses: php-actions/composer@v6 - with: - php_version: ${{ matrix.php-version }} - args: --ignore-platform-reqs - - - name: Run tests - uses: php-actions/phpunit@v3.0.0 - with: - php_version: ${{ matrix.php-version }} - configuration: phpunit.xml diff --git a/.github/workflows/run-workflow.yaml b/.github/workflows/run-workflow.yaml new file mode 100644 index 0000000..94b2bf7 --- /dev/null +++ b/.github/workflows/run-workflow.yaml @@ -0,0 +1,46 @@ +name: Run Checks + +on: + - push + - pull_request + - fork + +jobs: + run-checks: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + continue-on-error: ${{ matrix.experimental }} + strategy: + matrix: + php-version: ['7.3', '7.4', '8.0', '8.1', '8.2'] + experimental: [false] + steps: + - uses: actions/checkout@v3 + + - name: Validate Composer Files + run: composer validate --strict + + - name: Run composer install + uses: php-actions/composer@v6 + with: + php_version: ${{ matrix.php-version }} + + - name: Run linter + run: composer lint + + - name: Run phpstan + uses: php-actions/phpstan@v3 + with: + php_version: ${{ matrix.php-version }} + version: 1.9.14 + configuration: phpstan.neon + memory_limit: 256M + + - name: Run tests + uses: php-actions/phpunit@v3 + with: + php_version: ${{ matrix.php-version }} + version: 9 + configuration: phpunit.xml diff --git a/.gitignore b/.gitignore index 4346a40..ade8a81 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -.phpunit.result.cache test-reports/ -composer.lock \ No newline at end of file +composer.lock +*.cache \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1da40be..7e3ac96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,50 @@ 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.5.2] - 2023-05-05 +### Fixed +- Improved refundRequest Validation +- Fix to allow zero amount items + +## [2.5.1] - 2023-04-19 +### Fixed +- Fixed requestSettlements url parameters +- Fixed item validation + +## [2.5.0] - 2023-04-11 +### Added +- You can now request payment report by settlement ID +- Added new improved way for requesting payment reports: requestSettlements() +### Fixed +- Fixed date validation on report requests +- Code cleanup for request classes + +## [2.3.2] - 2023-02-22 +### Added +- PHPStan (static analyser) added in workflow +- Tests are now run also on PHP 8.2 +### Fixed +- Code quality improvements and other fixes + +## [2.4.1] - 2023-01-11 +- Add missing transaction property to activateInvoice request +- Use PSR-12 standard + +## [2.4.0] - 2022-11-15 +### Added +- Add missing properties to RefundRequest +- Add missing fields to PaymentResponse model +- Add method for activate-invoice endpoint +### Fixed +- Fix function parameter types + +## [2.3.0] - 2022-09-05 +### Added +- Payment report endpoint added +- companyName added to Customer model +### Fixed +- Fixed cUrlClient query parameters + ## [2.2.0] - 2022-06-15 ### Added - Added PHPUnit test workflow diff --git a/README.md b/README.md index bed4f74..816d2a8 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,18 @@ To use the payment service, you need to sign up for a Paytrail account. Transact ### General requirements - PHP version >= 7.3 -- [Guzzle](https://github.com/guzzle/guzzle) 7 or 6 - PHP HTTP client for performing HTTP request. +- ext-curl PHP cURL extension +- ext-json PHP JSON extension ### Development requirements - [PHPUnit](https://github.com/sebastianbergmann/phpunit) - A programmer-oriented testing framework for running unit tests in PHP. +- [Guzzle](https://github.com/guzzle/guzzle) 7 or 6 - PHP HTTP client for performing HTTP request. + +### Guzzle +PHP-SDK will use Guzzle 6 or 7, if in present application, otherwise it will fall back to cURL. Guzzle is still used as dev dependency to make testing easier. + +Using Guzzle is recommended on applications using PHP-SDK. ## Installation @@ -76,6 +83,10 @@ Some of the key features are: - [Requesting merchant settlements](https://docs.paytrail.com/#/?id=settlements) +### Reports + +- [Request payment report](https://docs.paytrail.com/#/?id=payment-report-request) + ## Methods List of `Client::class` methods @@ -98,4 +109,12 @@ List of `Client::class` methods | createMitPaymentAuthorizationHold() | Create MiT authorization hold | | createMitPaymentCommit() | Commit MiT authorization hold | | revertPaymentAuthorizationHold() | Revert existing Mit or CiT authorization hold | -| getSettlements() | Request settlements | +| getSettlements() [Deprecated] | Deprecated Request settlements | +| requestSettlements() | Request settlements | +| requestPaymentReport() | Request payment report | +| requestPaymentReportBySettlement() | Request payment report by settlement ID | + + +--- + +**_Disclaimer:_** *This open source project is made available to assist coders in getting started with our API. However, we do not provide any warranty or guarantee that the code will work as intended and offer limited support for it. Use at your own risk.* diff --git a/composer.json b/composer.json index b39aad9..a07cee6 100644 --- a/composer.json +++ b/composer.json @@ -19,10 +19,11 @@ "ext-curl": "*" }, "require-dev": { - "phpunit/phpunit": "^9.0 | ^8.4", + "phpunit/phpunit": "^10.0 || ^9.0", "squizlabs/php_codesniffer": "^3.6", "phpcompatibility/php-compatibility": "^9.3", "phpmd/phpmd": "^2.10", + "phpstan/phpstan": "1.9.14", "mockery/mockery": "^1.5", "guzzlehttp/guzzle": "^7.0|^6.0" }, @@ -33,6 +34,9 @@ } }, "scripts": { + "analyze": [ + "vendor/bin/phpstan" + ], "post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility", "post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility", "test": "\"vendor/bin/phpunit\"", diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..749a32d --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + level: 3 + paths: + - src + - tests diff --git a/phpunit.xml b/phpunit.xml index c93f96a..039a248 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,5 +1,10 @@ - + tests diff --git a/src/Client.php b/src/Client.php index 607a2d5..9a43845 100644 --- a/src/Client.php +++ b/src/Client.php @@ -1,18 +1,22 @@ bindProperties($provider_data); - }, $decoded->providers); - $groups = array_map(function ($group_data) { return [ 'id' => $group_data->id, @@ -179,11 +181,9 @@ public function getGroupedPaymentProviders(int $amount = null, string $locale = ]; }, $decoded->groups); - //$res['providers'] = $providers; $res['terms'] = $decoded->terms; $res['groups'] = $groups; - //return $providers; return $res; } @@ -215,13 +215,16 @@ function ($decoded) { return (new PaymentResponse()) ->setTransactionId($decoded->transactionId ?? null) ->setHref($decoded->href ?? null) - ->setProviders($decoded->providers ?? null); + ->setTerms($decoded->terms ?? null) + ->setGroups($decoded->groups ?? []) + ->setReference($decoded->reference ?? null) + ->setProviders($decoded->providers ?? []); } ); return $payment_response; } - + /** * Create a shop-in-shop payment request. * @@ -231,32 +234,34 @@ function ($decoded) { * @throws HmacException Thrown if HMAC calculation fails for responses. * @throws ValidationException Thrown if payment validation fails. */ - public function createShopInShopPayment(ShopInShopPaymentRequest $payment): PaymentResponse - { - $this->validateRequestItem($payment); - - $uri = '/payments'; - - $payment_response = $this->post( - $uri, - $payment, - /** - * Create the response instance. - * - * @param mixed $decoded The decoded body. - * @return PaymentResponse - */ - function ($decoded) { - return (new PaymentResponse()) - ->setTransactionId($decoded->transactionId ?? null) - ->setHref($decoded->href ?? null) - ->setProviders($decoded->providers ?? null); - } - ); - - return $payment_response; - } - + public function createShopInShopPayment(ShopInShopPaymentRequest $payment): PaymentResponse + { + $this->validateRequestItem($payment); + + $uri = '/payments'; + + $paymentResponse = $this->post( + $uri, + $payment, + /** + * Create the response instance. + * + * @param mixed $decoded The decoded body. + * @return PaymentResponse + */ + function ($decoded) { + return (new PaymentResponse()) + ->setTransactionId($decoded->transactionId ?? null) + ->setHref($decoded->href ?? null) + ->setTerms($decoded->terms ?? null) + ->setGroups($decoded->groups ?? []) + ->setReference($decoded->reference ?? null) + ->setProviders($decoded->providers ?? []); + } + ); + return $paymentResponse; + } + /** * Create a payment status request. * @@ -445,7 +450,6 @@ function ($decoded) { true, $paytrailTokenizationId ); - } catch (HmacException $e) { throw $e; } @@ -516,8 +520,10 @@ public function createMitPaymentAuthorizationHold(MitPaymentRequest $mitPayment) * @throws HmacException Thrown if HMAC calculation fails for responses. * @throws ValidationException Thrown if payment validation fails. */ - public function createCitPaymentCommit(CitPaymentRequest $citPayment, string $transactionId = ''): CitPaymentResponse - { + public function createCitPaymentCommit( + CitPaymentRequest $citPayment, + string $transactionId = '' + ): CitPaymentResponse { $this->validateRequestItem($citPayment); $uri = '/payments/' . $transactionId . '/token/commit'; @@ -549,8 +555,10 @@ function ($decoded) { * @throws HmacException Thrown if HMAC calculation fails for responses. * @throws ValidationException Thrown if payment validation fails. */ - public function createMitPaymentCommit(MitPaymentRequest $mitPayment, string $transactionId = ''): MitPaymentResponse - { + public function createMitPaymentCommit( + MitPaymentRequest $mitPayment, + string $transactionId = '' + ): MitPaymentResponse { $this->validateRequestItem($mitPayment); $uri = '/payments/' . $transactionId . '/token/commit'; @@ -582,8 +590,9 @@ function ($decoded) { * @throws HmacException Thrown if HMAC calculation fails for responses. * @throws ValidationException Thrown if payment validation fails. */ - public function revertPaymentAuthorizationHold(RevertPaymentAuthHoldRequest $revertPaymentAuthHoldRequest): RevertPaymentAuthHoldResponse - { + public function revertPaymentAuthorizationHold( + RevertPaymentAuthHoldRequest $revertPaymentAuthHoldRequest + ): RevertPaymentAuthHoldResponse { $this->validateRequestItem($revertPaymentAuthHoldRequest); $transactionId = $revertPaymentAuthHoldRequest->getTransactionId(); @@ -608,6 +617,35 @@ function ($decoded) { return $revertPaymentAuthHoldResponse; } + /** + * Get settlements for merchant + * + * @param SettlementRequest $settlementRequest + * @return mixed + * @throws HmacException + * @throws ValidationException + */ + public function requestSettlements(SettlementRequest $settlementRequest) + { + $this->validateRequestItem($settlementRequest); + + $uri = '/settlements'; + + $query = http_build_query($settlementRequest->jsonSerialize()); + + if (!empty($query)) { + $uri .= '?' . $query; + } + + return $this->get( + $uri, + function ($decoded) { + return (new SettlementResponse()) + ->setSettlements($decoded); + } + ); + } + /** * Get settlements for merchant * @@ -618,9 +656,16 @@ function ($decoded) { * @param int|null $subMerchant * @return SettlementResponse * @throws HmacException + * + * @deprecated Method deprecated, use requestSettlements() */ - public function getSettlements(?string $startDate = null, ?string $endDate = null, ?string $reference = null, ?int $limit = null, ?int $subMerchant = null) - { + public function getSettlements( + ?string $startDate = null, + ?string $endDate = null, + ?string $reference = null, + ?int $limit = null, + ?int $subMerchant = null + ) { if ($startDate) { if ((new \DateTime())->createFromFormat('Y-m-d', $startDate) == false) { throw new ValidationException('startDate must be in Y-m-d format'); @@ -629,7 +674,7 @@ public function getSettlements(?string $startDate = null, ?string $endDate = nul if ($endDate) { if ((new \DateTime())->createFromFormat('Y-m-d', $endDate) == false) { - throw new ValidationException('startDate must be in Y-m-d format'); + throw new ValidationException('endDate must be in Y-m-d format'); } } @@ -643,17 +688,105 @@ public function getSettlements(?string $startDate = null, ?string $endDate = nul 'submerchant' => $subMerchant, ]; - $query = http_build_query($parameters); + $query = http_build_query(array_filter($parameters)); if (!empty($query)) { $uri .= '?' . $query; } - return $this->get($uri, - function ($decoded) { - return (new SettlementResponse()) - ->setSettlements($decoded); - }); + return $this->get( + $uri, + function ($decoded) { + return (new SettlementResponse()) + ->setSettlements($decoded); + } + ); + } + + /** + * Request payment report. + * Report is sent to callbackUrl defined in ReportRequest. + * + * @param ReportRequest $reportRequest + * @return ReportRequestResponse + * @throws HmacException + * @throws ValidationException + */ + public function requestPaymentReport(ReportRequest $reportRequest): ReportRequestResponse + { + $this->validateRequestItem($reportRequest); + $uri = '/payments/report'; + + $reportRequestResponse = $this->post( + $uri, + $reportRequest, + /** + * Create the response instance. + * + * @param mixed $decoded The decoded body. + * @return ReportRequestResponse + */ + function ($decoded) { + return (new ReportRequestResponse()) + ->setRequestId($decoded->requestId ?? null); + }, + ); + + return $reportRequestResponse; + } + + /** + * Request payment report by settlement ID. + * + * @param ReportBySettlementRequest $reportRequest + * @param int $settlementId + * @return ReportRequestResponse + * @throws HmacException + * @throws ValidationException + */ + public function requestPaymentReportBySettlement( + ReportBySettlementRequest $reportRequest, + int $settlementId + ): ReportRequestResponse { + $this->validateRequestItem($reportRequest); + $uri = "/settlements/{$settlementId}/payments/report"; + + return $this->post( + $uri, + $reportRequest, + function ($decoded) { + return (new ReportRequestResponse()) + ->setRequestId($decoded->requestId ?? null); + }, + ); + } + + /** + * Activate invoice created with manualInvoiceActivation set to true + * + * @param string $transactionId + * @return InvoiceActivationResponse + * @throws HmacException + */ + public function activateInvoice(string $transactionId) + { + $uri = "/payments/{$transactionId}/activate-invoice"; + + return $this->post( + $uri, + null, + /** + * Create the response instance. + * + * @param mixed $decoded The decoded body. + * @return InvoiceActivationResponse + */ + function ($decoded) { + return (new InvoiceActivationResponse()) + ->setStatus($decoded->status); + }, + $transactionId + ); } /** diff --git a/src/Exception/ClientException.php b/src/Exception/ClientException.php index 2d4185f..44adda7 100644 --- a/src/Exception/ClientException.php +++ b/src/Exception/ClientException.php @@ -1,4 +1,5 @@ responseBody = $responseBody; } diff --git a/src/Exception/HmacException.php b/src/Exception/HmacException.php index 6ff52c7..36da5c5 100644 --- a/src/Exception/HmacException.php +++ b/src/Exception/HmacException.php @@ -1,10 +1,11 @@ messages = $messages; @@ -52,7 +42,7 @@ public function setMessages(array $messages = []) : ValidationException * * @return array */ - public function getMessages() : array + public function getMessages(): array { return $this->messages; } diff --git a/src/Interfaces/AddressInterface.php b/src/Interfaces/AddressInterface.php index e11a757..7091983 100644 --- a/src/Interfaces/AddressInterface.php +++ b/src/Interfaces/AddressInterface.php @@ -1,10 +1,11 @@ postalCode; } @@ -136,7 +135,7 @@ public function getPostalCode(): ?string * * @return AddressInterface Return self to enable chaining. */ - public function setPostalCode(?string $postalCode) : AddressInterface + public function setPostalCode(?string $postalCode): AddressInterface { $this->postalCode = $postalCode; @@ -150,7 +149,6 @@ public function setPostalCode(?string $postalCode) : AddressInterface */ public function getCity(): ?string { - return $this->city; } @@ -161,7 +159,7 @@ public function getCity(): ?string * * @return AddressInterface Return self to enable chaining. */ - public function setCity(?string $city) : AddressInterface + public function setCity(?string $city): AddressInterface { $this->city = $city; @@ -175,7 +173,6 @@ public function setCity(?string $city) : AddressInterface */ public function getCounty(): ?string { - return $this->county; } @@ -186,7 +183,7 @@ public function getCounty(): ?string * * @return AddressInterface Return self to enable chaining. */ - public function setCounty(?string $county) : AddressInterface + public function setCounty(?string $county): AddressInterface { $this->county = $county; @@ -200,7 +197,6 @@ public function setCounty(?string $county) : AddressInterface */ public function getCountry(): ?string { - return $this->country; } @@ -211,7 +207,7 @@ public function getCountry(): ?string * * @return AddressInterface Return self to enable chaining. */ - public function setCountry(?string $country) : AddressInterface + public function setCountry(?string $country): AddressInterface { $this->country = $country; diff --git a/src/Model/CallbackUrl.php b/src/Model/CallbackUrl.php index f5d81e9..480ba67 100644 --- a/src/Model/CallbackUrl.php +++ b/src/Model/CallbackUrl.php @@ -1,10 +1,11 @@ success; } @@ -97,7 +96,6 @@ public function setSuccess(?string $success): CallbackUrlInterface */ public function getCancel(): ?string { - return $this->cancel; } diff --git a/src/Model/Commission.php b/src/Model/Commission.php index da8e5ff..b03bdc1 100644 --- a/src/Model/Commission.php +++ b/src/Model/Commission.php @@ -1,4 +1,5 @@ merchant = $merchant; - - return $this; - } - - /** - * The getter for the merchant. - * - * @return string - */ - public function getMerchant() : string - { - return $this->merchant; - } - - /** - * The setter for the amount. - * - * @param int $amount - * @return Commission Return self to enable chaining. - */ - public function setAmount(int $amount) : Commission - { - $this->amount = $amount; - - return $this; - } - - /** - * The getter for the amount. - * - * @return string - */ - public function getAmount() : int - { - return $this->amount; - } +{ + use JsonSerializable; + + /** + * Validate commission + * + * @throws ValidationException + */ + public function validate() + { + $props = get_object_vars($this); + + if (empty($props['merchant'])) { + throw new ValidationException('Merchant is empty'); + } + + if (filter_var($props['amount'], FILTER_VALIDATE_INT) === false) { + throw new ValidationException('Amount is not an integer'); + } + + return true; + } + + /** + * Merchant identifier for the commission. + * + * @var string + */ + protected $merchant; + + /** + * Total amount to refund this item, in currency's minor units. + * + * @var int + */ + protected $amount; + + /** + * The setter for the merchant. + * + * @param string $merchant + * @return Commission Return self to enable chaining. + */ + public function setMerchant(string $merchant): Commission + { + $this->merchant = $merchant; + + return $this; + } + + /** + * The getter for the merchant. + * + * @return string + */ + public function getMerchant(): string + { + return $this->merchant; + } + + /** + * The setter for the amount. + * + * @param int $amount + * @return Commission Return self to enable chaining. + */ + public function setAmount(int $amount): Commission + { + $this->amount = $amount; + + return $this; + } + + /** + * The getter for the amount. + */ + public function getAmount(): int + { + return $this->amount; + } } diff --git a/src/Model/Customer.php b/src/Model/Customer.php index 96630bc..33fdd80 100644 --- a/src/Model/Customer.php +++ b/src/Model/Customer.php @@ -1,10 +1,11 @@ email; } /** * Set email. * - * @param string $email + * @param string|null $email * * @return self Return self to enable chaining. */ - public function setEmail(?string $email) : CustomerInterface + public function setEmail(?string $email): CustomerInterface { $this->email = $email; - return $this; } @@ -111,21 +116,19 @@ public function setEmail(?string $email) : CustomerInterface */ public function getFirstName(): ?string { - return $this->firstName; } /** * Set first name. * - * @param string $firstName + * @param string|null $firstName * * @return self Return self to enable chaining. */ - public function setFirstName(?string $firstName) : CustomerInterface + public function setFirstName(?string $firstName): CustomerInterface { $this->firstName = $firstName; - return $this; } @@ -136,21 +139,19 @@ public function setFirstName(?string $firstName) : CustomerInterface */ public function getLastName(): ?string { - return $this->lastName; } /** * Set last name. * - * @param string $lastName + * @param string|null $lastName * * @return self Return self to enable chaining. */ - public function setLastName(?string $lastName) : CustomerInterface + public function setLastName(?string $lastName): CustomerInterface { $this->lastName = $lastName; - return $this; } @@ -161,21 +162,19 @@ public function setLastName(?string $lastName) : CustomerInterface */ public function getPhone(): ?string { - return $this->phone; } /** * Set phone. * - * @param string $phone + * @param string|null $phone * * @return self Return self to enable chaining. */ - public function setPhone(?string $phone) : CustomerInterface + public function setPhone(?string $phone): CustomerInterface { $this->phone = $phone; - return $this; } @@ -186,21 +185,42 @@ public function setPhone(?string $phone) : CustomerInterface */ public function getVatId(): ?string { - return $this->vatId; } /** * Set VAT id. * - * @param string $vatId + * @param string|null $vatId * * @return self Return self to enable chaining. */ - public function setVatId(?string $vatId) : CustomerInterface + public function setVatId(?string $vatId): CustomerInterface { $this->vatId = $vatId; + return $this; + } + + /** + * Get Company name. + * + * @return string + */ + public function getCompanyName(): ?string + { + return $this->companyName; + } + /** + * Set Company Name. + * + * @param string|null $companyName + * + * @return self Return self to enable chaining. + */ + public function setCompanyName(?string $companyName): CustomerInterface + { + $this->companyName = $companyName; return $this; } } diff --git a/src/Model/Item.php b/src/Model/Item.php index 5a3e4b2..3847dca 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1,10 +1,11 @@ unitPrice = $unitPrice; @@ -147,7 +149,7 @@ public function getUnits(): ?int * @param int $units * @return ItemInterface Return self to enable chaining. */ - public function setUnits(?int $units) : ItemInterface + public function setUnits(?int $units): ItemInterface { $this->units = $units; @@ -170,7 +172,7 @@ public function getVatPercentage(): ?int * @param int $vatPercentage * @return ItemInterface Return self to enable chaining. */ - public function setVatPercentage(?int $vatPercentage) : ItemInterface + public function setVatPercentage(?int $vatPercentage): ItemInterface { $this->vatPercentage = $vatPercentage; @@ -193,7 +195,7 @@ public function getProductCode(): ?string * @param string $productCode * @return ItemInterface Return self to enable chaining. */ - public function setProductCode(?string $productCode) : ItemInterface + public function setProductCode(?string $productCode): ItemInterface { $this->productCode = $productCode; @@ -204,6 +206,8 @@ public function setProductCode(?string $productCode) : ItemInterface * Get the delivery date. * * @return string + * + * @deprecated Delivery date is deprecated */ public function getDeliveryDate(): ?string { @@ -215,8 +219,10 @@ public function getDeliveryDate(): ?string * * @param string $deliveryDate * @return ItemInterface Return self to enable chaining. + * + * @deprecated Delivery date is deprecated */ - public function setDeliveryDate(?string $deliveryDate) : ItemInterface + public function setDeliveryDate(?string $deliveryDate): ItemInterface { $this->deliveryDate = $deliveryDate; @@ -239,7 +245,7 @@ public function getDescription(): ?string * @param string $description * @return ItemInterface Return self to enable chaining. */ - public function setDescription(?string $description) : ItemInterface + public function setDescription(?string $description): ItemInterface { $this->description = $description; @@ -262,7 +268,7 @@ public function getCategory(): ?string * @param string $category * @return ItemInterface Return self to enable chaining. */ - public function setCategory(?string $category) : ItemInterface + public function setCategory(?string $category): ItemInterface { $this->category = $category; @@ -285,7 +291,7 @@ public function getStamp(): ?string * @param string $stamp * @return ItemInterface Return self to enable chaining. */ - public function setStamp(?string $stamp) : ItemInterface + public function setStamp(?string $stamp): ItemInterface { $this->stamp = $stamp; @@ -308,7 +314,7 @@ public function getReference(): ?string * @param string $reference * @return ItemInterface Return self to enable chaining. */ - public function setReference(?string $reference) : ItemInterface + public function setReference(?string $reference): ItemInterface { $this->reference = $reference; @@ -331,7 +337,7 @@ public function getMerchant(): ?string * @param string $merchant * @return ItemInterface Return self to enable chaining. */ - public function setMerchant(?string $merchant) : ItemInterface + public function setMerchant(?string $merchant): ItemInterface { $this->merchant = $merchant; @@ -354,7 +360,7 @@ public function getCommission(): ?CommissionInterface * @param CommissionInterface $commission * @return ItemInterface Return self to enable chaining. */ - public function setCommission(?CommissionInterface $commission) : ItemInterface + public function setCommission(?CommissionInterface $commission): ItemInterface { $this->commission = $commission; @@ -362,7 +368,7 @@ public function setCommission(?CommissionInterface $commission) : ItemInterface } /** - * Validates with Respect\Validation library and throws an exception for invalid objects + * Validates properties and throws an exception for invalid values * * @throws ValidationException */ @@ -370,19 +376,23 @@ public function validate() { $props = get_object_vars($this); + if ($props['unitPrice'] === null) { + throw new ValidationException('Item unitPrice is empty'); + } if ($props['unitPrice'] < 0) { - throw new ValidationException('Items UnitPrice can\'t be a negative number'); + throw new ValidationException('Items unitPrice can\'t be a negative number'); } - - if (filter_var($props['unitPrice'], FILTER_VALIDATE_INT) === false) { - //throw new \Exception('UnitPrice is not an integer'); - throw new ValidationException('UnitPrice is not an integer'); + if ($props['unitPrice'] > 99999999) { + throw new ValidationException('Items unitPrice can\'t be over 99999999'); + } + if ($props['units'] === null) { + throw new ValidationException('Item units is empty'); } - if (filter_var($props['units'], FILTER_VALIDATE_INT) === false) { - throw new ValidationException('Units is not an integer'); + if ($props['units'] < 0) { + throw new ValidationException('Items units can\'t be a negative number'); } - if (filter_var($props['vatPercentage'], FILTER_VALIDATE_INT) === false) { - throw new ValidationException('vatPercentage is not an integer'); + if ($props['vatPercentage'] < 0) { + throw new ValidationException('Items vatPercentage can\'t be a negative number'); } if (empty($props['productCode'])) { throw new ValidationException('productCode is empty'); @@ -391,19 +401,19 @@ public function validate() return true; } - /** - * Validates shop-in-shop props with Respect\Validation library and throws an exception for invalid objects - * - * @throws ValidationException - */ - public function validateShopInShop() - { - $props = get_object_vars($this); - - if (empty($props['merchant'])) { - throw new ValidationException('merchant is empty'); - } - - return true; - } + /** + * Validates shop-in-shop props and throws an exception for invalid values + * + * @throws ValidationException + */ + public function validateShopInShop() + { + $props = get_object_vars($this); + + if (empty($props['merchant'])) { + throw new ValidationException('merchant is empty'); + } + + return true; + } } diff --git a/src/Model/PaymentMethodGroup.php b/src/Model/PaymentMethodGroup.php new file mode 100644 index 0000000..921a8e5 --- /dev/null +++ b/src/Model/PaymentMethodGroup.php @@ -0,0 +1,140 @@ +id; + } + + /** + * Set payment method group id. + * + * @param string|null $id + * @return self + */ + public function setId(?string $id): self + { + $this->id = $id; + + return $this; + } + + /** + * Get payment method group name. + * + * @return string|null + */ + public function getName(): ?string + { + return $this->name; + } + + /** + * Set payment method group name. + * + * @param string|null $name + * @return self + */ + public function setName(?string $name): self + { + $this->name = $name; + + return $this; + } + + /** + * Get payment method group svg url. + * + * @return string|null + */ + public function getSvg(): ?string + { + return $this->svg; + } + + /** + * Set payment method group svg url. + * + * @param string|null $svg + * @return self + */ + public function setSvg(?string $svg): self + { + $this->svg = $svg; + + return $this; + } + + /** + * Get payment method group icon url. + * + * @return string|null + */ + public function getIcon(): ?string + { + return $this->icon; + } + + /** + * Set payment method group icon url. + * + * @param string|null $icon + * @return self + */ + public function setIcon(?string $icon): self + { + $this->icon = $icon; + + return $this; + } +} diff --git a/src/Model/Provider.php b/src/Model/Provider.php index c6f7883..cc851af 100644 --- a/src/Model/Provider.php +++ b/src/Model/Provider.php @@ -1,10 +1,11 @@ url; } @@ -91,7 +90,7 @@ public function getUrl() : ?string * @param string $url * @return Provider Return self to enable chaining. */ - public function setUrl(?string $url) : Provider + public function setUrl(?string $url): Provider { $this->url = $url; @@ -103,9 +102,8 @@ public function setUrl(?string $url) : Provider * * @return string */ - public function getIcon() : ?string + public function getIcon(): ?string { - return $this->icon; } @@ -115,7 +113,7 @@ public function getIcon() : ?string * @param string $icon * @return Provider Return self to enable chaining. */ - public function setIcon(?string $icon) : Provider + public function setIcon(?string $icon): Provider { $this->icon = $icon; @@ -127,9 +125,8 @@ public function setIcon(?string $icon) : Provider * * @return string */ - public function getSvg() : ?string + public function getSvg(): ?string { - return $this->svg; } @@ -139,7 +136,7 @@ public function getSvg() : ?string * @param string $svg * @return Provider Return self to enable chaining. */ - public function setSvg(?string $svg) : Provider + public function setSvg(?string $svg): Provider { $this->svg = $svg; @@ -151,9 +148,8 @@ public function setSvg(?string $svg) : Provider * * @return string */ - public function getName() : ?string + public function getName(): ?string { - return $this->name; } @@ -163,7 +159,7 @@ public function getName() : ?string * @param string $name * @return Provider Return self to enable chaining. */ - public function setName(?string $name) : Provider + public function setName(?string $name): Provider { $this->name = $name; @@ -175,9 +171,8 @@ public function setName(?string $name) : Provider * * @return string */ - public function getGroup() : ?string + public function getGroup(): ?string { - return $this->group; } @@ -187,7 +182,7 @@ public function getGroup() : ?string * @param string $group * @return Provider Return self to enable chaining. */ - public function setGroup(?string $group) : Provider + public function setGroup(?string $group): Provider { $this->group = $group; @@ -199,9 +194,8 @@ public function setGroup(?string $group) : Provider * * @return string */ - public function getId() : ?string + public function getId(): ?string { - return $this->id; } @@ -211,7 +205,7 @@ public function getId() : ?string * @param string $id * @return Provider Return self to enable chaining. */ - public function setId(?string $id) : Provider + public function setId(?string $id): Provider { $this->id = $id; @@ -223,9 +217,8 @@ public function setId(?string $id) : Provider * * @return array */ - public function getParameters() : ?array + public function getParameters(): ?array { - return $this->parameters; } @@ -235,7 +228,7 @@ public function getParameters() : ?array * @param array $parameters * @return Provider Return self to enable chaining. */ - public function setParameters(?array $parameters) : Provider + public function setParameters(?array $parameters): Provider { $this->parameters = $parameters; diff --git a/src/Model/RefundItem.php b/src/Model/RefundItem.php index ccfbb07..66ff6c3 100644 --- a/src/Model/RefundItem.php +++ b/src/Model/RefundItem.php @@ -1,10 +1,11 @@ amount; } @@ -76,7 +74,7 @@ public function getAmount() : int * @param int $amount The amount. * @return RefundItem Return self to enable chaining. */ - public function setAmount(? int $amount) : RefundItem + public function setAmount(?int $amount): RefundItem { $this->amount = $amount; @@ -88,7 +86,7 @@ public function setAmount(? int $amount) : RefundItem * * @return string */ - public function getStamp() : string + public function getStamp(): string { return $this->stamp; } @@ -99,7 +97,7 @@ public function getStamp() : string * @param string $stamp The stamp. * @return RefundItem Return self to enable chaining. */ - public function setStamp(?string $stamp) : RefundItem + public function setStamp(?string $stamp): RefundItem { $this->stamp = $stamp; diff --git a/src/Model/Token/Card.php b/src/Model/Token/Card.php index 9b87dc2..b306df4 100644 --- a/src/Model/Token/Card.php +++ b/src/Model/Token/Card.php @@ -1,4 +1,5 @@ http_client = new RequestClient(); } + /** + * A proxy for the Signature class' static method + * to be used via a client instance. + * + * @param array $response The response parameters. + * @param string $body The response body. + * @param string $signature The response signature key. + * + * @throws HmacException + */ + abstract public function validateHmac(array $response = [], string $body = '', string $signature = ''); + /** * A wrapper for post requests. * * @param string $uri The uri for the request. - * @param \JsonSerializable $data The request payload. - * @param callable|null $callback The callback method to run for the decoded response. If left empty, the response is returned. - * @param string|null $transactionId Paytrail transaction ID when accessing single transaction not required for a new payment request. + * @param \JsonSerializable|null $data The request payload. + * @param callable|null $callback The callback method to run for the decoded response. + * If left empty, the response is returned. + * @param string|null $transactionId Paytrail transaction ID when accessing single transaction. + * Not required for a new payment request. * @param bool $signatureInHeader Checks if signature is calculated from header/body parameters * @param string|null $paytrailTokenizationId Paytrail tokenization ID for getToken request * * @return mixed * @throws HmacException */ - protected function post(string $uri, \JsonSerializable $data, callable $callback = null, string $transactionId = null, bool $signatureInHeader = true, string $paytrailTokenizationId = null) - { + protected function post( + string $uri, + \JsonSerializable $data = null, + callable $callback = null, + string $transactionId = null, + bool $signatureInHeader = true, + string $paytrailTokenizationId = null + ) { $body = json_encode($data, JSON_UNESCAPED_SLASHES); if ($signatureInHeader) { @@ -77,8 +98,11 @@ protected function post(string $uri, \JsonSerializable $data, callable $callback $headers = $this->reduceHeaders($response->getHeaders()); $this->validateHmac($headers, $body, $headers['signature'] ?? ''); } else { + // @phpstan-ignore-next-line FIXME $mac = $this->calculateHmac($data->toArray()); + // @phpstan-ignore-next-line FIXME $data->setSignature($mac); + // @phpstan-ignore-next-line FIXME $body = json_encode($data->toArray(), JSON_UNESCAPED_SLASHES); $response = $this->http_client->request('POST', $uri, [ @@ -101,8 +125,10 @@ protected function post(string $uri, \JsonSerializable $data, callable $callback * A wrapper for get requests. * * @param string $uri The uri for the request. - * @param callable|null $callback The callback method to run for the decoded response. If left empty, the response is returned. - * @param string|null $transactionId Paytrail transaction ID when accessing single transaction not required for a new payment request. + * @param callable|null $callback The callback method to run for the decoded response. + * If left empty, the response is returned. + * @param string|null $transactionId Paytrail transaction ID when accessing single transaction. + * Not required for a new payment request. * * @return mixed * @throws HmacException @@ -136,13 +162,17 @@ protected function get(string $uri, callable $callback = null, string $transacti * Format request headers. * * @param string $method The request method. GET or POST. - * @param string|null $transactionId Paytrail transaction ID when accessing single transaction not required for a new payment request. + * @param string|null $transactionId Paytrail transaction ID when accessing single transaction. + * Not required for a new payment request. * @param string|null $checkoutTokenizationId Paytrail tokenization ID for getToken request * * @return array */ - protected function getHeaders(string $method, string $transactionId = null, string $checkoutTokenizationId = null): array - { + protected function getHeaders( + string $method, + string $transactionId = null, + string $checkoutTokenizationId = null + ): array { $datetime = new \DateTime(); $headers = [ @@ -213,4 +243,4 @@ protected function calculateHmac(array $params = [], string $body = ''): string { return Signature::calculateHmac($params, $body, $this->secretKey); } -} \ No newline at end of file +} diff --git a/src/Request/AbstractPaymentRequest.php b/src/Request/AbstractPaymentRequest.php index bdcee43..c6bf131 100644 --- a/src/Request/AbstractPaymentRequest.php +++ b/src/Request/AbstractPaymentRequest.php @@ -1,4 +1,5 @@ getItems(), function ($carry = 0, ?Item $item = null) { + $items_total = array_reduce($this->getItems(), function ($carry = 0, ?ItemInterface $item = null) { if ($item === null) { return $carry; } @@ -156,42 +154,42 @@ public function validate() /** * Array of items. * - * @var Item[] + * @var ItemInterface[] */ protected $items; /** * Customer information. * - * @var Customer + * @var CustomerInterface */ protected $customer; /** * Delivery address. * - * @var Address + * @var AddressInterface */ protected $deliveryAddress; /** * Invoicing address. * - * @var Address + * @var AddressInterface */ protected $invoicingAddress; /** * Where to redirect browser after a payment is paid or cancelled. * - * @var CallbackUrl; + * @var CallbackUrlInterface */ protected $redirectUrls; /** * Which url to ping after this payment is paid or cancelled. * - * @var CallbackUrl; + * @var CallbackUrlInterface */ protected $callbackUrls; @@ -210,14 +208,20 @@ public function validate() */ protected $groups; + /** + * Activate invoices manually + * + * @var boolean + */ + protected $manualInvoiceActivation; + /** * Get the stamp. * * @return string */ - public function getStamp() : ?string + public function getStamp(): ?string { - return $this->stamp; } @@ -240,9 +244,8 @@ public function setStamp(?string $stamp): PaymentRequestInterface * * @return string */ - public function getReference() : ?string + public function getReference(): ?string { - return $this->reference; } @@ -255,7 +258,6 @@ public function getReference() : ?string */ public function setReference(?string $reference): PaymentRequestInterface { - $this->reference = $reference; return $this; @@ -266,9 +268,8 @@ public function setReference(?string $reference): PaymentRequestInterface * * @return int */ - public function getAmount() : ?int + public function getAmount(): ?int { - return $this->amount; } @@ -279,9 +280,8 @@ public function getAmount() : ?int * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setAmount(?int $amount) : PaymentRequestInterface + public function setAmount(?int $amount): PaymentRequestInterface { - $this->amount = $amount; return $this; @@ -292,9 +292,8 @@ public function setAmount(?int $amount) : PaymentRequestInterface * * @return string */ - public function getCurrency() : ?string + public function getCurrency(): ?string { - return $this->currency; } @@ -305,9 +304,8 @@ public function getCurrency() : ?string * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setCurrency(?string $currency) : PaymentRequestInterface + public function setCurrency(?string $currency): PaymentRequestInterface { - $this->currency = $currency; return $this; @@ -318,9 +316,8 @@ public function setCurrency(?string $currency) : PaymentRequestInterface * * @return string */ - public function getLanguage() : ?string + public function getLanguage(): ?string { - return $this->language; } @@ -331,9 +328,8 @@ public function getLanguage() : ?string * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setLanguage(?string $language) : PaymentRequestInterface + public function setLanguage(?string $language): PaymentRequestInterface { - $this->language = $language; return $this; @@ -344,9 +340,8 @@ public function setLanguage(?string $language) : PaymentRequestInterface * * @return ItemInterface[] */ - public function getItems() : ?array + public function getItems(): ?array { - return $this->items; } @@ -357,7 +352,7 @@ public function getItems() : ?array * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setItems(?array $items) : PaymentRequestInterface + public function setItems(?array $items): PaymentRequestInterface { $this->items = $items; @@ -373,9 +368,8 @@ public function setItems(?array $items) : PaymentRequestInterface * * @return CustomerInterface */ - public function getCustomer() : ?CustomerInterface + public function getCustomer(): ?CustomerInterface { - return $this->customer; } @@ -386,9 +380,8 @@ public function getCustomer() : ?CustomerInterface * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setCustomer(?CustomerInterface $customer) : PaymentRequestInterface + public function setCustomer(?CustomerInterface $customer): PaymentRequestInterface { - $this->customer = $customer; return $this; @@ -399,9 +392,8 @@ public function setCustomer(?CustomerInterface $customer) : PaymentRequestInterf * * @return AddressInterface */ - public function getDeliveryAddress() : ?AddressInterface + public function getDeliveryAddress(): ?AddressInterface { - return $this->deliveryAddress; } @@ -412,9 +404,8 @@ public function getDeliveryAddress() : ?AddressInterface * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setDeliveryAddress(?AddressInterface $deliveryAddress) : PaymentRequestInterface + public function setDeliveryAddress(?AddressInterface $deliveryAddress): PaymentRequestInterface { - $this->deliveryAddress = $deliveryAddress; return $this; @@ -425,9 +416,8 @@ public function setDeliveryAddress(?AddressInterface $deliveryAddress) : Payment * * @return AddressInterface */ - public function getInvoicingAddress() : ?AddressInterface + public function getInvoicingAddress(): ?AddressInterface { - return $this->invoicingAddress; } @@ -438,9 +428,8 @@ public function getInvoicingAddress() : ?AddressInterface * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setInvoicingAddress(?AddressInterface $invoicingAddress) : PaymentRequestInterface + public function setInvoicingAddress(?AddressInterface $invoicingAddress): PaymentRequestInterface { - $this->invoicingAddress = $invoicingAddress; return $this; @@ -451,9 +440,8 @@ public function setInvoicingAddress(?AddressInterface $invoicingAddress) : Payme * * @return CallbackUrlInterface */ - public function getRedirectUrls() : ?CallbackUrlInterface + public function getRedirectUrls(): ?CallbackUrlInterface { - return $this->redirectUrls; } @@ -464,9 +452,8 @@ public function getRedirectUrls() : ?CallbackUrlInterface * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setRedirectUrls(?CallbackUrlInterface $redirectUrls) : PaymentRequestInterface + public function setRedirectUrls(?CallbackUrlInterface $redirectUrls): PaymentRequestInterface { - $this->redirectUrls = $redirectUrls; return $this; @@ -477,9 +464,8 @@ public function setRedirectUrls(?CallbackUrlInterface $redirectUrls) : PaymentRe * * @return CallbackUrlInterface */ - public function getCallbackUrls() : ?CallbackUrlInterface + public function getCallbackUrls(): ?CallbackUrlInterface { - return $this->callbackUrls; } @@ -490,9 +476,8 @@ public function getCallbackUrls() : ?CallbackUrlInterface * * @return PaymentRequestInterface Return self to enable chaining. */ - public function setCallbackUrls(?CallbackUrlInterface $callbackUrls) : PaymentRequestInterface + public function setCallbackUrls(?CallbackUrlInterface $callbackUrls): PaymentRequestInterface { - $this->callbackUrls = $callbackUrls; return $this; @@ -510,7 +495,7 @@ public function getCallbackDelay(): int * @param int $callbackDelay * @return PaymentRequestInterface Return self to enable chaining. */ - public function setCallbackDelay(int $callbackDelay) : PaymentRequestInterface + public function setCallbackDelay(int $callbackDelay): PaymentRequestInterface { $this->callbackDelay = $callbackDelay; @@ -521,7 +506,7 @@ public function setCallbackDelay(int $callbackDelay) : PaymentRequestInterface * @param array $groups * @return PaymentRequestInterface Return self to enable chaining. */ - public function setGroups(array $groups) : PaymentRequestInterface + public function setGroups(array $groups): PaymentRequestInterface { $this->groups = $groups; @@ -535,4 +520,22 @@ public function getGroups(): array { return $this->groups; } + + /** + * @param bool $value + * @return PaymentRequestInterface + */ + public function setManualInvoiceActivation(bool $value = false): PaymentRequestInterface + { + $this->manualInvoiceActivation = $value; + return $this; + } + + /** + * @return bool + */ + public function getManualInvoiceActivation(): bool + { + return $this->manualInvoiceActivation; + } } diff --git a/src/Request/AddCardFormRequest.php b/src/Request/AddCardFormRequest.php index 09e9f57..98fd7a5 100644 --- a/src/Request/AddCardFormRequest.php +++ b/src/Request/AddCardFormRequest.php @@ -1,4 +1,5 @@ jsonSerialize()); return json_decode($dataArray, true); } -} \ No newline at end of file +} diff --git a/src/Request/CitPaymentRequest.php b/src/Request/CitPaymentRequest.php index d240a1c..2ead458 100644 --- a/src/Request/CitPaymentRequest.php +++ b/src/Request/CitPaymentRequest.php @@ -1,4 +1,5 @@ email; } @@ -61,14 +57,13 @@ public function getEmail() : string /** * Set the email. * - * @param string $email + * @param string|null $email * * @return EmailRefundRequest Return self to enable chaining. */ - public function setEmail(?string $email) : EmailRefundRequest + public function setEmail(?string $email): RefundRequest { $this->email = $email; - return $this; } } diff --git a/src/Request/GetTokenRequest.php b/src/Request/GetTokenRequest.php index a2ef9b4..93aaba7 100644 --- a/src/Request/GetTokenRequest.php +++ b/src/Request/GetTokenRequest.php @@ -1,4 +1,5 @@ transactionId; } @@ -50,7 +49,7 @@ public function getTransactionId() : string * * @return PaymentStatusRequest Return self to enable chaining. */ - public function setTransactionId(?string $transactionId) : PaymentStatusRequest + public function setTransactionId(?string $transactionId): PaymentStatusRequest { $this->transactionId = $transactionId; diff --git a/src/Request/RefundRequest.php b/src/Request/RefundRequest.php index c632f99..25fc479 100644 --- a/src/Request/RefundRequest.php +++ b/src/Request/RefundRequest.php @@ -1,4 +1,5 @@ items)) { - // Count the total amount of the payment. + if (!empty($this->items)) { + // Count the total amount of the refund. $items_total = array_reduce($this->items, function ($carry = 0, ?RefundItem $item = null) { if ($item === null) { return $carry; @@ -49,12 +49,8 @@ public function validate() $items_total = $this->amount; } - if (empty($props['amount'])) { - throw new ValidationException('Amount can not be empty'); - } - - if (filter_var($props['amount'], FILTER_VALIDATE_INT) === false) { - throw new ValidationException('Amount is not an integer'); + if (empty($props['amount']) && empty($this->items)) { + throw new ValidationException('Amount can not be empty when making refund without items'); } if ($items_total !== $props['amount']) { @@ -65,6 +61,7 @@ public function validate() throw new ValidationException('CallbackUrls are not set'); } + // Validate callbackUrls $this->callbackUrls->validate(); return true; @@ -93,12 +90,33 @@ public function validate() */ protected $callbackUrls; + /** + * Refund recipient email address. + * + * @var string|null $email + */ + protected $email; + + /** + * Merchant unique identifier for the refund. + * + * @var string|null $refundStamp + */ + protected $refundStamp; + + /** + * Refund reference. + * + * @var string|null $refundReference + */ + protected $refundReference; + /** * Get the amount. * - * @return int + * @return int|null */ - public function getAmount() : int + public function getAmount(): ?int { return $this->amount; } @@ -106,14 +124,13 @@ public function getAmount() : int /** * Set the amount. * - * @param int $amount + * @param int|null $amount * * @return RefundRequest Return self to enable chaining. */ - public function setAmount(?int $amount) : RefundRequest + public function setAmount(?int $amount): RefundRequest { $this->amount = $amount; - return $this; } @@ -122,7 +139,7 @@ public function setAmount(?int $amount) : RefundRequest * * @return RefundItem[] */ - public function getItems() : array + public function getItems(): array { return $this->items ?? []; } @@ -134,19 +151,18 @@ public function getItems() : array * * @return RefundRequest Return self to enable chaining. */ - public function setItems(?array $items) : RefundRequest + public function setItems(?array $items): RefundRequest { $this->items = $items; - return $this; } /** * Get the callback urls. * - * @return CallbackUrl + * @return CallbackUrl|null */ - public function getCallbackUrls() : CallbackUrl + public function getCallbackUrls(): ?CallbackUrl { return $this->callbackUrls; } @@ -154,14 +170,79 @@ public function getCallbackUrls() : CallbackUrl /** * Set the callback urls. * - * @param CallbackUrl $callbackUrls The callback url instance holding success and cancel urls. + * @param CallbackUrl|null $callbackUrls The callback url instance holding success and cancel urls. * * @return RefundRequest Return self to enable chaining. */ - public function setCallbackUrls(?CallbackUrl $callbackUrls) : RefundRequest + public function setCallbackUrls(?CallbackUrl $callbackUrls): RefundRequest { $this->callbackUrls = $callbackUrls; + return $this; + } + + /** + * Get customer email. + * + * @return string|null + */ + public function getEmail(): ?string + { + return $this->email; + } + + /** + * Set customer email + * + * @param string|null $email + * @return RefundRequest + */ + public function setEmail(?string $email): RefundRequest + { + $this->email = $email; + return $this; + } + + /** + * Get refund stamp. + * + * @return string|null + */ + public function getRefundStamp(): ?string + { + return $this->refundStamp; + } + + /** + * Set refund stamp. + * + * @param string|null $refundStamp + * @return RefundRequest + */ + public function setRefundStamp(?string $refundStamp): RefundRequest + { + $this->refundStamp = $refundStamp; + return $this; + } + + /** + * Get refund reference. + * + * @return string|null + */ + public function getRefundReference(): ?string + { + return $this->refundReference; + } + /** + * Set refund reference. + * + * @param string|null $refundReference + * @return RefundRequest + */ + public function setRefundReference(?string $refundReference): RefundRequest + { + $this->refundReference = $refundReference; return $this; } } diff --git a/src/Request/ReportBySettlementRequest.php b/src/Request/ReportBySettlementRequest.php new file mode 100644 index 0000000..3a6645e --- /dev/null +++ b/src/Request/ReportBySettlementRequest.php @@ -0,0 +1,91 @@ +requestType = $requestType; + return $this; + } + + /** + * Set callback url. + * + * @param string $callbackUrl + * @return $this + */ + public function setCallbackUrl(string $callbackUrl): self + { + $this->callbackUrl = $callbackUrl; + return $this; + } + + /** + * Set report fields. + * + * @param string[] $reportFields + * @return $this + */ + public function setReportFields(array $reportFields): self + { + $this->reportFields = $reportFields; + return $this; + } + + /** + * Set submerchant. + * + * @param int $subMerchant + * @return $this + */ + public function setSubMerchant(int $subMerchant): self + { + $this->subMerchant = $subMerchant; + return $this; + } + + public function jsonSerialize(): array + { + $dataArray = json_encode(get_object_vars($this)); + return array_filter(json_decode($dataArray, true)); + } +} diff --git a/src/Request/ReportRequest.php b/src/Request/ReportRequest.php new file mode 100644 index 0000000..0a7c216 --- /dev/null +++ b/src/Request/ReportRequest.php @@ -0,0 +1,181 @@ + 50000) { + throw new ValidationException('Limit exceeds maximum value of 50000'); + } + + if ($props['limit'] < 0) { + throw new ValidationException('Limit must have a minimum value of 0'); + } + + if ($props['reportFields'] && !is_array($props['reportFields'])) { + throw new ValidationException('ReportFields must be type of array'); + } + + if (!empty($props['startDate'])) { + if (!preg_match('/^\d{4}(-\d{2}){2}T\d{2}(:\d{2}){2}(\.\d+)?\+\d{2}:\d{2}/', $props['startDate'])) { + throw new ValidationException('startDate must be in ATOM, ISO8601 or RFC3339 format'); + } + } + + if (!empty($props['endDate'])) { + if (!preg_match('/^\d{4}(-\d{2}){2}T\d{2}(:\d{2}){2}(\.\d+)?\+\d{2}:\d{2}/', $props['endDate'])) { + throw new ValidationException('endDate must be in DateTimeInterface::ATOM, ISO8601 or RFC3339 format'); + } + } + + if (!empty($props['startDate']) && !empty($props['endDate'])) { + if (substr($props['startDate'], 0, 10) > substr($props['endDate'], 0, 10)) { + throw new ValidationException('startDate cannot be lower than endDate'); + } + } + + return true; + } + + /** + * Set request type. + * + * @param string $requestType + * @return $this + */ + public function setRequestType(string $requestType): self + { + $this->requestType = $requestType; + return $this; + } + + /** + * Set callback url. + * + * @param string $callbackUrl + * @return $this + */ + public function setCallbackUrl(string $callbackUrl): self + { + $this->callbackUrl = $callbackUrl; + return $this; + } + + /** + * Set payment statuses. + * + * @param string $paymentStatus + * @return $this + */ + public function setPaymentStatus(string $paymentStatus): self + { + $this->paymentStatus = $paymentStatus; + return $this; + } + + /** + * Set start date. + * + * @param string $startDate Start date as ISO format. + * @return $this + */ + public function setStartDate(string $startDate): self + { + $this->startDate = $startDate; + return $this; + } + + /** + * Set end date. + * + * @param string $endDate End date as ISO format. + * @return $this + */ + public function setEndDate(string $endDate): self + { + $this->endDate = $endDate; + return $this; + } + + /** + * Set limit. + * + * @param int $limit + * @return $this + */ + public function setLimit(int $limit): self + { + $this->limit = $limit; + return $this; + } + + /** + * Set report fields. + * + * @param string[] $reportFields + * @return $this + */ + public function setReportFields(array $reportFields): self + { + $this->reportFields = $reportFields; + return $this; + } + + /** + * Set submerchant. + * + * @param int $subMerchant + * @return $this + */ + public function setSubMerchant(int $subMerchant): self + { + $this->subMerchant = $subMerchant; + return $this; + } + + public function jsonSerialize(): array + { + $dataArray = json_encode(get_object_vars($this)); + return array_filter(json_decode($dataArray, true)); + } +} diff --git a/src/Request/RevertPaymentAuthHoldRequest.php b/src/Request/RevertPaymentAuthHoldRequest.php index 46518c5..4ce275f 100644 --- a/src/Request/RevertPaymentAuthHoldRequest.php +++ b/src/Request/RevertPaymentAuthHoldRequest.php @@ -1,4 +1,5 @@ createFromFormat('Y-m-d', $props['startDate'])) { + throw new ValidationException('startDate must be in Y-m-d format'); + } + } + + if (!empty($props['endDate'])) { + if (!(new \DateTime())->createFromFormat('Y-m-d', $props['endDate'])) { + throw new ValidationException('endDate must be in Y-m-d format'); + } + } + + if (!empty($props['startDate']) && !empty($props['endDate'])) { + if ( + (new \DateTime())->createFromFormat('Y-m-d', $props['startDate']) + > (new \DateTime())->createFromFormat('Y-m-d', $props['endDate']) + ) { + throw new ValidationException('startDate cannot be lower than endDate'); + } + } + + if ($props['limit'] < 0) { + throw new ValidationException('Limit must have a minimum value of 0'); + } + + return true; + } + + /** + * Set start date. + * + * @param string|null $startDate Start date as ISO format. + * @return $this + */ + public function setStartDate(?string $startDate): self + { + $this->startDate = $startDate; + return $this; + } + + /** + * Set end date. + * + * @param string|null $endDate End date as ISO format. + * @return $this + */ + public function setEndDate(?string $endDate): self + { + $this->endDate = $endDate; + return $this; + } + + /** + * Set the reference. + * + * @param string $reference + * + * @return $this + */ + public function setReference(?string $reference): self + { + $this->reference = $reference; + + return $this; + } + + /** + * Set limit. + * + * @param int $limit + * @return $this + */ + public function setLimit(int $limit): self + { + $this->limit = $limit; + return $this; + } + + /** + * Set submerchant. + * + * @param int $subMerchant + * @return $this + */ + public function setSubMerchant(int $subMerchant): self + { + $this->subMerchant = $subMerchant; + return $this; + } + + public function jsonSerialize(): array + { + $dataArray = json_encode(get_object_vars($this)); + return array_filter(json_decode($dataArray, true)); + } +} diff --git a/src/Request/ShopInShopPaymentRequest.php b/src/Request/ShopInShopPaymentRequest.php index 63060ce..7b63e3a 100644 --- a/src/Request/ShopInShopPaymentRequest.php +++ b/src/Request/ShopInShopPaymentRequest.php @@ -1,37 +1,39 @@ items, function (Item $item) { - $item->validateShopInShop(); - }); +/** + * Class PaymentRequest + * + * This class is used to create a payment request object for + * the Paytrail\SDK\Client class. + * + * @see https://Paytrail.github.io/api-documentation/#/?id=create-request-body + * @package Paytrail\SDK\Request + */ +class ShopInShopPaymentRequest extends PaymentRequest +{ + /** + * Validates properties and throws an exception for invalid values + * + * @throws ValidationException + */ + public function validate() + { + parent::validate(); - return true; - } - } + // Validate the shop-in-shop items. + array_walk($this->items, function (Item $item) { + $item->validateShopInShop(); + }); + + return true; + } +} diff --git a/src/Response/CitPaymentResponse.php b/src/Response/CitPaymentResponse.php index 9fba630..0d19bea 100644 --- a/src/Response/CitPaymentResponse.php +++ b/src/Response/CitPaymentResponse.php @@ -1,10 +1,11 @@ transactionId = $transactionId; - return $this; } @@ -53,7 +53,7 @@ public function getTransactionId(): ?string } /** - * @param string $threeDSecureUrl + * @param string|null $threeDSecureUrl * @return CitPaymentResponse */ public function setThreeDSecureUrl(?string $threeDSecureUrl): CitPaymentResponse diff --git a/src/Response/CurlResponse.php b/src/Response/CurlResponse.php index cb44278..b3f8e95 100644 --- a/src/Response/CurlResponse.php +++ b/src/Response/CurlResponse.php @@ -60,8 +60,8 @@ private function setHeaders(string $headers): void continue; } [$key, $value] = explode(': ', $header); - $responseHeaders[$key] = [rtrim($value)]; + $responseHeaders[strtolower($key)] = [rtrim($value)]; } $this->headers = $responseHeaders; } -} \ No newline at end of file +} diff --git a/src/Response/EmailRefundResponse.php b/src/Response/EmailRefundResponse.php index 92c991e..98a3a09 100644 --- a/src/Response/EmailRefundResponse.php +++ b/src/Response/EmailRefundResponse.php @@ -1,10 +1,11 @@ status; + } + + /** + * Set the status. + * + * @param string $status + * + * @return InvoiceActivationResponse Return self to enable chaining. + */ + public function setStatus(string $status): InvoiceActivationResponse + { + $this->status = $status; + return $this; + } +} diff --git a/src/Response/MitPaymentResponse.php b/src/Response/MitPaymentResponse.php index b611547..4c10c8c 100644 --- a/src/Response/MitPaymentResponse.php +++ b/src/Response/MitPaymentResponse.php @@ -1,10 +1,11 @@ transactionId = $transactionId; - return $this; } diff --git a/src/Response/PaymentResponse.php b/src/Response/PaymentResponse.php index 04ec97c..5ec4671 100644 --- a/src/Response/PaymentResponse.php +++ b/src/Response/PaymentResponse.php @@ -1,12 +1,10 @@ transactionId; } @@ -54,11 +72,11 @@ public function getTransactionId() : ?string /** * Set the transaction id. * - * @param string $transactionId + * @param string|null $transactionId * * @return PaymentResponse Return self to enable chaining. */ - public function setTransactionId(string $transactionId) : PaymentResponse + public function setTransactionId(?string $transactionId): PaymentResponse { $this->transactionId = $transactionId; @@ -68,9 +86,9 @@ public function setTransactionId(string $transactionId) : PaymentResponse /** * Get the href. * - * @return string + * @return string|null */ - public function getHref() : ?string + public function getHref(): ?string { return $this->href; } @@ -78,26 +96,88 @@ public function getHref() : ?string /** * Set the href. * - * @param string $href + * @param string|null $href * * @return PaymentResponse Return self to enable chaining. */ - public function setHref(string $href) : PaymentResponse + public function setHref(?string $href): PaymentResponse { $this->href = $href; return $this; } + /** + * @return string|null + */ + public function getTerms(): ?string + { + return $this->terms; + } + + /** + * @param string|null $terms + * @return PaymentResponse + */ + public function setTerms(?string $terms): PaymentResponse + { + $this->terms = $terms; + + return $this; + } + + /** + * @return PaymentMethodGroup[] + */ + public function getGroups(): array + { + return $this->groups; + } + + /** + * @param PaymentMethodGroup[]|array $groups + * @return PaymentResponse + */ + public function setGroups(array $groups): PaymentResponse + { + $this->groups = array_map(function ($group) { + if (! $group instanceof PaymentMethodGroup) { + return (new PaymentMethodGroup())->bindProperties($group); + } + + return $group; + }, $groups); + + return $this; + } + + /** + * @return string|null + */ + public function getReference(): ?string + { + return $this->reference; + } + + /** + * @param string|null $reference + * @return PaymentResponse + */ + public function setReference(?string $reference): PaymentResponse + { + $this->reference = $reference; + + return $this; + } + /** * Get providers. * * @return Provider[] */ - public function getProviders() : ?array + public function getProviders(): array { - - return $this->providers; + return $this->providers ?? []; } /** @@ -111,21 +191,15 @@ public function getProviders() : ?array * * @return PaymentResponse Return self to enable chaining. */ - public function setProviders(?array $providers) : PaymentResponse + public function setProviders(array $providers): PaymentResponse { - if (empty($providers)) { - return $this; - } - - array_walk($providers, function ($provider) { - if (! $provider instanceof Provider) { - $instance = new Provider(); - $instance->bindProperties($provider); - $this->providers[] = $instance; - } else { - $this->providers[] = $provider; + $this->providers = array_map(function ($provider) { + if (! $provider instanceof Provider) { + return (new Provider())->bindProperties($provider); } - }); + + return $provider; + }, $providers); return $this; } diff --git a/src/Response/PaymentStatusResponse.php b/src/Response/PaymentStatusResponse.php index 0dab874..0aa24c6 100644 --- a/src/Response/PaymentStatusResponse.php +++ b/src/Response/PaymentStatusResponse.php @@ -1,10 +1,11 @@ transactionId; @@ -116,7 +117,7 @@ public function getTransactionId(): string * @param string $transactionId * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setTransactionId(string $transactionId): PaymentStatusResponse { $this->transactionId = $transactionId; @@ -128,7 +129,7 @@ public function setTransactionId(string $transactionId): PaymentStatusResponse * Get the payment status. * * @return string - */ + */ public function getStatus(): ?string { return $this->status; @@ -137,15 +138,14 @@ public function getStatus(): ?string /** * Set the payment status. * - * @param string $status Possible values: new, ok, fail, + * @param string|null $status Possible values: new, ok, fail, * pending, or delayed * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setStatus(?string $status): PaymentStatusResponse { $this->status = $status; - return $this; } @@ -153,7 +153,7 @@ public function setStatus(?string $status): PaymentStatusResponse * Get the total amount of the payment. * * @return integer - */ + */ public function getAmount(): ?int { return $this->amount; @@ -161,16 +161,15 @@ public function getAmount(): ?int /** * Set the total amount of the payment in currency's minor units, - * eg. for Euros means cents. + * e.g. for Euros means cents. * - * @param integer $amount + * @param integer|null $amount * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setAmount(?int $amount): PaymentStatusResponse { $this->amount = $amount; - return $this; } @@ -178,7 +177,7 @@ public function setAmount(?int $amount): PaymentStatusResponse * Get currency. * * @return string - */ + */ public function getCurrency(): ?string { return $this->currency; @@ -187,14 +186,13 @@ public function getCurrency(): ?string /** * Set currency. * - * @param string $currency + * @param string|null $currency * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setCurrency(?string $currency): PaymentStatusResponse { $this->currency = $currency; - return $this; } @@ -202,7 +200,7 @@ public function setCurrency(?string $currency): PaymentStatusResponse * Get merchant unique identifier for the order. * * @return string - */ + */ public function getStamp(): ?string { return $this->stamp; @@ -211,14 +209,13 @@ public function getStamp(): ?string /** * Set merchant unique identifier for the order. * - * @param string $stamp + * @param string|null $stamp * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setStamp(?string $stamp): PaymentStatusResponse { $this->stamp = $stamp; - return $this; } @@ -226,8 +223,8 @@ public function setStamp(?string $stamp): PaymentStatusResponse * Get the order reference. * * @return string - */ - public function getReference() + */ + public function getReference(): string { return $this->reference; } @@ -235,14 +232,13 @@ public function getReference() /** * Set the order reference. * - * @param string $reference + * @param string|null $reference * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setReference(?string $reference): PaymentStatusResponse { $this->reference = $reference; - return $this; } @@ -250,7 +246,7 @@ public function setReference(?string $reference): PaymentStatusResponse * Get the transaction creation timestamp. * * @return string - */ + */ public function getCreatedAt(): ?string { return $this->createdAt; @@ -259,14 +255,13 @@ public function getCreatedAt(): ?string /** * Set the transaction creation timestamp. * - * @param string $createdAt + * @param string|null $createdAt * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setCreatedAt(?string $createdAt): PaymentStatusResponse { $this->createdAt = $createdAt; - return $this; } @@ -274,7 +269,7 @@ public function setCreatedAt(?string $createdAt): PaymentStatusResponse * Get payment API url. * * @return string - */ + */ public function getHref(): ?string { return $this->href; @@ -283,14 +278,13 @@ public function getHref(): ?string /** * Set payment API url. * - * @param string $href + * @param string|null $href * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setHref(?string $href): PaymentStatusResponse { $this->href = $href; - return $this; } @@ -298,7 +292,7 @@ public function setHref(?string $href): PaymentStatusResponse * Get provider name. * * @return string - */ + */ public function getProvider() { return $this->provider; @@ -307,14 +301,13 @@ public function getProvider() /** * Set provider name. * - * @param string $provider If processed, the name of the payment method provider + * @param string|null $provider If processed, the name of the payment method provider * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setProvider(?string $provider): PaymentStatusResponse { $this->provider = $provider; - return $this; } @@ -322,7 +315,7 @@ public function setProvider(?string $provider): PaymentStatusResponse * Get filing code. * * @return string - */ + */ public function getFilingCode(): ?string { return $this->filingCode; @@ -331,14 +324,13 @@ public function getFilingCode(): ?string /** * Set filing code. * - * @param string $filingCode + * @param string|null $filingCode * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setFilingCode(?string $filingCode): PaymentStatusResponse { $this->filingCode = $filingCode; - return $this; } @@ -346,7 +338,7 @@ public function setFilingCode(?string $filingCode): PaymentStatusResponse * Get timestamp when the transaction was paid * * @return string - */ + */ public function getPaidAt(): ?string { return $this->paidAt; @@ -355,14 +347,13 @@ public function getPaidAt(): ?string /** * Set timestamp when the transaction was paid * - * @param string $paidAt + * @param string|null $paidAt * * @return PaymentStatusResponse Return self to enable chaining. - */ + */ public function setPaidAt(?string $paidAt): PaymentStatusResponse { $this->paidAt = $paidAt; - return $this; } } diff --git a/src/Response/RefundResponse.php b/src/Response/RefundResponse.php index 82d0ce4..b7e9512 100644 --- a/src/Response/RefundResponse.php +++ b/src/Response/RefundResponse.php @@ -1,10 +1,11 @@ provider; } /** * Set the provider. * - * @param string $provider + * @param string|null $provider * * @return RefundResponse Return self to enable chaining. */ public function setProvider(?string $provider): RefundResponse { - $this->provider = $provider; return $this; @@ -71,20 +69,18 @@ public function setProvider(?string $provider): RefundResponse */ public function getStatus(): string { - return $this->status; } /** * Set the status. * - * @param string $status + * @param string|null $status * * @return RefundResponse Return self to enable chaining. */ public function setStatus(?string $status): RefundResponse { - $this->status = $status; return $this; @@ -97,20 +93,18 @@ public function setStatus(?string $status): RefundResponse */ public function getTransactionId(): string { - return $this->transactionId; } /** * Set the transactionId. * - * @param string $transactionId + * @param string|null $transactionId * * @return RefundResponse Return self to enable chaining. */ public function setTransactionId(?string $transactionId): RefundResponse { - $this->transactionId = $transactionId; return $this; diff --git a/src/Response/ReportRequestResponse.php b/src/Response/ReportRequestResponse.php new file mode 100644 index 0000000..8290a4f --- /dev/null +++ b/src/Response/ReportRequestResponse.php @@ -0,0 +1,52 @@ +requestId = $requestId; + + return $this; + } + + /** + * Get the request id. + * + * @return string + */ + public function getRequestId(): ?string + { + return $this->requestId; + } +} diff --git a/src/Response/RevertPaymentAuthHoldResponse.php b/src/Response/RevertPaymentAuthHoldResponse.php index ecb37ba..9c60c59 100644 --- a/src/Response/RevertPaymentAuthHoldResponse.php +++ b/src/Response/RevertPaymentAuthHoldResponse.php @@ -1,10 +1,11 @@ transactionId = $transactionId; - return $this; } @@ -44,7 +44,7 @@ public function setTransactionId(string $transactionId): RevertPaymentAuthHoldRe * * @return string */ - public function getTransactionId(): string + public function getTransactionId(): ?string { return $this->transactionId; } diff --git a/src/Response/SettlementResponse.php b/src/Response/SettlementResponse.php index 1d7d064..9b24053 100644 --- a/src/Response/SettlementResponse.php +++ b/src/Response/SettlementResponse.php @@ -1,4 +1,5 @@ baseUrl . $uri); + curl_setopt($curl, CURLOPT_URL, $this->buildUrl($uri, $options)); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, true); @@ -47,12 +48,30 @@ public function request(string $method, string $uri, array $options) $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); $headers = rtrim(substr($response, 0, $header_size)); $body = substr($response, $header_size); + curl_close($curl); - $curlResponse = new CurlResponse($headers, $body, $statusCode); + if ($statusCode == 400) { + throw new ClientException($body, $statusCode); + } - curl_close($curl); + return new CurlResponse($headers, $body, $statusCode); + } + + /** + * Build URL by prefixing endpoint with base URL and possible query parameters. + * + * @param string $uri + * @param array $options + * @return string + */ + private function buildUrl(string $uri, array $options): string + { + $query = ''; + if (isset($options['query'])) { + $uri .= '?' . http_build_query($options['query']); + } - return $curlResponse; + return $this->baseUrl . $uri . $query; } /** @@ -65,7 +84,7 @@ private function parseHeaders($options): array $headers = $options['headers'] ?? []; $result = []; foreach ($headers as $key => $value) { - $result[] = $key .': ' . $value; + $result[] = $key . ': ' . $value; } return $result; @@ -82,6 +101,6 @@ private function formatBody($body): string if (!is_array($body)) { return $body; } - return http_build_query($body,'','&'); + return http_build_query($body, '', '&'); } -} \ No newline at end of file +} diff --git a/src/Util/JsonSerializable.php b/src/Util/JsonSerializable.php index 1e77d55..eb5c92b 100644 --- a/src/Util/JsonSerializable.php +++ b/src/Util/JsonSerializable.php @@ -1,18 +1,15 @@ getMessage()); if ($exception->hasResponse()) { $responseBody = $exception->getResponse()->getBody()->getContents(); - $clientException->SetResponseBody($responseBody); + $clientException->setResponseBody($responseBody); $clientException->setResponseCode($exception->getCode()); } throw $clientException; } catch (GuzzleConnectException $exception) { throw new RequestException($exception->getMessage()); - } - catch (GuzzleRequestException $exception) { + } catch (GuzzleRequestException $exception) { throw new RequestException($exception->getMessage()); } } @@ -70,8 +70,7 @@ private function createClient(): void 'timeout' => Client::DEFAULT_TIMEOUT, ] ); - } - else { + } else { $this->client = new CurlClient(Client::API_ENDPOINT, Client::DEFAULT_TIMEOUT); } } diff --git a/src/Util/Signature.php b/src/Util/Signature.php index f067665..f34e578 100644 --- a/src/Util/Signature.php +++ b/src/Util/Signature.php @@ -1,10 +1,11 @@ $params HTTP headers in an associative array. * @param string $body HTTP request body, empty string for GET requests * @param string $secretKey The merchant secret key. + * * @return string SHA-256 HMAC */ public static function calculateHmac(array $params = [], string $body = '', string $secretKey = '') diff --git a/tests/ClientTest.php b/tests/ClientTest.php index fc05b0a..098d302 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -1,4 +1,5 @@ client = new Client(self::MERCHANT_ID, self::SECRET, self::COF_PLUGIN_VERSION); + parent::setUp(); $this->item = (new Item()) - ->setDeliveryDate('2020-12-12') ->setProductCode('pr1') ->setVatPercentage(24) ->setReference('itemReference123') - ->setStamp('itemStamp-' . rand(1, 999999)) + ->setStamp('itemStamp-1' . rand(1, 999999)) ->setUnits(1) ->setDescription('some description') ->setUnitPrice(100); @@ -78,7 +58,7 @@ protected function setUp(): void ->setProductCode('pr2') ->setVatPercentage(24) ->setReference('itemReference123') - ->setStamp('itemStamp-' . rand(1, 999999)) + ->setStamp('itemStamp-2' . rand(1, 999999)) ->setUnits(2) ->setDescription('some description2') ->setUnitPrice(200); @@ -171,93 +151,41 @@ protected function setUp(): void public function testPaymentRequest() { - $client = $this->client; - $paymentRequest = $this->paymentRequest; - - $transactionId = ''; - - if ($paymentRequest->validate()) { - try { - $response = $client->createPayment($paymentRequest); - - $this->assertObjectHasAttribute('transactionId', $response); - $this->assertObjectHasAttribute('href', $response); - $this->assertObjectHasAttribute('providers', $response); - $this->assertIsArray($response->getProviders()); + $response = $this->createPayment($this->paymentRequest); + $this->assertPaymentResponseIsValid($response); - $transactionId = $response->getTransactionId(); - - } catch (HmacException $e) { - var_dump($e->getMessage()); - } catch (ValidationException $e) { - var_dump($e->getMessage()); - } catch (RequestException $e) { - var_dump(json_decode($e->getResponse()->getBody())); - } - - } else { - echo 'PaymentRequest is not valid'; - } + $transactionId = $response->getTransactionId(); // Test payment status request with the transactionId we got from the PaymentRequest $psr = new PaymentStatusRequest(); $psr->setTransactionId($transactionId); - $client = new Client(self::MERCHANT_ID, self::SECRET, self::COF_PLUGIN_VERSION); - try { - $res = $client->getPaymentStatus($psr); + $res = $this->client->getPaymentStatus($psr); $this->assertEquals('new', $res->getStatus()); - $this->assertEquals($res->getTransactionId(), $transactionId); - } catch (HmacException $e) { - var_dump('hmac error'); - } catch (ValidationException $e) { - var_dump('validation error'); + $this->assertEquals($transactionId, $res->getTransactionId()); + } catch (HmacException | ValidationException $e) { + $this->fail($e->getMessage()); } } public function testShopInShopPaymentRequest() { - $client = new Client(self::SHOP_IN_SHOP_AGGREGATE_MERCHANT_ID, self::SHOP_IN_SHOP_SECRET, self::COF_PLUGIN_VERSION); - $paymentRequest = $this->shopInShopPaymentRequest; - - $transactionId = ''; - - if ($paymentRequest->validate()) { - try { - $response = $client->createShopInShopPayment($paymentRequest); - - $this->assertObjectHasAttribute('transactionId', $response); - $this->assertObjectHasAttribute('href', $response); - $this->assertObjectHasAttribute('providers', $response); - $this->assertIsArray($response->getProviders()); - - $transactionId = $response->getTransactionId(); + $response = $this->createShopInShopPayment($this->shopInShopPaymentRequest); + $this->assertPaymentResponseIsValid($response); - } catch (HmacException $e) { - var_dump($e->getMessage()); - } catch (ValidationException $e) { - var_dump($e->getMessage()); - } catch (RequestException $e) { - var_dump(json_decode($e->getResponse()->getBody())); - } - - } else { - echo 'ShopInShopPaymentRequest is not valid'; - } + $transactionId = $response->getTransactionId(); // Test payment status request with the transactionId we got from the PaymentRequest $psr = new PaymentStatusRequest(); $psr->setTransactionId($transactionId); try { - $res = $client->getPaymentStatus($psr); + $res = $this->sisClient->getPaymentStatus($psr); $this->assertEquals('new', $res->getStatus()); - $this->assertEquals($res->getTransactionId(), $transactionId); - } catch (HmacException $e) { - var_dump('hmac error'); - } catch (ValidationException $e) { - var_dump('validation error'); + $this->assertEquals($transactionId, $res->getTransactionId()); + } catch (HmacException | ValidationException $e) { + $this->fail($e->getMessage()); } } @@ -321,9 +249,9 @@ public function testGetTokenRequest() ] ]; - $this->assertObjectHasAttribute('token', $response); - $this->assertObjectHasAttribute('card', $response); - $this->assertObjectHasAttribute('customer', $response); + $this->assertNotEmpty($response->getToken()); + $this->assertNotEmpty($response->getCard()); + $this->assertNotEmpty($response->getCustomer()); $this->assertJsonStringEqualsJsonString(json_encode($expectedArray), json_encode($responseJsonData)); } @@ -338,7 +266,7 @@ public function testCitPaymentRequestCharge() $response = $client->createCitPaymentCharge($citPaymentRequest); - $this->assertObjectHasAttribute('transactionId', $response); + $this->assertNotEmpty($response->getTransactionId()); $transactionId = $response->getTransactionId(); @@ -364,7 +292,7 @@ public function testMitPaymentRequestCharge() $response = $client->createMitPaymentCharge($mitPaymentRequest); - $this->assertObjectHasAttribute('transactionId', $response); + $this->assertNotEmpty($response->getTransactionId()); $transactionId = $response->getTransactionId(); @@ -390,8 +318,8 @@ public function testCitPaymentRequestCharge3DS() $response = $client->createCitPaymentCharge($citPaymentRequest); - $this->assertObjectHasAttribute('transactionId', $response); - $this->assertObjectHasAttribute('threeDSecureUrl', $response); + $this->assertNotEmpty($response->getTransactionId()); + $this->assertNotEmpty($response->getThreeDSecureUrl()); } public function testCitPaymentRequestAuthorizationHold() @@ -405,7 +333,7 @@ public function testCitPaymentRequestAuthorizationHold() $response = $client->createCitPaymentAuthorizationHold($citPaymentRequest); - $this->assertObjectHasAttribute('transactionId', $response); + $this->assertNotEmpty($response->getTransactionId()); $transactionId = $response->getTransactionId(); @@ -431,7 +359,7 @@ public function testMitPaymentRequestAuthorizationHold() $response = $client->createMitPaymentAuthorizationHold($mitPaymentRequest); - $this->assertObjectHasAttribute('transactionId', $response); + $this->assertNotEmpty($response->getTransactionId()); $transactionId = $response->getTransactionId(); @@ -457,8 +385,8 @@ public function testCitPaymentRequestAuthorizationHold3DS() $response = $client->createCitPaymentAuthorizationHold($citPaymentRequest); - $this->assertObjectHasAttribute('transactionId', $response); - $this->assertObjectHasAttribute('threeDSecureUrl', $response); + $this->assertNotEmpty($response->getTransactionId()); + $this->assertNotEmpty($response->getThreeDSecureUrl()); } public function testCitPaymentRequestCommit() @@ -472,7 +400,7 @@ public function testCitPaymentRequestCommit() $this->assertTrue($citPaymentRequest->validate()); $response = $client->createCitPaymentCommit($citPaymentRequest, $transactionId); - $this->assertObjectHasAttribute('transactionId', $response); + $this->assertNotEmpty($response->getTransactionId()); } public function testMitPaymentRequestCommit() @@ -486,7 +414,7 @@ public function testMitPaymentRequestCommit() $this->assertTrue($mitPaymentRequest->validate()); $response = $client->createMitPaymentCommit($mitPaymentRequest, $transactionId); - $this->assertObjectHasAttribute('transactionId', $response); + $this->assertNotEmpty($response->getTransactionId()); } public function testRevertCitPaymentAuthorizationHold() @@ -500,7 +428,7 @@ public function testRevertCitPaymentAuthorizationHold() // Create new CitPaymentAuthorizationHold $response = $client->createCitPaymentAuthorizationHold($citPaymentRequest); - $this->assertObjectHasAttribute('transactionId', $response); + $this->assertNotEmpty($response->getTransactionId()); $transactionId = $response->getTransactionId(); @@ -511,7 +439,7 @@ public function testRevertCitPaymentAuthorizationHold() $this->assertTrue($revertCitPaymentAuthHoldRequest->validate()); $revertResponse = $client->revertPaymentAuthorizationHold($revertCitPaymentAuthHoldRequest); - $this->assertObjectHasAttribute('transactionId', $revertResponse); + $this->assertNotEmpty($revertResponse->getTransactionId()); } public function testRevertMitPaymentAuthorizationHold() @@ -525,7 +453,7 @@ public function testRevertMitPaymentAuthorizationHold() // Create new CitPaymentAuthorizationHold $response = $client->createMitPaymentAuthorizationHold($mitPaymentRequest); - $this->assertObjectHasAttribute('transactionId', $response); + $this->assertNotEmpty($response->getTransactionId()); $transactionId = $response->getTransactionId(); @@ -536,7 +464,7 @@ public function testRevertMitPaymentAuthorizationHold() $this->assertTrue($revertCitPaymentAuthHoldRequest->validate()); $revertResponse = $client->revertPaymentAuthorizationHold($revertCitPaymentAuthHoldRequest); - $this->assertObjectHasAttribute('transactionId', $revertResponse); + $this->assertNotEmpty($revertResponse->getTransactionId()); } public function testRevertCitPaymentAuthorizationHoldException() @@ -557,9 +485,128 @@ public function testRevertCitPaymentAuthorizationHoldException() } } - public function testGetSettlementsWithInvalidDateThrowsException() + public function testRequestSettlementsWithInvalidDateThrowsException() + { + $settlementRequest = (new SettlementRequest())->setStartDate('30.5.2022'); + $this->expectException(ValidationException::class); + $this->client->requestSettlements($settlementRequest); + } + + public function testRequestSettlementsReturnsValidResponse() + { + $settlementRequest = (new SettlementRequest()); + $settlementResponse = $this->client->requestSettlements($settlementRequest); + $this->assertIsArray($settlementResponse->getSettlements()); + } + + public function testGetSettlementsReturnsValidResponse() + { + $settlementRequest = new SettlementRequest(); + $settlementResponse = $this->client->requestSettlements($settlementRequest); + $this->assertIsArray($settlementResponse->getSettlements()); + } + + public function testGetGroupedPaymentProvidersAcceptsLanguageParameters() + { + $providers = $this->client->getGroupedPaymentProviders(100, 'EN'); + $this->assertIsArray($providers); + $this->assertEquals('Mobile payment methods', $providers['groups'][0]['name']); + } + + public function testRequestPaymentReportReturnsRequestId() + { + $reportRequest = (new ReportRequest()) + ->setRequestType('json') + ->setCallbackUrl('https://nourl.test'); + $response = $this->client->requestPaymentReport($reportRequest); + + $this->assertNotNull($response->getRequestId()); + $this->assertNotEmpty($response->getRequestId()); + } + + public function testRequestPaymentReportThrowsExceptionWhenRequestTypeIsEmpty() + { + $this->expectException(ValidationException::class); + $reportRequest = (new ReportRequest()) + ->setCallbackUrl('https://nourl.test'); + $this->client->requestPaymentReport($reportRequest); + } + + public function testRequestPaymentReportThrowsExceptionWhenCallbackUrlIsEmpty() + { + $this->expectException(ValidationException::class); + $reportRequest = (new ReportRequest()) + ->setRequestType('json'); + $this->client->requestPaymentReport($reportRequest); + } + + public function testRequestPaymentReportThrowsExceptionWithInvalidPaymentStatus() + { + $this->expectException(ValidationException::class); + $reportRequest = (new ReportRequest()) + ->setRequestType('json') + ->setCallbackUrl('https://nourl.test') + ->setPaymentStatus('Foobar'); + $this->client->requestPaymentReport($reportRequest); + } + + public function testRequestPaymentReportThrowsExceptionWhenLimitExceeds() + { + $this->expectException(ValidationException::class); + $reportRequest = (new ReportRequest()) + ->setRequestType('json') + ->setCallbackUrl('https://nourl.test') + ->setLimit(99999999); + $this->client->requestPaymentReport($reportRequest); + } + + public function testRequestPaymentReportThrowsExceptionWhenLimitIsNegative() + { + $this->expectException(ValidationException::class); + $reportRequest = (new ReportRequest()) + ->setRequestType('json') + ->setCallbackUrl('https://nourl.test') + ->setLimit(-500); + $this->client->requestPaymentReport($reportRequest); + } + + public function testRequestPaymentReportThrowsExceptionWhenUrlInvalid() + { + $this->expectException(ClientException::class); + $reportRequest = (new ReportRequest()) + ->setRequestType('json') + ->setCallbackUrl('invalid-url'); + $this->client->requestPaymentReport($reportRequest); + } + + public function testRequestPaymentReportThrowsExceptionWhenEndDateIsLowerThanStartDate() + { + $this->expectException(ValidationException::class); + $reportRequest = (new ReportRequest()) + ->setRequestType('json') + ->setCallbackUrl('https://nourl.test') + ->setStartDate('2023-01-20T12:00:00+02:00') + ->setEndDate('2023-01-01T23:59:50+02:00'); + $this->client->requestPaymentReport($reportRequest); + } + + public function testRequestPaymentReportThrowsExceptionWhenStartDateIsInWrongFormat() + { + $this->expectException(ValidationException::class); + $reportRequest = (new ReportRequest()) + ->setRequestType('json') + ->setCallbackUrl('https://nourl.test') + ->setStartDate('1.1.2023'); + $this->client->requestPaymentReport($reportRequest); + } + + public function testRequestPaymentReportThrowsExceptionWhenEndDateIsInWrongFormat() { $this->expectException(ValidationException::class); - $this->client->getSettlements('30.5.2022'); + $reportRequest = (new ReportRequest()) + ->setRequestType('json') + ->setCallbackUrl('https://nourl.test') + ->setEndDate('1.1.2023'); + $this->client->requestPaymentReport($reportRequest); } } diff --git a/tests/Model/AbstractPaymentRequestTest.php b/tests/Model/AbstractPaymentRequestTest.php index b2e8d03..1d3a357 100644 --- a/tests/Model/AbstractPaymentRequestTest.php +++ b/tests/Model/AbstractPaymentRequestTest.php @@ -1,4 +1,5 @@ getMockForAbstractClass(AbstractPaymentRequest::class); @@ -90,15 +90,18 @@ public function testValidationExceptionMessages(): void } try { - $paymentRequest->setCustomer(new Customer); + $paymentRequest->setCustomer(new Customer()); $paymentRequest->validate(); } catch (Exception $e) { $this->assertEquals('RedirectUrls is empty', $e->getMessage()); } } - private function setProtectedProperty(AbstractPaymentRequest $paymentRequest, string $propertyName, string $value): void - { + private function setProtectedProperty( + AbstractPaymentRequest $paymentRequest, + string $propertyName, + string $value + ): void { $attribute = new ReflectionProperty($paymentRequest, $propertyName); $attribute->setAccessible(true); $attribute->setValue($paymentRequest, $value); @@ -107,14 +110,14 @@ private function setProtectedProperty(AbstractPaymentRequest $paymentRequest, st private function getPaymentItems(): array { return [ - (new Item) + (new Item()) ->setStamp('someStamp') ->setDeliveryDate('12.12.2020') ->setProductCode('pr1') ->setVatPercentage(25) ->setUnitPrice(10) ->setUnits(1), - (new Item) + (new Item()) ->setStamp('someOtherStamp') ->setDeliveryDate('12.12.2020') ->setProductCode('pr2') @@ -123,5 +126,4 @@ private function getPaymentItems(): array ->setUnits(2), ]; } - -} \ No newline at end of file +} diff --git a/tests/Model/AddressTest.php b/tests/Model/AddressTest.php index 9f32af8..6ef501b 100644 --- a/tests/Model/AddressTest.php +++ b/tests/Model/AddressTest.php @@ -1,4 +1,5 @@ expectException(ValidationException::class); - $a = new Address; + $a = new Address(); $a->validate(); } public function testIsAddressValid() { - $a = new Address; + $a = new Address(); $this->assertInstanceOf( Address::class, @@ -40,7 +40,7 @@ public function testIsAddressValid() public function testExeceptionMessages() { - $a = new Address; + $a = new Address(); try { $a->validate(); @@ -86,5 +86,4 @@ public function testSetStreetAddressAcceptsNull() $addressModel->setStreetAddress(null); $this->assertNull($addressModel->getStreetAddress()); } - -} \ No newline at end of file +} diff --git a/tests/Model/CallbackUrlTest.php b/tests/Model/CallbackUrlTest.php index b38a886..9137447 100644 --- a/tests/Model/CallbackUrlTest.php +++ b/tests/Model/CallbackUrlTest.php @@ -1,4 +1,5 @@ expectException(ValidationException::class); - $a = new CallbackUrl; + $a = new CallbackUrl(); $a->validate(); } public function testIsCallbackUrlValid() { - $c = new CallbackUrl; + $c = new CallbackUrl(); $this->assertInstanceOf(CallbackUrl::class, $c); @@ -28,14 +29,12 @@ public function testIsCallbackUrlValid() try { $this->assertIsBool($c->validate(), 'CallbackUrl::validate is bool'); } catch (ValidationException $e) { - } - } public function testExceptionMessages() { - $c = new CallbackUrl; + $c = new CallbackUrl(); try { $c->validate(); @@ -57,8 +56,5 @@ public function testExceptionMessages() $this->assertIsBool($c->validate(), 'CallbackUrl::validate is bool'); } catch (ValidationException $e) { } - - } - -} \ No newline at end of file +} diff --git a/tests/Model/CommissionTest.php b/tests/Model/CommissionTest.php index a321962..a47db80 100644 --- a/tests/Model/CommissionTest.php +++ b/tests/Model/CommissionTest.php @@ -1,4 +1,5 @@ setMerchant('123456'); $commission->validate(); } - -} +} diff --git a/tests/Model/CustomerTest.php b/tests/Model/CustomerTest.php index 673b1eb..7790644 100644 --- a/tests/Model/CustomerTest.php +++ b/tests/Model/CustomerTest.php @@ -1,4 +1,5 @@ setEmail('notAnEmailAddress'); $c2->validate(); } - -} \ No newline at end of file +} diff --git a/tests/Model/ItemTest.php b/tests/Model/ItemTest.php index 4b09ec8..b544c34 100644 --- a/tests/Model/ItemTest.php +++ b/tests/Model/ItemTest.php @@ -1,4 +1,5 @@ assertInstanceOf( - Item::class, - $i - ); - - $i->setUnitPrice(1) + $item = (new Item())->setUnitPrice(1) ->setUnits(2) + ->setStamp('thisIsStamp') ->setVatPercentage(0) ->setProductCode('productCode123') - ->setDeliveryDate('12.12.1999') + ->setDeliveryDate('2023-01-01') ->setDescription('description'); - $this->assertEquals(true, $i->validate()); + $this->assertTrue($item->validate()); } - public function testExceptions() + public function testItemWithoutUnitPriceThrowsError() { $this->expectException(ValidationException::class); - $i = new Item; - $i->validate(); + (new Item())->setUnits(2) + ->setStamp('thisIsStamp') + ->setVatPercentage(0) + ->setProductCode('productCode123') + ->setDescription('description') + ->validate(); } - public function testExceptionMessages() + public function testItemWithoutUnitsTrowsError() { - $i = new Item; - - try { - $i->validate(); - } catch (\Exception $e) { - $this->assertStringContainsString('UnitPrice is not an integer', $e->getMessage()); - } - - try { - $i->setUnitPrice(-10); - $i->validate(); - } catch (\Exception $e) { - $this->assertStringContainsString('UnitPrice can\'t be a negative number', $e->getMessage()); - } + $this->expectException(ValidationException::class); + (new Item())->setUnitPrice(1) + ->setStamp('thisIsStamp') + ->setVatPercentage(0) + ->setProductCode('productCode123') + ->setDescription('description') + ->validate(); + } - try { - $i->setUnitPrice(2); - $i->validate(); - } catch (\Exception $e) { - $this->assertStringContainsString('Units is not an integer', $e->getMessage()); - } + public function testItemWithNegativeUnitsThrowsError() + { + $this->expectException(ValidationException::class); + (new Item())->setUnitPrice(1) + ->setUnits(-1) + ->setStamp('thisIsStamp') + ->setVatPercentage(0) + ->setProductCode('productCode123') + ->setDescription('description') + ->validate(); + } - try { - $i->setUnits(3); - $i->validate(); - } catch (ValidationException $e) { - $this->assertStringContainsString('vatPercentage is not an integer', $e->getMessage()); - } + public function testItemWIthNegativeVatThrowsError() + { + $this->expectException(ValidationException::class); + (new Item())->setUnitPrice(1) + ->setUnits(2) + ->setStamp('thisIsStamp') + ->setVatPercentage(-10) + ->setProductCode('productCode123') + ->setDescription('description') + ->validate(); + } - try { - $i->setVatPercentage(12); - $i->validate(); - } catch (ValidationException $e) { - $this->assertStringContainsString('productCode is empty', $e->getMessage()); - } + public function testItemWithoutProductCodeThrowsError() + { + $this->expectException(ValidationException::class); + (new Item())->setUnitPrice(1) + ->setUnits(2) + ->setStamp('thisIsStamp') + ->setVatPercentage(10) + ->setDescription('description') + ->validate(); + } - try { - $i->setProductCode('productCode123'); - $i->validate(); - } catch (ValidationException $e) { - $this->assertStringContainsString('deliveryDate is empty', $e->getMessage()); - } + public static function providerForUnitPriceLimitValues() + { + return [ + 'Negative amount' => [-1, false], + 'Zero amount' => [0, true], + 'Maximum amount' => [99999999, true], + 'Over maximum amount' => [100000000, false] + ]; + } - $i->setDeliveryDate('12.12.1999'); + /** + * @dataProvider providerForUnitPriceLimitValues + */ + public function testUnitPriceLimitValues($unitPrice, $expectedResult) + { + $item = (new Item())->setUnitPrice($unitPrice) + ->setUnits(2) + ->setStamp('thisIsStamp') + ->setVatPercentage(0) + ->setProductCode('productCode123') + ->setDeliveryDate('2023-01-01') + ->setDescription('description'); try { - $this->assertIsBool($i->validate(), 'Item::validate returns bool'); - } catch (ValidationException $e) { + $validationResult = $item->validate(); + } catch (ValidationException $exception) { + $validationResult = false; } - + $this->assertEquals($expectedResult, $validationResult); } - -} \ No newline at end of file +} diff --git a/tests/Model/ProviderTest.php b/tests/Model/ProviderTest.php index b6512ea..57ba5d2 100644 --- a/tests/Model/ProviderTest.php +++ b/tests/Model/ProviderTest.php @@ -1,4 +1,5 @@ assertContains(1, $p->getParameters()); $this->assertContains(2, $p->getParameters()); } -} \ No newline at end of file +} diff --git a/tests/Model/RefundItemTest.php b/tests/Model/RefundItemTest.php index 3749503..0ce6180 100644 --- a/tests/Model/RefundItemTest.php +++ b/tests/Model/RefundItemTest.php @@ -1,4 +1,5 @@ setAmount(123.2322323); } - public function testTypeError() + + public function testRefundItemIsValid() { - $this->expectException(\TypeError::class); - $rfi = new RefundItem(); - $rfi->setAmount("not a number"); + $refundItem = (new RefundItem())->setAmount(123) + ->setStamp('thisIsStamp'); + + $this->assertEquals(true, $refundItem->validate()); } - public function testValidationExceptions() + public function testRefundItemWithoutAmountThrowsError() { $this->expectException(ValidationException::class); - $rfi = new RefundItem(); - $rfi->setAmount(123); - $rfi->setStamp(''); - $rfi->validate(); + (new RefundItem())->setStamp('thisIsStamp') + ->validate(); + } + + public function testRefundItemWithNegativeAmountThrowsError() + { + $this->expectException(ValidationException::class); + (new RefundItem())->setAmount(-1) + ->setStamp('thisIsStamp') + ->validate(); } } diff --git a/tests/Model/Token/CardTest.php b/tests/Model/Token/CardTest.php index b807aad..6371b33 100644 --- a/tests/Model/Token/CardTest.php +++ b/tests/Model/Token/CardTest.php @@ -1,4 +1,5 @@ [ diff --git a/tests/Model/Token/CustomerTest.php b/tests/Model/Token/CustomerTest.php index 902e1cb..1529ee7 100644 --- a/tests/Model/Token/CustomerTest.php +++ b/tests/Model/Token/CustomerTest.php @@ -1,4 +1,5 @@ [['networkAddress' => ''], 'Network address is empty'], - 'Country code is empty' => [['networkAddress' => '93.174.192.154', 'countryCode' => ''], 'Country code is empty'] + 'Network address is empty' => [ + [ + 'networkAddress' => '' + ], + 'Network address is empty' + ], + 'Country code is empty' => [ + [ + 'networkAddress' => '93.174.192.154', + 'countryCode' => '' + ], + 'Country code is empty' + ] ]; } diff --git a/tests/PaymentRequestTestCase.php b/tests/PaymentRequestTestCase.php new file mode 100644 index 0000000..860f37a --- /dev/null +++ b/tests/PaymentRequestTestCase.php @@ -0,0 +1,101 @@ +client = new Client(self::MERCHANT_ID, self::SECRET, self::COF_PLUGIN_VERSION); + $this->sisClient = new Client( + self::SHOP_IN_SHOP_AGGREGATE_MERCHANT_ID, + self::SHOP_IN_SHOP_SECRET, + self::COF_PLUGIN_VERSION + ); + } + + /** + * Create a payment request. + * + * @param PaymentRequest|PaymentRequestInterface $paymentRequest + * @return PaymentResponse + */ + protected function createPayment(PaymentRequestInterface $paymentRequest): PaymentResponse + { + try { + $paymentRequest->validate(); + + return $this->client->createPayment($paymentRequest); + } catch (HmacException | ValidationException $e) { + $this->fail($e->getMessage()); + } + } + + /** + * Create a shop-in-shop payment request. + * + * @param ShopInShopPaymentRequest|PaymentRequestInterface $paymentRequest + * @return PaymentResponse + */ + protected function createShopInShopPayment(PaymentRequestInterface $paymentRequest): PaymentResponse + { + try { + $paymentRequest->validate(); + + return $this->sisClient->createShopInShopPayment($paymentRequest); + } catch (HmacException | ValidationException $e) { + $this->fail($e->getMessage()); + } + } + + /** + * Asserts that a payment response is valid and has all the required fields. + * + * @param PaymentResponse $paymentResponse + * @return void + */ + public static function assertPaymentResponseIsValid(PaymentResponse $paymentResponse): void + { + static::assertNotEmpty($paymentResponse->getTransactionId()); + static::assertNotEmpty($paymentResponse->getHref()); + static::assertNotEmpty($paymentResponse->getTerms()); + static::assertNotEmpty($paymentResponse->getReference()); + static::assertIsArray($paymentResponse->getGroups()); + static::assertContainsOnlyInstancesOf(PaymentMethodGroup::class, $paymentResponse->getGroups()); + static::assertIsArray($paymentResponse->getProviders()); + } +} diff --git a/tests/Request/AddCardFormRequestTest.php b/tests/Request/AddCardFormRequestTest.php index 0254281..96557a1 100644 --- a/tests/Request/AddCardFormRequestTest.php +++ b/tests/Request/AddCardFormRequestTest.php @@ -1,12 +1,6 @@ [ diff --git a/tests/Request/CitPaymentRequestTest.php b/tests/Request/CitPaymentRequestTest.php index faec388..dded277 100644 --- a/tests/Request/CitPaymentRequestTest.php +++ b/tests/Request/CitPaymentRequestTest.php @@ -1,12 +1,6 @@ setAmount(20); - $er->setEmail('some@email.com'); + $emailRequest = new EmailRefundRequest(); + $emailRequest->setAmount(20); + $emailRequest->setEmail('some@email.com'); $item = new RefundItem(); $item->setAmount(10) @@ -26,113 +26,40 @@ public function testEmailRefundRequest() $item2->setAmount(10) ->setStamp('anotherStamp'); - $er->setItems([$item, $item2]); + $emailRequest->setItems([$item, $item2]); $cb = new CallbackUrl(); $cb->setCancel('https://some.url.com/cancel') ->setSuccess('https://some.url.com/success'); - $er->setCallbackUrls($cb); + $emailRequest->setCallbackUrls($cb); + + $emailRequest->setRefundReference('ref-1234') + ->setRefundStamp('c7557cd5d5f548daa5332ccc4abb264f'); - $this->assertEquals(true, $er->validate()); + $this->assertTrue($emailRequest->validate()); } - public function testExceptions() + public function testRefundRequestWithoutItemsAndAmountThrowsException() { + $this->expectException(ValidationException::class); + (new EmailRefundRequest())->validate(); + } - $er = new EmailRefundRequest(); - - try { - $er->validate(); - } catch (ValidationException $e) { - $this->assertEquals("Amount can not be empty", $e->getMessage()); - } - - $er->setAmount(99999); - - try { - $er->validate(); - } catch (ValidationException $e) { - $this->assertEquals('CallbackUrls are not set', $e->getMessage()); - } - - $cb = new CallbackUrl(); - $er->setCallbackUrls($cb); - - try { - $er->validate(); - } catch (ValidationException $e) { - $this->assertEquals('Success is empty', $e->getMessage()); - } - - $cb->setSuccess('someurl.somewhere.com/success'); - $er->setCallbackUrls($cb); - - try { - $er->validate(); - } catch (ValidationException $e) { - $this->assertEquals('Cancel is empty', $e->getMessage()); - } - - $cb->setCancel('someurl.somewhere.com/cancel'); - $er->setCallbackUrls($cb); - - try { - $er->validate(); - } catch (ValidationException $e) { - $this->assertEquals('Success is not a valid URL', $e->getMessage()); - } - - $cb->setSuccess('https://someurl.somewhere.com/success'); - $er->setCallbackUrls($cb); - - try { - $er->validate(); - } catch (ValidationException $e) { - $this->assertEquals('Cancel is not a valid URL', $e->getMessage()); - } - - $cb->setCancel('https://someurl.somewhere.com/cancel'); - $er->setCallbackUrls($cb); - - try { - $er->validate(); - } catch (ValidationException $e) { - $this->assertEquals('email can not be empty', $e->getMessage()); - } - - $er->setEmail('some@email.com'); - - // Items are not mandatory, so should pass from here - try { - $er->validate(); - } catch (ValidationException $e) { - var_dump($e->getMessage()); - } - - $item = new RefundItem(); - $item->setAmount(110) - ->setStamp('someStamp'); - - $item2 = new RefundItem(); - $item2->setAmount(10) - ->setStamp('anotherStamp'); - - $er->setItems([$item, $item2]); - - // Fails, as refund->total was set to 9999 - try { - $er->validate(); - } catch (ValidationException $e) { - $this->assertEquals('ItemsTotal does not match Amount', $e->getMessage()); - } - - // Set correct amount - $er->setAmount(120); + public function testRefundWithItemsAndAmountMismatchThrowsException() + { + $this->expectException(ValidationException::class); + (new EmailRefundRequest())->setAmount(100) + ->setItems([ + (new RefundItem())->setAmount(200) + ->setStamp('foobar') + ])->validate(); + } - try { - $this->assertEquals(true, $er->validate()); - } catch (ValidationException $e) { - } + public function testRefundRequestWithoutCallbackUrlsThrowsError() + { + $this->expectException(ValidationException::class); + (new EmailRefundRequest())->setAmount(100) + ->validate(); } } diff --git a/tests/Request/GetTokenRequestTest.php b/tests/Request/GetTokenRequestTest.php index 5145272..2a5d874 100644 --- a/tests/Request/GetTokenRequestTest.php +++ b/tests/Request/GetTokenRequestTest.php @@ -1,4 +1,5 @@ [['checkoutTokenizationId' => ''], 'checkout-tokenization-id is empty'] + 'checkout-tokenization-id is empty' => [ + [ + 'checkoutTokenizationId' => '' + ], + 'checkout-tokenization-id is empty' + ] ]; } diff --git a/tests/Request/MitPaymentRequestTest.php b/tests/Request/MitPaymentRequestTest.php index e4f382a..4b46de9 100644 --- a/tests/Request/MitPaymentRequestTest.php +++ b/tests/Request/MitPaymentRequestTest.php @@ -1,4 +1,5 @@ setAmount(30) ->setStamp('RequestStamp') ->setReference('RequestReference123') ->setCurrency('EUR') ->setLanguage('EN'); - $customer = (new Customer) + $customer = (new Customer()) ->setEmail('customer@email.com'); $payment->setCustomer($customer); - $callback = (new CallbackUrl) + $callback = (new CallbackUrl()) ->setCancel('https://somedomain.com/cancel') ->setSuccess('https://somedomain.com/success'); $payment->setCallbackUrls($callback); - $redirect = (new CallbackUrl) + $redirect = (new CallbackUrl()) ->setSuccess('https://someother.com/success') ->setCancel('https://someother.com/cancel'); @@ -68,14 +70,14 @@ private function getPaymentRequest(): PaymentRequest private function getPaymentItems(): array { return [ - (new Item) + (new Item()) ->setStamp('someStamp') ->setDeliveryDate('12.12.2020') ->setProductCode('pr1') ->setVatPercentage(25) ->setUnitPrice(10) ->setUnits(1), - (new Item) + (new Item()) ->setStamp('someOtherStamp') ->setDeliveryDate('12.12.2020') ->setProductCode('pr2') diff --git a/tests/Request/PaymentStatusRequestTest.php b/tests/Request/PaymentStatusRequestTest.php index 2f23901..584d4fb 100644 --- a/tests/Request/PaymentStatusRequestTest.php +++ b/tests/Request/PaymentStatusRequestTest.php @@ -1,4 +1,5 @@ validate(); } -} \ No newline at end of file +} diff --git a/tests/Request/ShopInShopPaymentRequestTest.php b/tests/Request/ShopInShopPaymentRequestTest.php index 452d3cf..b55f965 100644 --- a/tests/Request/ShopInShopPaymentRequestTest.php +++ b/tests/Request/ShopInShopPaymentRequestTest.php @@ -1,4 +1,5 @@