Skip to content

Commit aeb2aa6

Browse files
authored
Replace contributte/thepay-api with thepay/api-client v2 (#103)
* feat: replace contributte/thepay-api with thepay/api-client v2 Migrate from old SOAP-based Tp\ namespace to new REST-based ThePay\ApiClient\ namespace. The DI extension now registers TheConfig, SignatureService, ApiService (as ApiServiceInterface), GateService (as GateServiceInterface), and TheClient. Removed all old wrapper classes (Payment, PermanentPayment, ReturnedPayment, DataApi, MerchantConfig, etc.) that extended Tp\ classes which no longer exist in the new package. Users must provide PSR-18/17 implementations (e.g. Guzzle) in their DI container for the HTTP client layer. * test: rewrite tests for new thepay/api-client integration Update DITest for new flat config structure (merchantId, projectId, apiPassword, apiUrl, gateUrl, language) with demo, production, and custom URL test cases. Add ContainerTest that compiles a full Nette DI container with stub PSR-18/17 implementations and verifies all services resolve by type. Remove TpPaymentTest that tested deleted Payment/MerchantConfig classes. * chore: add dependabot config with daily schedule and automerge
1 parent b2f4736 commit aeb2aa6

24 files changed

Lines changed: 332 additions & 770 deletions

.docs/README.md

Lines changed: 96 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,32 @@
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
1633
extensions:
@@ -21,223 +38,129 @@ List of all options:
2138

2239
```neon
2340
contributte.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

3550
Minimal production configuration:
3651

3752
```neon
3853
contributte.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;
101114
use 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;
147139
use 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/)

.github/dependabot.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "composer"
4+
directory: "/"
5+
schedule:
6+
interval: "daily"
7+
versioning-strategy: "increase"
8+
reviewers:
9+
- "trejjam"
10+
labels:
11+
- "automerge"
12+
13+
- package-ecosystem: "github-actions"
14+
directory: "/"
15+
schedule:
16+
interval: "daily"
17+
reviewers:
18+
- "trejjam"
19+
labels:
20+
- "automerge"

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ For details on how to use this package, check out our [documentation](.docs).
3434

3535
| State | Version | Branch | PHP |
3636
|-------------|---------|----------|----------|
37-
| dev | `^4.2` | `master` | `>= 7.1` |
38-
| stable | `^4.1` | `master` | `>= 7.1` |
39-
| stable | `^3.0` | `master` | `>= 5.6` |
37+
| dev | `^5.0` | `master` | `>= 8.2` |
38+
| stable | `^4.1` | `v4.x` | `>= 7.1` |
4039

4140
## Development
4241

composer.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@
1010
"license": "MIT",
1111
"require": {
1212
"php": "^8.2",
13-
"ext-soap": "*",
14-
"contributte/thepay-api": "^4.0.0",
15-
"nette/application": "^3.2.0",
1613
"nette/di": "^3.2.0",
17-
"nette/http": "^3.3.0"
14+
"nette/schema": "^1.3.0",
15+
"thepay/api-client": "^2.0.0"
1816
},
1917
"require-dev": {
2018
"contributte/phpstan": "~0.2.0",
@@ -41,7 +39,7 @@
4139
},
4240
"extra": {
4341
"branch-alias": {
44-
"dev-master": "v4.2.x-dev"
42+
"dev-master": "v5.0.x-dev"
4543
}
4644
}
4745
}

0 commit comments

Comments
 (0)