diff --git a/.github/README.md b/.github/README.md index af4c2ee..85cef03 100644 --- a/.github/README.md +++ b/.github/README.md @@ -5,19 +5,21 @@ interacts with The Pay's REST API. To get started see examples below. ## Requirements -- PHP 7.4+ - -- **curl** extension -- **json** extension +All necessary requirements are defined in [composer.json](../composer.json) `require` property. +We strongly recommend SDK installation using [Composer](https://getcomposer.org/)! ## Installation -To install the SDK we recommend to use [Composer](https://getcomposer.org/): - ```console composer require thepay/api-client ``` +Installation with suggested PSR http client. + +```console +composer require thepay/api-client guzzlehttp/guzzle +``` + This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Support & Contributions @@ -54,7 +56,14 @@ You will work with only two classes when using this SDK. All constructor parameters are described in [php doc](../src/TheConfig.php) ```php -$config = new ThePay\ApiClient\TheConfig( +$merchantId = '86a3eed0-95a4-11ea-ac9f-371f3488e0fa'; +$projectId = 3; +$apiPassword = 'secret'; +$apiUrl = 'https://demo.api.thepay.cz/'; // production: 'https://api.thepay.cz/' +$gateUrl = 'https://demo.gate.thepay.cz/'; // production: 'https://gate.thepay.cz/' +$language = 'cs'; + +$theConfig = new \ThePay\ApiClient\TheConfig( $merchantId, $projectId, $apiPassword, @@ -62,7 +71,40 @@ $config = new ThePay\ApiClient\TheConfig( $gateUrl ); -$config->setLanguage($language); +$theConfig->setLanguage($language); +``` + +## TheClient instance + +Before making `\ThePay\ApiClient\TheClient` instance, some dependencies must be prepared. + +If you use some DI container automation, all other dependencies than `TheConfig` +should be auto-injected even PSR interfaces if you have some implementations +already installed in your application. + +```php +/** @var \ThePay\ApiClient\TheConfig $theConfig */ + +// TheClient instance dependencies +$signatureService = new \ThePay\ApiClient\Service\SignatureService($theConfig); +/** @var \Psr\Http\Client\ClientInterface $httpClient some PSR-18 implementation */ +/** @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(); +// $requestFactory = $streamFactory = new \GuzzleHttp\Psr7\HttpFactory(); +$apiService = new \ThePay\ApiClient\Service\ApiService( + $theConfig, + $signatureService, + $httpClient, + $requestFactory, + $streamFactory +); + +$thePayClient = new \ThePay\ApiClient\TheClient( + $theConfig, + $apiService +); ``` ## Usual workflow @@ -124,31 +166,23 @@ Always create only one payment for your order for all payment creation options, For more examples see [create-payment.md](../doc/create-payment.md) -```php -use ThePay\ApiClient\TheConfig; -use ThePay\ApiClient\TheClient; -use ThePay\ApiClient\Model\CreatePaymentParams; +[See how to make TheClient](#theclient-instance) -$merchantId = '86a3eed0-95a4-11ea-ac9f-371f3488e0fa'; -$projectId = 3; -$apiPassword = 'secret'; -$apiUrl = 'https://demo.api.thepay.cz/'; // production: 'https://api.thepay.cz/' -$gateUrl = 'https://demo.gate.thepay.cz/'; // production: 'https://gate.thepay.cz/' +```php -$config = new TheConfig($merchantId, $projectId, $apiPassword, $apiUrl, $gateUrl); -$thePay = new TheClient($config); +/** @var \ThePay\ApiClient\TheClient $thePayClient */ // Render payment methods for payment (100,- Kč) -$paymentParams = new CreatePaymentParams(10000, 'CZK', 'uid124'); +$paymentParams = new \ThePay\ApiClient\Model\CreatePaymentParams(10000, 'CZK', 'uid124'); // display button, user will choose payment method at the payment gate -echo $thePay->getPaymentButton($paymentParams); +echo $thePayClient->getPaymentButton($paymentParams); // or buttons with available payment methods, payment method will be preselected -// echo $thePay->getPaymentButtons($paymentParams); +// echo $thePayClient->getPaymentButtons($paymentParams); // or just get payment link and redirect customer whenever you want -// $payment = $thePay->createPayment($createPayment); +// $payment = $thePayClient->createPayment($createPayment); // $redirectLink = $payment->getPayUrl(); ``` @@ -162,23 +196,14 @@ The state of payment must be checked at the time of customer return, since the p For example the customer simply returns to the e-shop without paying. #### General example of handling the customer return -```php -use ThePay\ApiClient\TheConfig; -use ThePay\ApiClient\TheClient; -use ThePay\ApiClient\Model\CreatePaymentParams; -$uid = $_GET["payment_uid"]; -$projectId = $_GET["project_id"]; +[See how to make TheClient](#theclient-instance) -$merchantId = '86a3eed0-95a4-11ea-ac9f-371f3488e0fa'; -$apiPassword = 'secret'; -$apiUrl = 'https://demo.api.thepay.cz/'; // production: 'https://api.thepay.cz/' -$gateUrl = 'https://demo.gate.thepay.cz/'; // production: 'https://gate.thepay.cz/' +```php -$config = new TheConfig($merchantId, $projectId, $apiPassword, $apiUrl, $gateUrl); -$thePay = new TheClient($config); +/** @var \ThePay\ApiClient\TheClient $thePayClient */ -$payment = $thePay->getPayment($uid); +$payment = $thePayClient->getPayment($uid); // check if the payment is paid if ($payment->wasPaid()) { @@ -191,21 +216,13 @@ if ($payment->wasPaid()) { It's basically the same as second step (customer return), it's triggered everytime the payment has changed, for example when the state of payment has been changed. -```php -use ThePay\ApiClient\TheConfig; -use ThePay\ApiClient\TheClient; -use ThePay\ApiClient\Model\CreatePaymentParams; +[See how to make TheClient](#theclient-instance) -$uid = $_GET["payment_uid"]; -$projectId = $_GET["project_id"]; +```php -$merchantId = '86a3eed0-95a4-11ea-ac9f-371f3488e0fa'; -$apiPassword = 'secret'; -$apiUrl = 'https://demo.api.thepay.cz/'; // production: 'https://api.thepay.cz/' -$gateUrl = 'https://demo.gate.thepay.cz/'; // production: 'https://gate.thepay.cz/' +/** @var \ThePay\ApiClient\TheClient $thePayClient */ -$config = new TheConfig($merchantId, $projectId, $apiPassword, $apiUrl, $gateUrl); -$thePay = new TheClient($config); +$payment = $thePayClient->getPayment($uid); // check if the payment is paid if ($payment->wasPaid()) { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2110ec0..92f9619 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: jobs: php82: - name: "php 8.2" + name: "php 8.2 psr/http-message 2.0" runs-on: ubuntu-latest container: "nofutur3/php-tests:8.2" steps: @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v3 - name: Install dependencies - run: composer install --no-interaction + run: composer update --no-interaction --with psr/http-message:^2.0 - name: Check code style run: composer cs-check @@ -26,6 +26,23 @@ jobs: - 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" + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install dependencies + run: composer update --no-interaction --with psr/http-message:^1.0 + + - name: Run static analysis + run: composer stan + + - name: Run tests + run: composer test + php81: name: "php 8.1" runs-on: ubuntu-latest @@ -77,7 +94,7 @@ jobs: run: composer install --no-interaction - name: Run static analysis - run: composer stan7 + run: composer stan - name: Run tests run: composer test diff --git a/composer.json b/composer.json index 41cc466..9e4ace2 100644 --- a/composer.json +++ b/composer.json @@ -4,14 +4,20 @@ "type": "library", "require": { "php": "~7.4|~8.0", - "ext-curl": "*", - "ext-json": "*" + "ext-json": "*", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0|^2.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "*", + "guzzlehttp/guzzle": "^7.7", "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^9.0" }, + "suggest": { + "guzzlehttp/guzzle": "Widly used implementation of PSR-7 (psr/http-message), PSR-17 (psr/http-factory) and PSR-18 (psr/http-client)" + }, "config": { "sort-packages": true }, @@ -35,9 +41,6 @@ "test": [ "vendor/bin/phpunit tests --log-junit ./test-reports/junit.xml" ], - "stan7": [ - "vendor/bin/phpstan analyse -c phpstan7.neon --memory-limit=1G" - ], "stan": [ "vendor/bin/phpstan analyse --memory-limit=1G" ] diff --git a/doc/change-payment-method-of-payment.md b/doc/change-payment-method-of-payment.md index c8ec15a..0fd46b9 100644 --- a/doc/change-payment-method-of-payment.md +++ b/doc/change-payment-method-of-payment.md @@ -6,10 +6,10 @@ This can be useful when you disallow to customer to change payment method in The ```php -/** @var \ThePay\ApiClient\TheClient $client */ +/** @var \ThePay\ApiClient\TheClient $thePayClient */ /** @var non-empty-string $paymentMethodCode one method selected by user */ -$client->changePaymentMethod('UID_OF_PAYMENT', $paymentMethodCode); +$thePayClient->changePaymentMethod('UID_OF_PAYMENT', $paymentMethodCode); ``` diff --git a/doc/create-payment-recommended.md b/doc/create-payment-recommended.md index 6e5a8fc..c2be3da 100644 --- a/doc/create-payment-recommended.md +++ b/doc/create-payment-recommended.md @@ -3,24 +3,10 @@ Example with optional detail information about customer. ```php -use ThePay\ApiClient\Model\Address; -use ThePay\ApiClient\Model\CreatePaymentCustomer; -use ThePay\ApiClient\TheConfig; -use ThePay\ApiClient\TheClient; -use ThePay\ApiClient\Model\CreatePaymentParams; - -$merchantId = '86a3eed0-95a4-11ea-ac9f-371f3488e0fa'; -$projectId = 3; -$apiPassword = 'secret'; -// Connection to demo for testing -$apiUrl = 'https://demo.api.thepay.cz/'; -$gateUrl = 'https://demo.gate.thepay.cz/'; - -$config = new TheConfig($merchantId, $projectId, $apiPassword, $apiUrl, $gateUrl); -$thePay = new TheClient($config); +/** @var \ThePay\ApiClient\TheClient $thePayClient */ // Create entity with information about customer -$customer = new CreatePaymentCustomer( +$customer = new \ThePay\ApiClient\Model\CreatePaymentCustomer( 'Mike', 'Smith', 'mike.smith@example.com', @@ -31,13 +17,13 @@ $customer = new CreatePaymentCustomer( ); // Create payment (105.20 € with unique id uid123) -$createPayment = new CreatePaymentParams(10520, 'EUR', 'uid123'); +$createPayment = new \ThePay\ApiClient\Model\CreatePaymentParams(10520, 'EUR', 'uid123'); $createPayment->setOrderId('15478'); $createPayment->setDescriptionForCustomer('Payment for items on example.com'); $createPayment->setDescriptionForMerchant('Payment from VIP customer XYZ'); $createPayment->setCustomer($customer); -$payment = $thePay->createPayment($createPayment); +$payment = $thePayClient->createPayment($createPayment); // Get url where user can pay echo $payment->getPayUrl(); // https://demo.gate.thepay.cz/5aa4f4af546a74848/pay/ @@ -48,11 +34,11 @@ echo $payment->getPayUrl(); // https://demo.gate.thepay.cz/5aa4f4af546a74848/pay In scenarios where you know the customer's preferred language, you can pass the language code in `CreatePaymentParams` constructor as the fourth argument. For example: ```php -$createPayment = new CreatePaymentParams(10520, 'EUR', 'uid123', 'en'); +$createPayment = new \ThePay\ApiClient\Model\CreatePaymentParams(10520, 'EUR', 'uid123', 'en'); ``` Possible values are described in ISO 639-1 standard. If you pass a language, that ThePay does not support, for example French (fr), then the English language will be used, as is the most likely best choice for the customer. However, if the customer changed their language in ThePay system, then this setting will not have any impact. You may wonder which language will be used if you do not enter any, then the language from TheConfig will be used, and if even here you did not select the default language, -the default language will be Czech (cs). \ No newline at end of file +the default language will be Czech (cs). diff --git a/doc/create-payment.md b/doc/create-payment.md index 1945e54..0ffb2c5 100644 --- a/doc/create-payment.md +++ b/doc/create-payment.md @@ -24,7 +24,7 @@ Let's prepare payment of 1 CZK: ### Redirect user to gate without payment method ```php - $button = $client->getPaymentButton($params); + $button = $thePayClient->getPaymentButton($params); ``` ### Redirect user to gate with specific payment method and/or specify custom button attributes @@ -36,7 +36,7 @@ and method selection step is for user skipped in ThePay system. /** @var non-empty-string $paymentMethodCode one method selected by user */ $buttonAttributes = array('class' => 'btn btn-success'); - $button = $client->getPaymentButton($params, 'Button text', true, $paymentMethodCode, $buttonAttributes); + $button = $thePayClient->getPaymentButton($params, 'Button text', true, $paymentMethodCode, $buttonAttributes); ``` ### Redirect user to gate with payment method selected @@ -46,7 +46,7 @@ Method **getPaymentButtons** returns HTML code with form sended by click on paym ```php /** @var string $paymentButtons */ // used default rendering - $paymentButtons = $client->getPaymentButtons($params); + $paymentButtons = $thePayClient->getPaymentButtons($params); // Filter payment methods by tag. If tags are empty, all available methods will be displayed. $onlyMethodsWithTags = array( \ThePay\ApiClient\ValueObject\PaymentMethodTag::ONLINE, @@ -58,12 +58,12 @@ Method **getPaymentButtons** returns HTML code with form sended by click on paym // only payment methods matched used filter will be rendered in HTML, // but be still available for user in payment process! $filter = new \ThePay\ApiClient\Filter\PaymentMethodFilter(array(), $onlyMethodsWithTags, $onlyMethodsWithoutTags); - $paymentButtons = $client->getPaymentButtons($params, $filter); + $paymentButtons = $thePayClient->getPaymentButtons($params, $filter); // used without css styles // third bool parameter disable default css styles and javascript for payment method buttons // css styles are rendered in