Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ $theConfig->setLanguage($language);

Make sure to prepare the necessary dependencies before creating the `\ThePay\ApiClient\TheClient` instance.

In any case of dependencies preparation, you MUST check if your PSR-18 HTTP client, will return real PSR-7 network stream!
Because some API endpoints are not paginated for example: [getAccountStatementGPC](../doc/download-account-transaction-GPC.md), and can contain big amount of data!
If an HTTP client will try load full response to memory, some of your API calls can crash on out of memory error!

### With dependency injection

If you're using automatic dependency injection (as most frameworks do), all dependencies except `TheConfig`
Expand All @@ -103,7 +107,9 @@ $signatureService = new \ThePay\ApiClient\Service\SignatureService($theConfig);
/** @var \Psr\Http\Message\RequestFactoryInterface $requestFactory some PSR-17 implementation */
/** @var \Psr\Http\Message\StreamFactoryInterface $streamFactory some PSR-17 implementation */
// if you install suggested guzzle implementation you can use this:
// $httpClient = new \GuzzleHttp\Client();
// you MUST use RequestOptions::STREAM with true value!
// https://docs.guzzlephp.org/en/stable/request-options.html#stream
// $httpClient = new \GuzzleHttp\Client([\GuzzleHttp\RequestOptions::STREAM => true]);
// $requestFactory = $streamFactory = new \GuzzleHttp\Psr7\HttpFactory();
$apiService = new \ThePay\ApiClient\Service\ApiService(
$theConfig,
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ jobs:
name: "php 8.4"
runs-on: ubuntu-latest
container: "nofutur3/php-tests:8.4"
services:
openAPImock:
image: mockserver/mockserver
ports:
- 1080:1080
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -20,13 +25,21 @@ jobs:
- name: Run static analysis
run: composer stan

- name: Create mock server from our production OpenAPI
run: curl -X PUT -d "{\"specUrlOrPayload\":\"https://gate.thepay.cz/openapi.yaml\"}" http://openAPImock:1080/mockserver/openapi

- name: Run tests
run: composer test

php83:
name: "php 8.3"
runs-on: ubuntu-latest
container: "nofutur3/php-tests:8.3"
services:
openAPImock:
image: mockserver/mockserver
ports:
- 1080:1080
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand All @@ -37,13 +50,21 @@ jobs:
- name: Run static analysis
run: composer stan

- name: Create mock server from our production OpenAPI
run: curl -X PUT -d "{\"specUrlOrPayload\":\"https://gate.thepay.cz/openapi.yaml\"}" http://openAPImock:1080/mockserver/openapi

- name: Run tests
run: composer test

php82:
name: "php 8.2 psr/http-message 2.0"
runs-on: ubuntu-latest
container: "nofutur3/php-tests:8.2"
services:
openAPImock:
image: mockserver/mockserver
ports:
- 1080:1080
steps:
- name: Checkout repository
uses: actions/checkout@v3
Expand All @@ -57,13 +78,21 @@ jobs:
- name: Run static analysis
run: composer stan

- name: Create mock server from our production OpenAPI
run: curl -X PUT -d "{\"specUrlOrPayload\":\"https://gate.thepay.cz/openapi.yaml\"}" http://openAPImock:1080/mockserver/openapi

- name: Run tests
run: composer test

php82psrmessage10:
name: "php 8.2 psr/http-message 1.0"
runs-on: ubuntu-latest
container: "nofutur3/php-tests:8.2"
services:
openAPImock:
image: mockserver/mockserver
ports:
- 1080:1080
steps:
- name: Checkout repository
uses: actions/checkout@v3
Expand All @@ -74,13 +103,21 @@ jobs:
- name: Run static analysis
run: composer stan

- name: Create mock server from our production OpenAPI
run: curl -X PUT -d "{\"specUrlOrPayload\":\"https://gate.thepay.cz/openapi.yaml\"}" http://openAPImock:1080/mockserver/openapi

- name: Run tests
run: composer test

php81:
name: "php 8.1"
runs-on: ubuntu-latest
container: "nofutur3/php-tests:8.1"
services:
openAPImock:
image: mockserver/mockserver
ports:
- 1080:1080
steps:
- name: Checkout repository
uses: actions/checkout@v3
Expand All @@ -91,13 +128,21 @@ jobs:
- name: Run static analysis
run: composer stan

- name: Create mock server from our production OpenAPI
run: curl -X PUT -d "{\"specUrlOrPayload\":\"https://gate.thepay.cz/openapi.yaml\"}" http://openAPImock:1080/mockserver/openapi

- name: Run tests
run: composer test

php80:
name: "php 8.0"
runs-on: ubuntu-latest
container: "nofutur3/php-tests:8.0"
services:
openAPImock:
image: mockserver/mockserver
ports:
- 1080:1080
steps:
- name: Checkout repository
uses: actions/checkout@v3
Expand All @@ -108,13 +153,21 @@ jobs:
- name: Run static analysis
run: composer stan

- name: Create mock server from our production OpenAPI
run: curl -X PUT -d "{\"specUrlOrPayload\":\"https://gate.thepay.cz/openapi.yaml\"}" http://openAPImock:1080/mockserver/openapi

- name: Run tests
run: composer test

php74:
name: "php 7.4"
runs-on: ubuntu-latest
container: "nofutur3/php-tests:7.4"
services:
openAPImock:
image: mockserver/mockserver
ports:
- 1080:1080
steps:
# Deprecation example for future support removal.
#
Expand All @@ -130,6 +183,9 @@ jobs:
- name: Run static analysis
run: composer stan

- name: Create mock server from our production OpenAPI
run: curl -X PUT -d "{\"specUrlOrPayload\":\"https://gate.thepay.cz/openapi.yaml\"}" http://openAPImock:1080/mockserver/openapi

- name: Run tests
run: composer test

Expand Down
30 changes: 30 additions & 0 deletions doc/download-account-transaction-GPC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Download account transaction GPC statement

Use the `getAccountStatementGPC` method to download the transaction GPC statement for a specific account within a given date range.

## Example: Download statement to local file on server

```php

/** @var \ThePay\ApiClient\TheClient $thePayClient */

$from = new DateTime('2021-03-01');
$to = new DateTime('2021-03-31');
$filter = new \ThePay\ApiClient\Filter\TransactionFilter('TP3211114680489551165349', $from, $to);

$psrResponseBodyStream = $thePayClient->getAccountStatementGPC($filter);
$phpResponseBodyStream = $psrResponseBodyStream->detach() ?? new \RuntimeException('PHP stream missing');

$file = fopen('some_path.gpc', 'w');
stream_copy_to_stream($phpResponseBodyStream, $file);
fclose($file);

```

**Parameters:**
- `$filter` - An instance of `\ThePay\ApiClient\Filter\TransactionFilter()`. (See online API documentation for all available filter options.)

**Returns:**

A `Psr\Http\Message\StreamInterface` object containing:
- Binary stream with GPC transaction statement in windows-1250 encoding
3 changes: 3 additions & 0 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
| getPaymentRefund | https://thepay.docs.apiary.io/#reference/0/project-level-resources/payment-refund-info |
| createPaymentRefund | https://thepay.docs.apiary.io/#reference/0/project-level-resources/payment-refund-request |
| getAccountTransactionHistory | https://thepay.docs.apiary.io/#reference/0/merchant-level-resources/get-account-transaction-history |
| getAccountStatementGPC | https://docs.thepay.cz/#tag/Transactions/paths/~1v1~1transactions~1%7Baccount_iban%7D~1account_statement~1gpc/get |
| realizeRegularSubscriptionPayment | https://thepay.docs.apiary.io/#reference/0/project-level-resources/realize-regular-subscription-payment |
| realizeIrregularSubscriptionPayment | https://thepay.docs.apiary.io/#reference/0/project-level-resources/realize-irregular-subscription-payment |
| realizeUsageBasedSubscriptionPayment | https://thepay.docs.apiary.io/#reference/0/project-level-resources/realize-usage-based-subscription-payment |
Expand All @@ -42,6 +43,8 @@

[Get account transaction history](get-transactions-history.md)

[Download account transaction GPC statement](download-account-transaction-GPC.md)

[Creating subscription](subscription.md)

[Saving authorization](saving-authorization.md)
Expand Down
25 changes: 25 additions & 0 deletions src/Service/ApiService.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\StreamInterface;
use ThePay\ApiClient\Exception\ApiException;
use ThePay\ApiClient\Filter\PaymentsFilter;
use ThePay\ApiClient\Filter\TransactionFilter;
Expand All @@ -32,6 +33,7 @@
use ThePay\ApiClient\TheConfig;
use ThePay\ApiClient\Utils\Json;
use ThePay\ApiClient\ValueObject\Amount;
use ThePay\ApiClient\ValueObject\GPCPaymentIdentifier;
use ThePay\ApiClient\ValueObject\Identifier;
use ThePay\ApiClient\ValueObject\LanguageCode;
use ThePay\ApiClient\ValueObject\StringValue;
Expand Down Expand Up @@ -192,6 +194,29 @@ public function getAccountTransactionHistory(TransactionFilter $filter, int $pag
return new TransactionCollection(Json::decode($response->getBody()->getContents(), true), $page, $limit, (int) $response->getHeaderLine('X-Total-Count'));
}

public function getAccountStatementGPC(TransactionFilter $filter, ?GPCPaymentIdentifier $paymentIdentifier = null): StreamInterface
{
$arguments = [
'date_from' => $filter->getDateFrom()->format('Y-m-d'),
'date_to' => $filter->getDateTo()->format('Y-m-d'),
];
if ($filter->getCurrencyCode() !== null) {
$arguments['currency_code'] = $filter->getCurrencyCode()->getValue();
}
if ($paymentIdentifier !== null) {
$arguments['payment_identifier'] = $paymentIdentifier->getValue();
}

$url = $this->url(['transactions', $filter->getAccountIban(), 'account_statement', 'gpc'], $arguments, false);

$response = $this->sendRequest(self::METHOD_GET, $url);
if ($response->getStatusCode() !== 200) {
throw $this->buildException($url, $response);
}

return $response->getBody();
}

/**
* Get complete information about the specified payment.
*
Expand Down
4 changes: 4 additions & 0 deletions src/Service/ApiServiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace ThePay\ApiClient\Service;

use Psr\Http\Message\StreamInterface;
use ThePay\ApiClient\Exception\ApiException;
use ThePay\ApiClient\Filter\PaymentsFilter;
use ThePay\ApiClient\Filter\TransactionFilter;
Expand All @@ -23,6 +24,7 @@
use ThePay\ApiClient\Model\RealizeUsageBasedSubscriptionPaymentParams;
use ThePay\ApiClient\Model\RecurringPaymentResult;
use ThePay\ApiClient\ValueObject\Amount;
use ThePay\ApiClient\ValueObject\GPCPaymentIdentifier;
use ThePay\ApiClient\ValueObject\Identifier;
use ThePay\ApiClient\ValueObject\LanguageCode;
use ThePay\ApiClient\ValueObject\StringValue;
Expand Down Expand Up @@ -112,6 +114,8 @@ public function getAccountsBalances(?StringValue $accountIban = null, $projectId
*/
public function getAccountTransactionHistory(TransactionFilter $filter, int $page = 1, int $limit = 100): TransactionCollection;

public function getAccountStatementGPC(TransactionFilter $filter, ?GPCPaymentIdentifier $paymentIdentifier = null): StreamInterface;

/**
* @param non-empty-string|null $methodCode
*
Expand Down
16 changes: 16 additions & 0 deletions src/TheClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Exception;
use InvalidArgumentException;
use Psr\Http\Message\StreamInterface;
use ThePay\ApiClient\Exception\ApiException;
use ThePay\ApiClient\Filter\PaymentMethodFilter;
use ThePay\ApiClient\Filter\PaymentsFilter;
Expand All @@ -29,6 +30,7 @@
use ThePay\ApiClient\Service\GateService;
use ThePay\ApiClient\Service\GateServiceInterface;
use ThePay\ApiClient\ValueObject\Amount;
use ThePay\ApiClient\ValueObject\GPCPaymentIdentifier;
use ThePay\ApiClient\ValueObject\Identifier;
use ThePay\ApiClient\ValueObject\LanguageCode;
use ThePay\ApiClient\ValueObject\StringValue;
Expand Down Expand Up @@ -99,6 +101,20 @@ public function getAccountTransactionHistory(TransactionFilter $filter, $page =
->getAccountTransactionHistory($filter, $page, $limit);
}

/**
* @see https://docs.thepay.cz/#tag/Transactions/paths/~1v1~1transactions~1%7Baccount_iban%7D~1account_statement~1gpc/get
* @see ../doc/download-account-transaction-GPC.md
*
* @return StreamInterface MUST return real PSR-7 network stream, make sure you have your PSR-18 HTTP client correctly configured, GPC format is not paginated!
* @return StreamInterface content is windows-1250 encoded
*/
public function getAccountStatementGPC(TransactionFilter $filter, ?GPCPaymentIdentifier $paymentIdentifier = null): StreamInterface
{
return $this
->api
->getAccountStatementGPC($filter, $paymentIdentifier);
}

/**
* @param PaymentMethodFilter|null $filter
* @param LanguageCode|null $languageCode language for payment method titles, null value language from TheConfig used
Expand Down
5 changes: 5 additions & 0 deletions src/TheConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ public function getApiUrl(?string $specificVersion = null): string
return $this->apiUrl->getValue() . $this->apiVersion . '/';
}

public function getApiVersion(): string
{
return $this->apiVersion;
}

/**
* @return string
*/
Expand Down
24 changes: 24 additions & 0 deletions src/ValueObject/GPCPaymentIdentifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace ThePay\ApiClient\ValueObject;

final class GPCPaymentIdentifier extends EnumValueObject
{
public const ORDER_NUMBER = 'order_number';
public const UID = 'uid';
public const ID = 'id';

/**
* @return array<string>
*/
public static function cases(): array
{
return [
self::ORDER_NUMBER,
self::UID,
self::ID,
];
}
}
Loading
Loading