produman-org / kassa-php
PHP library for the Produman.Kassa API
Requires
- php: >=7.4.0
- ext-curl: *
- ext-json: *
- psr/log: ^1|^2|^3
- symfony/http-client: ^5.4|^6.0|^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.39
- phpunit/phpunit: ^9.6
This package is auto-updated.
Last update: 2024-05-11 08:55:39 UTC
README
Клиент для работы с онлайн кассой Продуман по API
Содержание
- Требования
- Установка
- Порядок работы с клиентом
- Примеры использования основных API методов
- Примеры использования сервисных API методов
- Примеры работы с исключениями
- Примеры использования RateLimit
Требования
PHP 7.4.0 (и выше) с расширениями json и curl
Установка
В консоли с помощью Composer
- Установите менеджер пакетов Composer.
- В консоли выполните команду
composer require produman-org/kassa-php
В файле composer.json своего проекта
- Добавьте строку
"produman-org/kassa-php": "^1.0"
в список зависимостей вашего проекта в файле composer.json
...
"require": {
"php": ">=7.4.0",
"produman-org/kassa-php": "^1.0"
...
- Обновите зависимости проекта. В консоли перейдите в каталог, где лежит composer.json, и выполните команду:
composer update
- В коде вашего проекта подключите автозагрузку файлов нашего клиента:
require __DIR__ . '/vendor/autoload.php';
Порядок работы с клиентом
- Для основных API запросов (справочники, операции или заказы) создайте экземпляр объекта клиента при помощи команды
buildClient
, задайте клиентский токен, идентификатор приложения и секретный ключ (их можно получить в личном кабинете Продуман).
use ProdumanApi\Builder; $client = Builder::buildClient( 'clientToken', 'appId', 'appSecret' );
-
Для сервисных API запросов (вебхуки и интеграции) создайте экземпляр объекта клиента при помощи команды
buildApplicationClient
(аналогично, как в примере выше, но без указанияclientToken
). -
Дополнительно, при создании клиента, можно скорректировать параметр
timeout
для curl запросов, а так же использовать логгер, реализующий интерфейсPsr\Log\LoggerInterface
. -
Вызовите нужный метод API в объекте
$client
. -
Для каждого API запроса клиент содержит в себе соответствующий метод. Методы, если требуется, в качестве параметра принимают объекты классов запросов
ProdumanApi\Request\...
. В качестве ответа, методы возвращают объекты классов ответовProdumanApi\Response\...
. -
Дополнительно имеется поддержка исключений
ProdumanApi\Exception\...
. Например, исключениеProdumanApi\Exception\ApiException
используется для вывода данных, описанных в разделе обработка ошибок API. -
В API Продуман имеются ограничения на количество и частоту запросов RateLimit. Для получения информации о текущем лимите в объекте клиента имеются соответствующие методы.
Примеры использования основных API методов
1. Инициализация клиента
use ProdumanApi\Builder; use ProdumanApi\Client\Client; use Example\Logger; $logger = new Logger(); /** @var Client $client */ $client = Builder::buildClient( 'clientToken', 'appId', 'appSecret' 30, $logger );
2. Справочник касс
use ProdumanApi\Request\Cashboxes\ListRequest; use ProdumanApi\Response\Cashboxes\ListDto; use ProdumanApi\Response\Cashboxes\CashboxDto; // касса по id /** @var CashboxDto $response */ $response = $client->cashboxes->get('1ee57a8d-f1b4-6764-9ec7-a537555944ab'); // список касс без фильтра /** @var ListDto $response */ $response = $client->cashboxes->list(); // список касс по фильтру $request = new ListRequest(); $request->limit = 2; $request->status = 'ACTIVE'; $request->cursor = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var ListDto $response */ $response = $client->cashboxes->list($request);
3. Справочник категорий внесений и выплат
use ProdumanApi\Request\CashMovementCategories\ListRequest; use ProdumanApi\Response\CashMovementCategories\ListDto; // список категорий внесений и выплат без фильтра /** @var ListDto $response */ $response = $client->cashMovementCategories->list(); // список категорий внесений и выплат по фильтру $request = new ListRequest(); $request->limit = 2; $request->type = 'IN'; $request->cursor = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var ListDto $response */ $response = $client->cashMovementCategories->list($request);
4. Справочник контрагентов
use ProdumanApi\Request\Counterparties\ListRequest; use ProdumanApi\Response\Counterparties\ListDto; // список контрагентов без фильтра /** @var ListDto $response */ $response = $client->counterparties->list(); // список контрагентов по фильтру $request = new ListRequest(); $request->limit = 2; $request->search = '123456789'; $request->cursor = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var ListDto $response */ $response = $client->counterparties->list($request);
5. Справочник сотрудников
use ProdumanApi\Request\Employees\ListRequest; use ProdumanApi\Response\Employees\ListDto; // список сотрудников без фильтра /** @var ListDto $response */ $response = $client->employees->list(); // список сотрудников по фильтру $request = new ListRequest(); $request->limit = 2; $request->status = 'ACTIVE'; $request->cursor = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var ListDto $response */ $response = $client->employees->list($request);
6. Работа с операциями
use ProdumanApi\Request\Operations\CashEditRequest; use ProdumanApi\Request\Operations\CreateCashIn; use ProdumanApi\Request\Operations\CreateKktInfo; use ProdumanApi\Request\Operations\ListRequest; use ProdumanApi\Request\Operations\CreateSell; use ProdumanApi\Request\Operations\CreateShiftOpen; use ProdumanApi\Request\Operations\CreateShiftClose; use ProdumanApi\Request\Operations\CreateXReport; use ProdumanApi\Request\Operations\DetailsShiftCloseModel; use ProdumanApi\Request\Operations\Model\ClientModel; use ProdumanApi\Request\Operations\Model\DetailsCashModel; use ProdumanApi\Request\Operations\Model\DetailsSellModel; use ProdumanApi\Request\Operations\Model\DetailsShiftCloseModel; use ProdumanApi\Request\Orders\Model\AgentSchemeModel; use ProdumanApi\Request\Orders\Model\PositionModel; use ProdumanApi\Request\Orders\Model\SupplierModel; use ProdumanApi\Response\Operations\ListDto; use ProdumanApi\Response\Operations\OperationDto; // операция по id /** @var OperationDto $response */ $response = $client->operations->get('1ee57a8d-f1b4-6764-9ec7-a537555944ab'); // список операций без фильтра /** @var ListDto $response */ $response = $client->operations->list(); // список операций по фильтру $request = new ListRequest(); $request->limit = 2; $request->status = 'COMPLETE'; $request->operationType = 'SELL'; $request->createdAtFrom = new \DateTime('- 1 year'); $request->createdAtTo = new \DateTime('now'); $request->cursor = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var ListDto $response */ $response = $client->operations->list($request); // повтор операции по id /** @var OperationDto $response */ $response = $client->operations->retry('1ee57a8d-f1b4-6764-9ec7-a537555944ab'); // редактирование операции с наличными $request = new CashEditRequest(); $request->cashMovementCategoryId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; $request->comment = 'Тестовый комментарий'; /** @var OperationDto $response */ $response = $client->operations->cashMovementEdit('1ee57a8d-f1b4-6764-9ec7-a537555944ab', $request); //создание операции X-отчет $request = new CreateXReport(); $request->cashboxId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var OperationDto $response */ $response = $client->operations->create($request); // создание операции открытия смены $request = new CreateShiftOpen(); $request->cashboxId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var OperationDto $response */ $response = $client->operations->create($request); // создание операции закрытия смены $details = new DetailsShiftCloseModel(); $details->onlyCashbox = true; $request = new CreateShiftClose(); $request->cashboxId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; $request->details = $details; /** @var OperationDto $response */ $response = $client->operations->create($request); // создание операции информации о ККТ $request = new CreateKktInfo(); $request->cashboxId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var OperationDto $response */ $response = $client->operations->create($request); // создание операции внесения наличных $details = new DetailsCashModel(); $details->cashMovementCategoryId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; $details->comment = 'Тестовый комментарий'; $details->amount = 10.00; $request = new CreateCashIn(); $request->cashboxId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; $request->details = $details; /** @var OperationDto $response */ $response = $client->operations->create($request); // создание операции прихода без заказа с действием формирования чека (actionType="PREPARE") $operationClient = new ClientModel(); $operationClient->name = 'Тестовый клиент'; $operationClient->inn = '485466710568'; $supplier = new SupplierModel(); $supplier->name = 'Тестовый поставщик'; $supplier->inn = '485466710568'; $supplier->phone = '+79999999999'; $agentScheme = new AgentSchemeModel(); $agentScheme->agentSign = 'ANOTHER_AGENT'; $agentScheme->supplier = $supplier; $position = new PositionModel(); $position->name = 'Тестовая позиция'; $position->quantity = 2; $position->price = 10.00; $position->paymentVat = 'WITHOUT'; $position->paymentObject = 'PRODUCT'; $position->paymentMethod = 'FULL_PAYMENT'; $position->excisable = false; $position->agentScheme = $agentScheme; $position->marks = [ '010641944077751221s40h&mLFSVODA93TEST', ]; $details = new DetailsSellModel(); $details->actionType = 'PREPARE'; $details->taxationSystem = 'OSN'; $details->client = $operationClient; $details->positions = [$position]; $request = new CreateSell(); $request->cashboxId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; $request->details = $details; /** @var OperationDto $response */ $response = $client->operations->create($request); // создание операции прихода без заказа с действием регистрации чека (actionType="EXECUTE") $paymentSolution = new PaymentSolutionModel(); $paymentSolution->id = 1; $paymentSolution->amount = 20.0; $operationClient = new ClientModel(); $operationClient->name = 'Тестовый клиент'; $operationClient->inn = '485466710568'; $supplier = new SupplierModel(); $supplier->name = 'Тестовый поставщик'; $supplier->inn = '485466710568'; $supplier->phone = '+79999999999'; $agentScheme = new AgentSchemeModel(); $agentScheme->agentSign = 'ANOTHER_AGENT'; $agentScheme->supplier = $supplier; $position = new PositionModel(); $position->name = 'Тестовая позиция'; $position->quantity = 2; $position->price = 10.00; $position->paymentVat = 'WITHOUT'; $position->paymentObject = 'PRODUCT'; $position->paymentMethod = 'FULL_PAYMENT'; $position->excisable = false; $position->agentScheme = $agentScheme; $position->marks = [ '010641944077751221s40h&mLFSVODA93TEST', ]; $details = new DetailsSellModel(); $details->actionType = 'EXECUTE'; $details->taxationSystem = 'OSN'; $details->client = $operationClient; $details->receiptContact = 'test@test.ru'; $details->print = true; $details->settlementPlace = 'Россия, Москва'; $details->paymentSolutions = [$paymentSolution]; $details->positions = [$position]; $request = new CreateSell(); $request->cashboxId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; $request->details = $details; /** @var OperationDto $response */ $response = $client->operations->create($request); // остальные типы операций создаются аналогично
7. Работа с заказами
use ProdumanApi\Request\Orders\CreateRequest; use ProdumanApi\Request\Orders\ListRequest; use ProdumanApi\Request\Orders\Model\AgentSchemeModel; use ProdumanApi\Request\Orders\Model\ClientModel; use ProdumanApi\Request\Orders\Model\DeliveryModel; use ProdumanApi\Request\Orders\Model\PaymentAgentModel; use ProdumanApi\Request\Orders\Model\PositionModel; use ProdumanApi\Request\Orders\Model\ReceivePaymentsOperatorModel; use ProdumanApi\Request\Orders\Model\SupplierModel; use ProdumanApi\Request\Orders\Model\TransferOperatorModel; use ProdumanApi\Response\Orders\ListDto; use ProdumanApi\Response\Orders\OrderDto; // заказ по id /** @var OrderDto $response */ $response = $client->orders->get('1ee57a8d-f1b4-6764-9ec7-a537555944ab'); // список заказов без фильтра /** @var ListDto $response */ $response = $client->orders->list(); // список заказов по фильтру $request = new ListRequest(); $request->limit = 2; $request->totalAmountFrom = 100; $request->totalAmountTo = 100000; $request->createdAtFrom = new \DateTime('- 1 year'); $request->createdAtTo = new \DateTime('now'); $request->cursor = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; /** @var ListDto $response */ $response = $client->orders->list($request); // создание заказа $orderClient = new ClientModel(); $orderClient->name = 'Тестовый клиент'; $orderClient->inn = '485466710568'; $orderClient->email = 'test@test.ru'; $orderClient->phone = '+79999999999'; $delivery = new DeliveryModel(); $delivery->courierId = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; $delivery->address = 'Россия, Москва'; $delivery->dateFrom = new \DateTime('- 1 min'); $delivery->dateTo = new \DateTime('+ 1 min'); $delivery->status = 'MOVED'; $delivery->comment = 'Тестовый комментарий'; $delivery->prepaid = false; $paymentAgent = new PaymentAgentModel(); $paymentAgent->phone = '+79999999999'; $paymentAgent->operation = 'Пополнение счета'; $transferOperator = new TransferOperatorModel(); $transferOperator->name = 'ПАО КИВИ БАНК'; $transferOperator->inn = '485466710568'; $transferOperator->phone = '+79999999999'; $transferOperator->address = 'Россия, Москва'; $supplier = new SupplierModel(); $supplier->name = 'Тестовый поставщик'; $supplier->inn = '485466710568'; $supplier->phone = '+79999999999'; $agentScheme = new AgentSchemeModel(); $agentScheme->agentSign = 'BANK_PAYING_AGENT'; $agentScheme->paymentAgent = $paymentAgent; $agentScheme->transferOperator = $transferOperator; $agentScheme->supplier = $supplier; $position = new PositionModel(); $position->name = 'Тестовая позиция'; $position->quantity = 2; $position->price = 10.00; $position->paymentVat = 'WITHOUT'; $position->paymentObject = 'PRODUCT'; $position->paymentMethod = 'FULL_PAYMENT'; $position->excisable = false; $position->agentScheme = $agentScheme; $position->marks = [ '010641944077751221s40h&mLFSVODA93TEST', ]; $request = new CreateRequest(); $request->createdById = '1ee57a8d-f1b4-6764-9ec7-a537555944ab'; $request->externalId = '1234567890'; $request->taxationSystem = 'OSN'; $request->client = $orderClient; $request->delivery = $delivery; $request->positions[] = $position; /** @var OrderDto $response */ $response = $client->orders->create($request); // обновление заказа по id (запрос с таким же объектом $request, что и при создании) /** @var OrderDto $response */ $response = $client->orders->update('1ee57a8d-f1b4-6764-9ec7-a537555944ab', $request); // удаление заказа по id $client->orders->delete('1ee57a8d-f1b4-6764-9ec7-a537555944ab');
Примеры использования сервисных API методов
1. Инициализация клиента сервисных запросов
use ProdumanApi\Builder; use ProdumanApi\Client\ApplicationClient; use Example\Logger; $logger = new Logger(); /** @var ApplicationClient $client */ $client = Builder::buildApplicationClient( 'appId', 'appSecret' 30, $logger );
2. Вебхуки
use ProdumanApi\Request\Webhooks\EndpointCreateRequest; use ProdumanApi\Request\Webhooks\EndpointListRequest; use ProdumanApi\Request\Webhooks\EndpointTestRequest; use ProdumanApi\Response\Webhooks\EndpointDto; use ProdumanApi\Response\Webhooks\EndpointListDto; // эндпоинт по id /** @var EndpointDto $response */ $response = $client->webhooks->endpointGet('1ee30707-89ed-696a-8501-a1e907a309b2'); // список эндпоинтов без фильтра /** @var EndpointListDto $response */ $response = $client->webhooks->endpointList(); // список эндпоинтов по фильтру $request = new EndpointListRequest(); $request->limit = 2; $request->status = 'ACTIVE'; /** @var EndpointListDto $response */ $response = $client->webhooks->endpointList($request); // создание эндпоинта $request = new EndpointCreateRequest(); $request->status = 'INACTIVE'; $request->url = 'https://rra.ru'; $request->authType = 'BEARER_TOKEN'; $request->secret = '1234567890'; $request->events = ['OPERATION_FAILED']; /** @var EndpointDto $response */ $response = $client->webhooks->endpointCreate($request); // обновление эндпоинта по id (запрос с таким же объектом $request, что и при создании) /** @var EndpointDto $response */ $response = $client->webhooks->endpointUpdate('1eeed9f2-a669-6fde-ad9f-1982a8a5337a', $request); // удаление эндпоинта $client->webhooks->endpointDelete('1ee921aa-9827-69d6-b16d-9f7549035bae'); // тестовая отправка вебхука с заданным событием $request = new EndpointTestRequest(); $request->event = 'INTEGRATION_REQUEST_COMPLETED'; $request->skipVerify = true; $client->webhooks->endpointTest($request);
3. Интеграции
use ProdumanApi\Request\Integrations\CreateConnectRequest; use ProdumanApi\Response\Integrations\IntegrationConnectDto; use ProdumanApi\Response\Integrations\IntegrationDto; // интеграция по id /** @var IntegrationDto $response */ $response = $client->integrations->get('1ee879f7-0eff-6092-9dc9-5d26875ad7b4'); // деактивация интеграции по id $client->integrations->deactivate('1ee879f7-0eff-6092-9dc9-5d26875ad7b4'); // запрос на создание новой интеграции $request = new CreateConnectRequest(); $request->email = 'test@test.ru'; /** @var IntegrationConnectDto $response */ $response = $client->integrations->create($request);
Примеры работы с исключениями
use ProdumanApi\Builder; use ProdumanApi\Response\Cashboxes\CashboxDto; use ProdumanApi\Exception\ApiException; use ProdumanApi\Exception\HttpException; use ProdumanApi\Exception\JsonResponseException; $client = Builder::buildClient( 'clientToken', 'appId', 'appSecret' ); try { // касса по id /** @var CashboxDto $response */ $response = $client->cashboxes->get('1ee879f7-0eff-6092-9dc9-5d26875ad7b4'); } catch (ApiException $e) { var_dump('API error: ' . $e->getApiMessage() . '|' . $e->getApiCode() . '|' . print_r($e->getApiDetails(), true) . '|' . $e->getStatusCode()); } catch (HttpException $e) { var_dump('HTTP error: ' . $e->getMessage()); } catch (JsonResponseException $e) { var_dump('JSON response error: ' . $e->getMessage()); } catch (\Exception $e) { var_dump('Other error: ' . get_class($e) . ': ' . $e->getMessage()); }
Примеры использования RateLimit
use ProdumanApi\Builder; $client = Builder::buildClient( 'clientToken', 'appId', 'appSecret' ); // квота var_dump($client->getLastXRateLimitRemaining()); // текущий остаток квоты var_dump($client->getLastXRateLimitLimit()); // HTTP-код ответа последнего запроса var_dump($client->getLastStatusCode());