maguto / dilovod-sdk
PHP SDK for Dilovod API — Ukrainian online accounting and reporting service
2.0.0
2026-04-03 13:28 UTC
Requires
- php: ^8.2
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1 || ^2.0
- psr/log: ^2.0 || ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- guzzlehttp/guzzle: ^7.0
- nyholm/psr7: ^1.8
- php-http/mock-client: ^1.6
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
Suggests
- guzzlehttp/guzzle: PSR-18/PSR-17 HTTP client implementation (recommended)
- nyholm/psr7: Lightweight PSR-7/PSR-17 implementation
- symfony/http-client: Alternative PSR-18 HTTP client (Symfony ecosystem)
README
PHP SDK для роботи з Dilovod API — українським онлайн-сервісом бухгалтерського, управлінського обліку та звітності.
Версія 2.x — потребує PHP 8.2+. Для PHP 7.4+ дивіться гілку
1.x.
Встановлення
composer require maguto/dilovod-sdk
SDK потребує реалізації PSR-18 (HTTP client) та PSR-17 (HTTP factories). Рекомендовані пакети:
# Guzzle (найпопулярніший) composer require guzzlehttp/guzzle nyholm/psr7 # або тільки Nyholm + Symfony HTTP Client composer require nyholm/psr7 symfony/http-client
Швидкий старт
use Maguto\Dilovod\Config; use Maguto\Dilovod\DilovodClient; use Maguto\Dilovod\Enum\Operator; use Maguto\Dilovod\Transport\PsrTransport; use GuzzleHttp\Client as GuzzleClient; use Nyholm\Psr7\Factory\Psr17Factory; // Конфігурація $config = new Config( apiKey: 'ваш_api_ключ', // apiUrl: 'https://vps.example.com', // для VPS-серверів // clientId: 'my-app', // для партнерської статистики ); // Ініціалізація $psr17 = new Psr17Factory(); $transport = new PsrTransport( config: $config, httpClient: new GuzzleClient(['timeout' => 30]), requestFactory: $psr17, streamFactory: $psr17, // logger: $psrLogger, // опціонально, PSR-3 ); $client = new DilovodClient($config, $transport);
Основні методи
Отримання об'єкта за ID
$product = $client->getObject('1100300000022632'); $header = $product->get('header'); echo $header['name']['uk'];
Збереження об'єкта
// Створення $id = $client->saveObject( header: [ 'id' => 'catalogs.goods', 'name' => ['uk' => 'Новий товар', 'ru' => 'Новый товар'], ], ); // Оновлення $client->saveObject( header: ['id' => $id, 'name' => ['uk' => 'Оновлена назва']], ); // Створення та проведення документа use Maguto\Dilovod\Enum\SaveType; $client->saveObject( header: [ 'id' => 'documents.saleOrder', 'firm' => '1100400000001001', 'person' => '1100100000001001', 'currency' => '1101200000001001', 'date' => '2026-04-03 14:00:00', ], saveType: SaveType::Register, );
Позначка на видалення
$client->setDelMark('1100300000022632');
Query Builder
Fluent API для вибірки даних. Підтримує 5 типів запитів.
Важливо: alias, що використовується у
where(), повинен бути оголошений уfields().
Прямий запит до довідника
$products = $client->query('catalogs.goods') ->fields(['id' => 'good', 'code' => 'code', 'name' => 'name', 'parent.code' => 'parentCode']) ->where('parentCode', Operator::Equal, 101010) ->limit(50) ->get(); foreach ($products as $product) { echo $product['name'] . PHP_EOL; } // Отримати перший запис $first = $client->query('catalogs.firms') ->fields(['id' => 'id', 'name' => 'name']) ->first(); // Отримати значення одного поля з усіх записів $codes = $client->query('catalogs.goods') ->fields(['id' => 'id', 'code' => 'code']) ->withoutLinks() ->get() ->pluck('code');
Товарні залишки на дату
$stock = $client->query() ->balance('goods', '2025-01-01 00:00:00', ['good', 'storage']) ->fields([ 'good' => 'good', 'good.code' => 'code', 'storage' => 'storage', 'qty' => 'qty', ]) ->where('good', Operator::Equal, '1100300000022619') ->get();
Обороти за період
$sales = $client->query() ->turnover('saleIncomes', '2025-01-01', '2025-06-30', ['good', 'firm']) ->fields([ 'good' => 'good', 'good.code' => 'code', 'amountReciept' => 'income', ]) ->get();
Залишки + обороти
$report = $client->query() ->balanceAndTurnover('goods', '2025-01-01', '2025-06-30') ->fields([ 'good' => 'good', 'qtyStart' => 'start', 'qtyReceipt' => 'receipt', 'qtyExpense' => 'expense', 'qtyFinal' => 'final', ]) ->get();
Зріз актуальних значень (ціни)
$prices = $client->query() ->sliceLast('goodsPrices', new \DateTimeImmutable()) ->fields([ 'good' => 'good', 'priceType' => 'priceType', 'price' => 'price', 'currency' => 'currency', ]) ->where('priceType', Operator::Equal, '1101300000001002') ->get();
Мультимовні поля
При multilang() API змінює формат імен полів: name → name__uk, name__ru.
$result = $client->query('catalogs.firms') ->fields(['id' => 'id', 'name' => 'name']) ->multilang() ->get(); // $result->first() = ['id' => '...', 'name__uk' => '...', 'name__ru' => '...']
Швидкий режим (без збірки посилань)
$result = $client->query('catalogs.goods') ->fields(['id' => 'id', 'code' => 'code', 'name' => 'name']) ->withoutLinks() ->get(); // ResultSet містить columns $result->getColumns(); // ['id', 'code', 'name']
Створення замовлення покупця
$orderId = $client->createOrder() ->firm('1100400000001001') ->person('1100100000001001') ->remarkFromPerson('Зателефонуйте, будь ласка') ->addProduct('1100300000022632', qty: 1) ->addProduct('1100300000022876', qty: 2, price: 150.00) ->addProductByArticle('ART-001', qty: 3) ->withAutoPlacement() ->send();
Довільні спецметоди (call)
$response = $client->call('saleOrderCreate', [ 'header' => ['firm' => '1100400000001001', 'person' => '1100100000001001'], 'goods' => [['good' => '1100300000022632', 'qty' => 1]], ]);
Метадані
// Список усіх об'єктів системи $objects = $client->listMetadata('uk'); // Опис реквізитів об'єкта $meta = $client->getMetadata(objectName: 'catalogs.goods'); // або за ID $meta = $client->getMetadata(objectId: '1000000000001258');
Партнерська статистика
Увага: метод
getStatisticреалізовано за документацією, але не верифіковано реальним API (потребує налаштованої партнерської інтеграції).
$stats = $client->getStatistic( partnerApiKey: 'ваш_партнерський_ключ', dateFrom: new \DateTimeImmutable('2025-01-01'), dateTo: new \DateTimeImmutable('2025-12-31'), );
Webhook
use Maguto\Dilovod\Webhook\WebhookParser; // У вашому контролері $packetJson = $_GET['packet'] ?? ''; if (!WebhookParser::isValidSource($_SERVER['REMOTE_ADDR'])) { http_response_code(403); exit; } $event = WebhookParser::parse($packetJson); echo $event->action; // 'objectChanged' echo $event->objectName; // 'documents.saleOrder' echo $event->id; // '1109100000001038'
Value Objects
use Maguto\Dilovod\ValueObject\ObjectId; use Maguto\Dilovod\ValueObject\MultiLangString; // ObjectId — 16-значний ID з типом та номером $id = new ObjectId('1100300000022632'); $id->getPrefix(); // '11003' (тип — товари) $id->getNumber(); // '00000022632' $id->isSameType(new ObjectId('1100300000022876')); // true // MultiLangString — мультимовний рядок $name = MultiLangString::fromArray(['uk' => 'Товар', 'ru' => 'Товар']); echo $name->get('uk'); // 'Товар' echo $name; // 'Товар' (uk за замовчуванням)
Обробка помилок
use Maguto\Dilovod\Exception\ApiException; use Maguto\Dilovod\Exception\TransportException; use Maguto\Dilovod\Exception\DilovodException; try { $client->getObject('0000000000000000'); } catch (ApiException $e) { // Помилка від Dilovod API echo $e->getMessage(); // 'object with id ... not found' $e->getRawResponse(); // повний масив відповіді } catch (TransportException $e) { // Мережева помилка або HTTP 5xx echo $e->getHttpStatusCode(); // 502, null для мережевих } catch (DilovodException $e) { // Будь-яка помилка SDK }
Розробка
# Встановити залежності composer install # Запустити всі перевірки (стиль + аналіз + тести) composer check # Unit-тести composer test:unit # Інтеграційні тести (потребують API-ключ) cp .env.example .env # вкажіть DILOVOD_API_KEY composer test:integration # Виправити стиль коду composer cs:fix # Статичний аналіз (PHPStan level max) composer analyse
Вимоги
- PHP 8.2+
- Будь-яка реалізація PSR-18 HTTP client
- Будь-яка реалізація PSR-17 HTTP factories
Посилання
Ліцензія
MIT — дивіться LICENSE.