Skip to content

Commit

Permalink
Merge pull request #13 from n4ss1m/enhancements
Browse files Browse the repository at this point in the history
chore(docs): Add PHP Version Support & PHPStan Badge + Code Quality Improvements
  • Loading branch information
n4ss1m authored Feb 3, 2025
2 parents 0020781 + b724d9b commit 8b2d808
Show file tree
Hide file tree
Showing 28 changed files with 258 additions and 152 deletions.
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Path-based git attributes
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
* text=auto

*.md diff=markdown
*.php diff=php

# Ignore all test and documentation with "export-ignore".
/.github export-ignore
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ yarn-error.log
/.idea
/.fleet
/.vscode
.editorconfig

# Code sniffer
.php_cs
Expand Down
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
![Satim logo](images/satim.png)

<img width="600" src="https://banners.beyondco.de/Satim.dz%20PHP%20Client.png?theme=light&packageManager=composer+require&packageName=piteurstudio%2Fsatim-php&pattern=architect&style=style_1&description=A+fully+open-source+PHP+package+for+seamless+integration+with+Satim.dz&md=1&showWatermark=1&fontSize=75px&images=https%3A%2F%2Fwww.php.net%2Fimages%2Flogos%2Fnew-php-logo.svg" alt="Satim PHP Client">

[![Latest Version on Packagist](https://img.shields.io/packagist/v/piteurstudio/satim-php.svg?style=flat-square)](https://packagist.org/packages/piteurstudio/satim-php)
[![codecov](https://codecov.io/gh/PiteurStudio/satim-php/branch/main/graph/badge.svg?token=MXKQCQ4AGX)](https://codecov.io/gh/PiteurStudio/satim-php)
[![Tests](https://img.shields.io/github/actions/workflow/status/piteurstudio/php-satim/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/piteurstudio/php-satim/actions/workflows/run-tests.yml)
[![Total Downloads](https://img.shields.io/packagist/dt/piteurstudio/satim-php.svg?style=flat-square)](https://packagist.org/packages/piteurstudio/satim-php)
<p align="center"><img src="images/satim.png" alt="Satim logo"></p>

<p align="center">
<img width="800" src="https://banners.beyondco.de/Satim.dz%20PHP%20Client.png?theme=light&packageManager=composer+require&packageName=piteurstudio%2Fsatim-php&pattern=architect&style=style_1&description=A+fully+open-source+PHP+package+for+seamless+integration+with+Satim.dz&md=1&showWatermark=1&fontSize=75px&images=https%3A%2F%2Fwww.php.net%2Fimages%2Flogos%2Fnew-php-logo.svg" alt="Satim PHP Client">
</p>

<p align="center">
<a href="https://packagist.org/packages/piteurstudio/satim-php"><img src="http://poser.pugx.org/piteurstudio/satim-php/require/php" alt="PHP Version Require"></a>
<a href="https://packagist.org/packages/piteurstudio/satim-php"><img src="https://img.shields.io/packagist/v/piteurstudio/satim-php.svg?style=flat" alt="Latest Version on Packagist"></a>
<a href="https://codecov.io/gh/PiteurStudio/satim-php"><img src="https://codecov.io/gh/PiteurStudio/satim-php/branch/main/graph/badge.svg?token=MXKQCQ4AGX" alt="codecov"></a>
<a href="https://github.com/PiteurStudio/satim-php/blob/main/phpstan.neon"><img src="https://img.shields.io/badge/PHPStan-max-blue.svg?style=flat" alt="phpstan"></a>
<a href="https://github.com/piteurstudio/php-satim/actions/workflows/run-tests.yml"><img src="https://img.shields.io/github/actions/workflow/status/piteurstudio/php-satim/run-tests.yml?branch=main&amp;label=tests&amp;style=flat" alt="Tests"></a>
<a href="https://packagist.org/packages/piteurstudio/satim-php"><img src="https://img.shields.io/packagist/dt/piteurstudio/satim-php.svg?style=flat" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/piteurstudio/satim-php"><img src="http://poser.pugx.org/piteurstudio/satim-php/license" alt="License"></a>
</p>

# Satim.dz PHP Client

Expand Down
3 changes: 1 addition & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@
"@test:lint",
"@test:types",
"@test:refactor"
],
"format": "vendor/bin/pint"
]
},
"config": {
"sort-packages": true,
Expand Down
6 changes: 1 addition & 5 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ parameters:
paths:
- src/

# Level 10 is the highest level
level: 8
level: max

treatPhpDocTypesAsCertain: false

# ignoreErrors:
# - '#Call to an undefined method Spatie\\Image\\Drivers\\ImageDriver::keepOriginalImageFormat#'
13 changes: 13 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,23 @@
declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\SetList;

return RectorConfig::configure()
->withPaths([
__DIR__.'/src',
__DIR__.'/tests',
])
->withSets([
SetList::DEAD_CODE,
SetList::CODE_QUALITY,
SetList::CODING_STYLE,
SetList::TYPE_DECLARATION,
SetList::PRIVATIZATION,
SetList::NAMING,
SetList::RECTOR_PRESET,
SetList::STRICT_BOOLEANS,
SetList::EARLY_RETURN,
SetList::INSTANCEOF,
])
->withPhpSets();
13 changes: 9 additions & 4 deletions src/Client/HttpClientService.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace PiteurStudio\Client;

use PiteurStudio\Exception\SatimInvalidArgumentException;
Expand Down Expand Up @@ -85,7 +87,10 @@ public function sendRequest(string $endpoint, array $data): array
try {
$response = $this->httpClient->request('POST', $url, ['body' => $data]);

return $response->toArray(); // This will throw exceptions if the response is invalid
/** @var array<string, mixed> $responseData */
$responseData = $response->toArray(); // This will throw exceptions if the response is invalid

return $responseData;
} catch (DecodingExceptionInterface|ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) {
throw new SatimUnexpectedResponseException('API Error: '.$e->getMessage(), 0, $e);
} catch (TransportExceptionInterface $e) {
Expand All @@ -112,11 +117,11 @@ private function getClientOptions(): array
*
* @param array<string,mixed> $response The API response to validate.
*
* @throws SatimUnexpectedResponseException|SatimInvalidCredentials If the response contains an error.
* @throws SatimInvalidCredentials If the response contains an error.
*/
private function validateApiResponse(array $response): void
{
if (isset($response['ErrorCode'])) {
if (isset($response['ErrorCode']) && is_string($response['ErrorCode'])) {
if ($response['ErrorCode'] === '6' && $response['ErrorMessage'] === 'Unknown order id') {
throw new SatimInvalidArgumentException('Invalid order ID');
}
Expand All @@ -125,7 +130,7 @@ private function validateApiResponse(array $response): void
throw new SatimInvalidCredentials('Invalid username or password or terminal ID');
}

throw new SatimUnexpectedResponseException('API Error { ErrorCode: '.$response['ErrorCode'].', ErrorMessage: '.($response['ErrorMessage'] ?? 'Unknown Error').' }');
// throw new SatimUnexpectedResponseException('API Error { ErrorCode: '.$response['ErrorCode'].', ErrorMessage: '.(isset($response['ErrorMessage']) && is_string($response['ErrorMessage']) ? $response['ErrorMessage'] : 'Unknown Error').' }');
}
}
}
2 changes: 2 additions & 0 deletions src/Exception/SatimInvalidArgumentException.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace PiteurStudio\Exception;

use InvalidArgumentException;
Expand Down
2 changes: 2 additions & 0 deletions src/Exception/SatimInvalidCredentials.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace PiteurStudio\Exception;

use Exception;
Expand Down
2 changes: 2 additions & 0 deletions src/Exception/SatimInvalidDataException.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace PiteurStudio\Exception;

use Exception;
Expand Down
2 changes: 2 additions & 0 deletions src/Exception/SatimMissingDataException.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace PiteurStudio\Exception;

use Exception;
Expand Down
2 changes: 2 additions & 0 deletions src/Exception/SatimUnexpectedResponseException.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace PiteurStudio\Exception;

use Exception;
Expand Down
2 changes: 2 additions & 0 deletions src/Exception/SatimUnexpectedValueException.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace PiteurStudio\Exception;

use UnexpectedValueException;
Expand Down
41 changes: 24 additions & 17 deletions src/Satim.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ public function __construct(array $data, ?HttpClientService $httpClientService =
private function validateData(): void
{
// Check if the return URL is set, throw an exception if missing
if (! $this->returnUrl) {
if ($this->returnUrl === null || $this->returnUrl === '' || $this->returnUrl === '0') {
throw new SatimMissingDataException('Return URL missing. Call returnUrl() to set it.');
}

// Check if the order number is set; if not, generate a random one
if (! $this->orderNumber) {
if ($this->orderNumber === null || $this->orderNumber === 0) {
$this->orderNumber(mt_rand(1000000000, 9999999999));
}

// Check if the amount is set, throw an exception if missing
if (! $this->amount) {
if ($this->amount === null || $this->amount === 0) {
throw new SatimMissingDataException('Amount missing. Call the amount() method to set it.');
}

Expand All @@ -79,7 +79,7 @@ private function buildData(): array
];

// If user-defined fields are set, add them to the additional data
if ($this->userDefinedFields) {
if ($this->userDefinedFields !== null && $this->userDefinedFields !== []) {
$additionalData = array_merge($additionalData, $this->userDefinedFields);
}

Expand All @@ -97,12 +97,12 @@ private function buildData(): array
];

// If a description is set, add it to the request data
if ($this->description) {
if ($this->description !== null && $this->description !== '' && $this->description !== '0') {
$data['description'] = $this->description;
}

// If a session timeout is set, add it to the request data
if ($this->sessionTimeoutSecs) {
if ($this->sessionTimeoutSecs !== null && $this->sessionTimeoutSecs !== 0) {
$data['sessionTimeoutSecs'] = $this->sessionTimeoutSecs;
}

Expand Down Expand Up @@ -133,9 +133,11 @@ public function register(): static
// Check the response and throw an exception if the error code is not 0
if ($result['errorCode'] !== '0') {

$errorMessage = $result['errorMessage'] ?? 'Unknown error';
$errorMessage = $result['errorMessage'] && is_string($result['errorMessage']) ? $result['errorMessage'] : 'Unknown error';

throw new SatimUnexpectedResponseException('registerPayment Error {errorCode: '.$result['errorCode'].' , errorMessage: '.$errorMessage.'}');
$errorCode = $result['errorCode'] && is_string($result['errorCode']) ? $result['errorCode'] : 'Unknown error';

throw new SatimUnexpectedResponseException('registerPayment Error {errorCode: '.$errorCode.' , errorMessage: '.$errorMessage.'}');
}

// Store the response data
Expand All @@ -153,16 +155,17 @@ public function register(): static
* This method sends a request to the Satim API to confirm the payment
* using the given order ID. The response is stored in the confirmOrderResponse property.
*
* @param non-empty-string $orderId The ID of the order to be confirmed.
* @param string $orderId The ID of the order to be confirmed.
* @return static The current instance for method chaining.
*
* @throws SatimUnexpectedResponseException|SatimInvalidCredentials Thrown if the API response is unexpected.
*/
public function confirm(string $orderId): static
{
if (empty($orderId)) {
if ($orderId === '' || $orderId === '0') {
throw new SatimInvalidArgumentException('Order ID is required for confirmation');
}

// Prepare the data for the confirmation request
$data = [
'userName' => $this->username,
Expand Down Expand Up @@ -192,9 +195,10 @@ public function confirm(string $orderId): static
*/
public function status(string $orderId): static
{
if (empty($orderId)) {
if ($orderId === '' || $orderId === '0') {
throw new SatimInvalidArgumentException('Order ID is required for confirmation');
}

// Prepare the data for the status request
$data = [
'userName' => $this->username,
Expand All @@ -218,21 +222,22 @@ public function status(string $orderId): static
* The amount should be specified in the major currency unit and will be
* converted to minor units in the request.
*
* @param non-empty-string $orderId The ID of the order to be refunded.
* @param string $orderId The ID of the order to be refunded.
* @param positive-int $amount The amount to refund in major currency units.
* @return array<string,mixed> The response from the Satim API.
*
* @throws SatimUnexpectedResponseException|SatimInvalidCredentials Thrown if the API response is unexpected.
* @throws SatimInvalidCredentials Thrown if the API response is unexpected.
* @throws SatimUnexpectedResponseException Thrown if the API response is unexpected.
*/
public function refund(string $orderId, int $amount): array
public function refund(string $orderId, int $amount): static
{
if (empty($orderId)) {
if ($orderId === '' || $orderId === '0') {
throw new SatimInvalidArgumentException('Order ID is required for refund');
}

if ($amount <= 0) {
throw new SatimInvalidArgumentException('Amount must be a positive integer');
}

// Prepare the data for the refund request
$data = [
'userName' => $this->username,
Expand All @@ -244,6 +249,8 @@ public function refund(string $orderId, int $amount): array

$this->context = 'refund';

return $this->httpClientService->handleApiRequest('/refund.do', $data);
$this->refundOrderResponse = $this->httpClientService->handleApiRequest('/refund.do', $data);

return $this;
}
}
Loading

0 comments on commit 8b2d808

Please sign in to comment.