22
33## Content
44
5+ - [ Requirements] ( #requirements )
56- [ Configuration] ( #configuration )
6- - [ Factories available in DI container] ( #factories-available-in-di-container )
77- [ Services available in DI container] ( #services-available-in-di-container )
88- [ Usage] ( #usage )
9- - [ Official documentation] ( #official-documentation )
9+
10+ ## Requirements
11+
12+ This extension requires PSR-18 HTTP client and PSR-17 HTTP factories to be registered in your DI container.
13+
14+ The recommended implementation is [ Guzzle] ( https://github.com/guzzle/guzzle ) :
15+
16+ ``` bash
17+ composer require guzzlehttp/guzzle
18+ ```
19+
20+ You need to register the PSR interfaces in your neon config:
21+
22+ ``` neon
23+ services:
24+ - GuzzleHttp\Client
25+ - GuzzleHttp\Psr7\HttpFactory
26+ ```
1027
1128## Configuration
1229
13- You have to register this extension at first.
30+ Register the extension:
1431
1532``` neon
1633extensions:
@@ -21,223 +38,129 @@ List of all options:
2138
2239``` neon
2340contributte.thepay:
24- demo: true/false # if is true, extension rewrite merchant values with debug ones
25- merchant:
26- gateUrl: 'https://www.thepay.cz/gate/'
27- merchantId: (int)
28- accountId: (int)
29- password: ''
30- dataApiPassword: ''
31- webServicesWsdl: 'https://www.thepay.cz/gate/api/api-demo.wsdl'
32- dataWebServicesWsdl: 'https://www.thepay.cz/gate/api/data-demo.wsdl'
41+ demo: true/false
42+ merchantId: 'your-merchant-id'
43+ projectId: (int)
44+ apiPassword: ''
45+ apiUrl: 'https://api.thepay.cz/'
46+ gateUrl: 'https://gate.thepay.cz/'
47+ language: 'cs'
3348```
3449
3550Minimal production configuration:
3651
3752``` neon
3853contributte.thepay:
39- demo: false
40- merchant:
41- merchantId: (int)
42- accountId: (int)
43- password: ''
44- dataApiPassword: ''
54+ merchantId: 'your-merchant-id'
55+ projectId: (int)
56+ apiPassword: ''
4557```
4658
47- ## Factories available in DI container
59+ Demo configuration:
4860
49- - ` Contributte\ThePay\IPayment `
50- - ` Contributte\ThePay\IPermanentPayment `
51- - ` Contributte\ThePay\IReturnedPayment `
52- - ` Contributte\ThePay\Helper\IRadioMerchant `
61+ ``` neon
62+ contributte.thepay:
63+ demo: true
64+ merchantId: 'your-merchant-id'
65+ projectId: (int)
66+ apiPassword: ''
67+ ```
68+
69+ When ` demo: true ` is set, ` apiUrl ` and ` gateUrl ` are automatically switched to demo endpoints.
5370
5471## Services available in DI container
5572
56- - ` Contributte\ThePay\MerchantConfig `
57- - ` Contributte\ThePay\Helper\DataApi `
73+ - ` ThePay\ApiClient\TheConfig `
74+ - ` ThePay\ApiClient\Service\SignatureService `
75+ - ` ThePay\ApiClient\Service\ApiService ` (implements ` ApiServiceInterface ` )
76+ - ` ThePay\ApiClient\Service\GateService ` (implements ` GateServiceInterface ` )
77+ - ` ThePay\ApiClient\TheClient `
5878
5979## Usage
6080
61- Simple DTO for simple and type secure passing payment method information in the template
81+ ### Create a payment
6282
63- ` PaymentMethodDTO.php ` :
6483``` php
65- final class PaymentMethodDTO {
66- private string $paymentMethodName;
67- private string $paymentIcon;
68- private bool $isPaymentByCard;
84+ use ThePay\ApiClient\TheClient;
85+ use ThePay\ApiClient\Model\CreatePaymentParams;
86+ use Nette\Application\UI\Presenter;
87+
88+ class OrderPresenter extends Presenter
89+ {
6990
7091 public function __construct(
71- string $paymentMethodName,
72- string $paymentIcon,
73- bool $isPaymentByCard
74- ) {
75- $this->paymentMethodName = $paymentMethodName;
76- $this->paymentIcon = $paymentIcon;
77- $this->isPaymentByCard = $isPaymentByCard;
92+ private TheClient $thePayClient,
93+ )
94+ {
95+ parent::__construct();
7896 }
7997
80- public function getPaymentMethodName(): string {
81- return $this->paymentMethodName;
82- }
98+ public function actionPay(): void
99+ {
100+ $params = new CreatePaymentParams(10000, 'CZK', 'order-123');
101+ $payment = $this->thePayClient->createPayment($params);
83102
84- public function getPaymentIcon(): string {
85- return $this->paymentIcon;
103+ $this->redirectUrl($payment->getPayUrl());
86104 }
87105
88- public function isPaymentByCard(): bool {
89- return $this->isPaymentByCard;
90- }
91106}
92107```
93108
94- Prepare list of available payment methods
95-
96- ` OrderPresenter.php ` :
109+ ### Render payment buttons
97110
98111``` php
99- use Contributte\ ThePay\Helper\DataApi ;
100- use Contributte\ ThePay\Helper\IPaymentMethod ;
112+ use ThePay\ApiClient\TheClient ;
113+ use ThePay\ApiClient\Model\CreatePaymentParams ;
101114use Nette\Application\UI\Presenter;
102115
103- class OrderPresenter extend Presenter {
104- /**
105- * @inject
106- */
107- public DataApi $thePayDataApi;
108-
109- public function renderListMethods(): void {
110- $template = $this->getTemplate();
111- $paymentMethods = [];
112-
113- foreach ($this->thePayDataApi->getPaymentMethods()->getMethods() as $_paymentMethod) {
114- $paymentIcon = $this->thePayDataApi->getPaymentMethodIcon($_paymentMethod, '209x127');
115- $isPaymentByCard = $_paymentMethod->getId() === IPaymentMethod::CREDIT_CARD_PAYMENT_ID;
116- $paymentName = $_paymentMethod->getId();
117-
118- $paymentMethods[$_paymentMethod->getId()] = new PaymentMethodDTO(
119- $_paymentMethod->getName(),
120- $paymentIcon,
121- $isPaymentByCard
122- );
123- }
116+ class OrderPresenter extends Presenter
117+ {
124118
125- $template->paymentMethods = $paymentMethods;
119+ public function __construct(
120+ private TheClient $thePayClient,
121+ )
122+ {
123+ parent::__construct();
126124 }
127- }
128- ```
129125
130- ` Order/listMethods.latte ` :
131-
132- ``` latte
133- <ul>
134- <li n:foreach="$paymentMethods as $paymentMethodId => $paymentMethod">
135- <a n:href="pay paymentMethodId => $paymentMethodId">
136- <img n:if="$paymentMethod->getPaymentIcon() !== null" src="{$paymentMethod->getPaymentIcon()}" alt="{$paymentMethod->getPaymentMethodName()}" title="{$paymentMethod->getPaymentMethodName()}">
137- <span n:if="$paymentMethod->getPaymentIcon() === null">{$paymentMethod->getPaymentMethodName()}</span>
138- </a>
139- </li>
140- </ul>
126+ public function renderPaymentMethods(): void
127+ {
128+ $params = new CreatePaymentParams(10000, 'CZK', 'order-123');
129+ $this->template->paymentButtons = $this->thePayClient->getPaymentButtons($params);
130+ }
131+
132+ }
141133```
142134
143- Payment is configured and invoked using following code
135+ ### Verify a payment
144136
145137``` php
146- use Contributte\ ThePay\IPayment ;
138+ use ThePay\ApiClient\TheClient ;
147139use Nette\Application\UI\Presenter;
148- use Tp\Payment;
149-
150- class OrderPresenter extend Presenter {
151- //...
152-
153- /**
154- * @inject
155- */
156- public IPayment $tpPayment;
157-
158- public function actionPay(int $paymentMethodId): void {
159- $payment = $this->tpPayment->create();
160- assert($payment instanceof Payment);
161-
162- $payment->setMethodId($paymentMethodId);
163- $payment->setValue(1000.0);
164- $payment->setCurrency('CZK');
165- $payment->setMerchantData('local-payment-unique-id');
166- $payment->setMerchantSpecificSymbol('local-user-id');
167- $payment->setReturnUrl($this->link('//onlineConfirmation', ['cartId' => 'local-payment-unique-id']));
168- $payment->setBackToEshopUrl(
169- 'offlineConfirmation',
170- ['cartId' => 'local-payment-unique-id']
171- );
172-
173- $payment->redirectOnlinePayment($this);
174- }
175140
176- ...
177- }
178- ```
141+ class OrderPresenter extends Presenter
142+ {
179143
180- Now is user redirected to ThePay site, when payment is completed we receive:
181- - ` HEAD ` request to action ` offlineConfirmation ` with specified ` cartId `
182- - ` GET ` request to action ` onlineConfirmation ` with specified ` cartId `
144+ public function __construct(
145+ private TheClient $thePayClient,
146+ )
147+ {
148+ parent::__construct();
149+ }
183150
184- In each offline or online action is necessary to active validate received data e.g. like this
151+ public function actionConfirmation(string $paymentUid): void
152+ {
153+ $payment = $this->thePayClient->getPayment($paymentUid);
185154
186- ``` php
187- use Contributte\ThePay\Helper\DataApi;
188- use Contributte\ThePay\IReturnedPayment;
189- use Tp\InvalidSignatureException;
190- use Tp\ReturnedPayment;
191-
192- class OrderPresenter extend Presenter {
193- /**
194- * @inject
195- */
196- public IReturnedPayment $tpReturnedPayment;
197-
198- /**
199- * @inject
200- */
201- public DataApi $thePayDataApi;
202-
203- //...
204-
205- public function actionOnlineConfirmation(int $cartId): void {
206- $returnedPayment = $this->tpReturnedPayment->create();
207-
208- try {
209- if ($returnedPayment->verifySignature()) {
210- if (in_array($returnedPayment->getStatus(), [
211- ReturnedPayment::STATUS_OK,
212- ReturnedPayment::STATUS_WAITING,
213- ], TRUE)) {
214- //Demo gate doesn't allow active check...
215- if ($this->thePayDataApi->getMerchantConfig()->isDemo()) {
216- //Do not load thePayDataApi->getPayment
217-
218- if (bccomp(number_format($returnedPayment->getValue(), 2, '.', ''), '1000.00', 2) === 0) {
219- // everything is ok
220- }
221- }
222- else {
223- $paymentId = $returnedPayment->getPaymentId();
224- $payment = $this->thePayDataApi->getPayment($paymentId);
225-
226- if (bccomp(number_format($payment->getPayment()->getValue(), 2, '.', ''), '1000.00', 2) === 0) {
227- // everything is ok
228- }
229- }
230- }
231- }
232- }
233- catch (InvalidSignatureException $e) {
234- // TODO handle invalid request signature
155+ if ($payment->wasPaid()) {
156+ // payment was successful
235157 }
236158 }
159+
237160}
238161```
239162
240-
241163## Official documentation
242164
243- You can find an official documentation with examples here [ https://www.thepay.cz/ke-stazeni/ ] ( https://www.thepay.cz/ke-stazeni/ )
165+ - [ ThePay API Client] ( https://github.com/ThePay/api-client )
166+ - [ ThePay API Documentation] ( https://thepay.docs.apiary.io/ )
0 commit comments