Skip to content
Merged
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
83 changes: 83 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Changelog

This file documents notable changes to the library.

## [3.3.0] - 2026-07-23

### Added

- Support for the CloudPayments `test` endpoint.
- Creation of payment links and retrieval of QR codes for SBP payments:
`payments/qr/sbp/link` and `payments/qr/sbp/image`.
- Retrieval of the list of banks participating in SBP via `sbp/v2/banks/info`.
- Lookup of the latest operation by invoice ID via `v2/payments/find`.
- Retrieval of payment operations for an arbitrary date range via
`v2/payments/list`.
- Retrieval of chargebacks via `chargebacks/list`.
- Typed request and response DTOs and enums for the new endpoints.
- The `CloudpaymentsData` DTO for building structured `JsonData`.
- Additional fiscal receipt requisites and VAT rates `5`, `7`, `22`, `5/105`,
`7/107`, and `22/122`.
- The `errorCode` field in `CloudResponse`.

### Changed

- Stricter type validation for the main CloudPayments response fields.
- `TransactionArrayResponse::model` now defaults to an empty array.

### Backward compatibility

- Existing API methods and their signatures remain unchanged.
- Support for the new endpoints does not change the behavior of existing
integrations.

## [3.2.4] - 2026-06-09

### Added

- PHPUnit, PHPStan, PHP CS Fixer, and Rector checks in CI.
- Tests for the API client, request and response DTOs, models, and webhook
handlers.
- Expanded documentation covering installation, configuration, and usage.

### Changed

- Improved static typing without changing the public API.
- Updated the code to comply with PHPStan and Rector rules.

## [3.2.3] - 2026-06-08

### Added

- A CI test matrix for PHP `8.1-8.5`.
- Missing transaction model fields.
- `BaseModel::getAdditionalProperties()` for accessing unknown fields returned
by CloudPayments.

### Fixed

- Unknown response fields no longer create dynamic model properties.

## [3.2.2] - 2025-06-10

### Added

- Composer Normalizer and Composer Bin Plugin.
- Isolated environments for PHPStan, PHP CS Fixer, and Rector.
- Makefile commands for dependency installation, testing, and code quality
checks.

### Changed

- Development tool caches moved to the `tmp` directory.

## [3.2.1] - 2025-06-10

### Added

- Initial release of the CloudPayments PHP client.
- Support for card and token payments, refunds, confirmations, and voids.
- Support for subscriptions, orders, notifications, fiscal receipts, and
Apple Pay.
- Request and response DTOs, response models, enums, and webhook handlers.
- Basic PHPUnit tests and code quality tools.
52 changes: 51 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,13 @@ if ($response->is3dsError()) {
| `payments/token/topup` | `paymentsTokenTopup` | `TokenTopUp` | `TransactionResponse` |
| `payments/get` | `getPaymentData` | `PaymentsGet` | `TransactionResponse` |
| `payments/find` | `getPaymentDataByInvoice` | `PaymentsFind` | `TransactionResponse` |
| `v2/payments/find` | `getPaymentDataByInvoiceV2` | `PaymentsFind` | `TransactionResponse` |
| `payments/list` | `getListPayment` | `PaymentsList` | `TransactionArrayResponse` |
| `v2/payments/list` | `getListPaymentV2` | `PaymentsListV2` | `TransactionArrayResponse` |
| `chargebacks/list` | `chargebacksList` | `ChargebacksList` | `ChargebackArrayResponse` |
| `payments/qr/sbp/link` | `paymentsQrSbpLink` | `SbpLink` | `QrLinkResponse` |
| `payments/qr/sbp/image` | `paymentsQrSbpImage` | `SbpLink` | `QrLinkResponse` |
| `sbp/v2/banks/info` | `sbpV2BanksInfo` | `SbpBanksInfo` или `null` | `SbpBanksInfoResponse` |
| `payments/tokens/list` | `paymentsTokensList` | `TokenList` или `null` | `TokenArrayResponse` |
| `subscriptions/create` | `subscriptionsCreate` | `SubscriptionCreate` | `SubscriptionResponse` |
| `subscriptions/get` | `subscriptionsGet` | `SubscriptionGet` | `SubscriptionResponse` |
Expand All @@ -125,6 +131,13 @@ if ($response->is3dsError()) {
| `site/notifications/{Type}/update` | `siteNotificationsUpdate` | `NotificationsUpdate` | `CloudResponse` |
| `applepay/startsession` | `startSession` | `ApplepayStartSession` | `AppleSessionResponse` |
| `kkt/receipt` | `createReceipt` | `KktReceipt` | `KktReceiptResponse` |
| `test` | `test` | — | `CloudResponse` |

`payments/find` сохраняется для обратной совместимости. `v2/payments/find` ищет последнюю операцию среди платежей, возвратов и выплат на карту.

`payments/list` выгружает операции за один день. `v2/payments/list` выгружает операции за произвольный период, использует пагинацию и необязательный фильтр статусов. `pageNumber` начинается с 1, одна страница содержит не более 100 операций. Порядок ответа сохраняется библиотекой.

`chargebacks/list` выгружает претензии за период не больше одного календарного года. `pageNumber` начинается с 1, одна страница содержит не более 100 претензий. Библиотека сохраняет порядок ответа CloudPayments. Поле `ErrorCode` доступно через `$response->errorCode`.

## Запросы

Expand All @@ -144,9 +157,38 @@ DTO наследуются от `BaseRequest` и преобразуются в

- `amount` превращается в `Amount`;
- значения `null` не попадают в запрос;
- `true` и `false` передаются как строковые значения, ожидаемые API;
- `true` и `false` в полях Request DTO передаются как строковые значения, ожидаемые API;
- вложенные DTO и массивы DTO преобразуются рекурсивно.

Для структурированных данных `JsonData` можно использовать общий DTO `CloudpaymentsData`. Он добавляет обязательную для CloudPayments обёртку `cloudpayments` и переиспользует `CustomerReceipt` во всех платежных методах, поддерживающих `JsonData`:

```php
use Excent\Cloudpayments\Enum\Currency;
use Excent\Cloudpayments\Enum\SbpScheme;
use Excent\Cloudpayments\Request\SbpLink;
use Excent\Cloudpayments\Request\CloudpaymentsData;
use Excent\Cloudpayments\Request\Receipt\CustomerReceipt;
use Excent\Cloudpayments\Request\Receipt\ReceiptItem;

$jsonData = new CloudpaymentsData(
customerReceipt: new CustomerReceipt([
new ReceiptItem('Товар', '100.00', '1.00', '100.00'),
]),
additionalData: ['name' => 'Покупатель'],
);

$request = new SbpLink(
'1000.00',
Currency::RUB,
SbpScheme::CHARGE,
jsonData: $jsonData,
);
```

Для `SbpLink` используются типизированные enum-поля `Currency::RUB`, `SbpScheme::CHARGE` и `Device`. Поля `Os` и `Browser` остаются строковыми, поскольку API допускает новые значения. Поле `jsonData` принимает только `CloudpaymentsData`; для существующих DTO со строковым `JsonData` используется `$jsonData->asJson()`.

`CustomerReceipt` является общим DTO для чеков и не привязан к СБП. Вложенные реквизиты представлены DTO `UserRequisiteData`, `OperationReceiptRequisite`, `IndustryRequisiteCollection[]` и `NonCashPayments[]`; `RussiaTimeZone` принимает RTZ enum-коды `1–11`.

Некоторые DTO для совместимости с существующим публичным контрактом заполняются через публичные свойства:

```php
Expand All @@ -169,23 +211,31 @@ $client->siteNotificationsUpdate($request);
| `success` | Результат операции из поля `Success`. |
| `message` | Сообщение из поля `Message`. |
| `warning` | Предупреждение из поля `Warning`. |
| `errorCode` | Код ошибки из поля `ErrorCode`. |
| `model` | Модель ответа, тип зависит от вызванного метода. |

Поддерживаемые модели:

| Response DTO | Model |
|--------------|-------|
| `AppleSessionResponse` | `AppleSessionModel` |
| `ChargebackArrayResponse` | `ChargebackModel[]` |
| `KktReceiptResponse` | `KktReceiptModel` |
| `NotificationResponse` | `NotificationModel` |
| `OrderResponse` | `OrderModel` |
| `QrLinkResponse` | `QrLinkModel` |
| `SbpBanksInfoResponse` | `SbpBanksInfoModel[]` |
| `SubscriptionResponse` | `SubscriptionModel` |
| `SubscriptionArrayResponse` | `SubscriptionModel[]` |
| `TokenArrayResponse` | `TokenModel[]` |
| `TransactionResponse` | `TransactionModel` |
| `TransactionArrayResponse` | `TransactionModel[]` |
| `TransactionWith3dsResponse` | `TransactionWith3dsModel` |

`SbpBanksInfoResponse` содержит массив источников (`SbpBanksInfoModel`), а `members` каждого источника — типизированный массив банков (`SbpBankMemberModel`). Библиотека сохраняет исходный порядок источников и банков и не изменяет значения `name`, `logo` и `url`.

Для `paymentsQrSbpImage` значение `model->qrImage` содержит PNG-код, закодированный в Base64, и возвращается библиотекой без декодирования. Значение `model->qrUrl` для этого метода равно `null`. Один QR-код СБП можно использовать для многократной оплаты.

Если CloudPayments вернет поля, которых нет в модели, они будут доступны через `getAdditionalProperties()`.

```php
Expand Down
21 changes: 21 additions & 0 deletions src/Enum/CloudMethodsEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ enum CloudMethodsEnum: string
/** Проверка платежа по номеру заказа */
case PAYMENTS_FIND = 'payments/find';

/** Проверка последней операции по номеру заказа, включая возвраты и выплаты на карту */
case V2_PAYMENTS_FIND = 'v2/payments/find';

/** Проверка платежа */
case PAYMENTS_GET = 'payments/get';

Expand All @@ -35,6 +38,21 @@ enum CloudMethodsEnum: string
/** Список транзакций за определенное время */
case PAYMENTS_LIST = 'payments/list';

/** Список транзакций за произвольный период */
case V2_PAYMENTS_LIST = 'v2/payments/list';

/** Список претензий за произвольный период */
case CHARGEBACKS_LIST = 'chargebacks/list';

/** Создание ссылки на оплату через СБП */
case PAYMENTS_QR_SBP_LINK = 'payments/qr/sbp/link';

/** Получение QR-кода для оплаты через СБП */
case PAYMENTS_QR_SBP_IMAGE = 'payments/qr/sbp/image';

/** Список участников СБП */
case SBP_V2_BANKS_INFO = 'sbp/v2/banks/info';

/** Отмена оплаты */
case PAYMENTS_VOID = 'payments/void';

Expand Down Expand Up @@ -79,4 +97,7 @@ enum CloudMethodsEnum: string

/** Создание чека */
case KKT_RECEIPT = 'kkt/receipt';

/** Тестовый метод */
case TEST = 'test';
}
40 changes: 40 additions & 0 deletions src/Enum/Currency.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Excent\Cloudpayments\Enum;

/**
* Валюты CloudPayments.
*/
enum Currency: string
{
case RUB = 'RUB';
case EUR = 'EUR';
case USD = 'USD';
case GBP = 'GBP';
case UAH = 'UAH';
case BYR = 'BYR';
case BYN = 'BYN';
case KZT = 'KZT';
case AZN = 'AZN';
case CHF = 'CHF';
case CZK = 'CZK';
case CAD = 'CAD';
case PLN = 'PLN';
case SEK = 'SEK';
case TRY = 'TRY';
case CNY = 'CNY';
case INR = 'INR';
case BRL = 'BRL';
case ZAR = 'ZAR';
case UZS = 'UZS';
case BGN = 'BGN';
case RON = 'RON';
case AUD = 'AUD';
case HKD = 'HKD';
case GEL = 'GEL';
case KGS = 'KGS';
case AMD = 'AMD';
case AED = 'AED';
}
15 changes: 15 additions & 0 deletions src/Enum/Device.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Excent\Cloudpayments\Enum;

/**
* Тип устройства плательщика для оплаты через СБП.
*/
enum Device: string
{
case MOBILE_APP = 'MobileApp';
case DESKTOP_WEB = 'DesktopWeb';
case MOBILE = 'Mobile';
}
44 changes: 44 additions & 0 deletions src/Enum/RussiaTimeZone.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Excent\Cloudpayments\Enum;

/**
* Часовые зоны места расчёта в формате RTZ для CustomerReceipt.
*/
enum RussiaTimeZone: int
{
/** Калининград (EET). */
case RTZ_1 = 1;

/** Волгоград, Москва, Санкт-Петербург, Минск (MSK). */
case RTZ_2 = 2;

/** Ижевск, Самара (SAMT). */
case RTZ_3 = 3;

/** Екатеринбург (YEKT). */
case RTZ_4 = 4;

/** Новосибирск (NOVT). */
case RTZ_5 = 5;

/** Красноярск (KRAT). */
case RTZ_6 = 6;

/** Иркутск (IRKT). */
case RTZ_7 = 7;

/** Якутск (YAKT). */
case RTZ_8 = 8;

/** Владивосток, Магадан (VLAT). */
case RTZ_9 = 9;

/** Чокурдах (SAKT). */
case RTZ_10 = 10;

/** Анадырь, Петропавловск-Камчатский (ANAT). */
case RTZ_11 = 11;
}
15 changes: 15 additions & 0 deletions src/Enum/SbpPlatform.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Excent\Cloudpayments\Enum;

/**
* Платформа клиента для получения списка участников СБП.
*/
enum SbpPlatform: string
{
case DESKTOP = 'desktop';
case IOS = 'ios';
case ANDROID = 'android';
}
13 changes: 13 additions & 0 deletions src/Enum/SbpScheme.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Excent\Cloudpayments\Enum;

/**
* Схемы проведения платежа через СБП.
*/
enum SbpScheme: string
{
case CHARGE = 'charge';
}
13 changes: 13 additions & 0 deletions src/Enum/TransactionStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Excent\Cloudpayments\Enum;

enum TransactionStatus: string
{
case AUTHORIZED = 'Authorized';
case COMPLETED = 'Completed';
case CANCELLED = 'Cancelled';
case DECLINED = 'Declined';
}
Loading
Loading