Разработка типизированного SDK для API 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка типизированного SDK для API 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка типизированного SDK для API 1С-Битрикс

Написание интеграций с 1С-Битрикс без SDK — это постоянный copy-paste кода авторизации, ручная сериализация запросов, строковые имена методов без автодополнения. Через полгода проект превращается в нечитаемый клубок curl_exec() с json_decode(). Типизированный SDK решает это: каждый метод API — отдельный класс или метод с PHPDoc, автодополнение в IDE, единая точка конфигурации, встроенная обработка ошибок.

Что такое SDK для Битрикс

SDK в данном контексте — это PHP-библиотека, которая инкапсулирует работу с одним из API:

  1. REST API Битрикс24 (облачный и коробочный) — методы вида crm.lead.add, tasks.task.update.
  2. API 1С-Битрикс (сайт) — внутренние классы CIBlockElement, \Bitrix\Sale\Order, D7 ORM.
  3. Webhook API — входящие и исходящие вебхуки Битрикс24.

Чаще всего SDK разрабатывается для REST API Битрикс24 — им пользуются внешние приложения и интеграции.

Структура типизированного REST API SDK

src/
├── Client/
│   ├── BitrixClient.php          # HTTP-клиент (Guzzle/native curl)
│   ├── TokenStorage.php          # Хранение OAuth-токенов
│   └── RetryMiddleware.php       # Повторные попытки при 503/rate limit
├── Api/
│   ├── Crm/
│   │   ├── LeadApi.php
│   │   ├── DealApi.php
│   │   ├── ContactApi.php
│   │   └── CompanyApi.php
│   ├── Tasks/
│   │   ├── TaskApi.php
│   │   └── CommentApi.php
│   └── Catalog/
│       ├── ProductApi.php
│       └── PriceApi.php
├── Dto/
│   ├── Crm/
│   │   ├── Lead.php
│   │   ├── LeadCreateRequest.php
│   │   └── LeadListRequest.php
│   └── Common/
│       ├── Pagination.php
│       └── Filter.php
├── Exception/
│   ├── BitrixApiException.php
│   ├── AuthException.php
│   └── RateLimitException.php
└── BitrixSdk.php                 # Точка входа / DI-контейнер

HTTP-клиент

namespace BitrixSdk\Client;

class BitrixClient
{
    private string $baseUrl;
    private TokenStorage $tokenStorage;
    private \GuzzleHttp\Client $http;

    public function __construct(string $baseUrl, TokenStorage $tokenStorage)
    {
        $this->baseUrl      = rtrim($baseUrl, '/') . '/rest/';
        $this->tokenStorage = $tokenStorage;
        $this->http         = new \GuzzleHttp\Client([
            'timeout'         => 30,
            'connect_timeout' => 10,
        ]);
    }

    public function call(string $method, array $params = []): array
    {
        $token  = $this->tokenStorage->getAccessToken();
        $url    = $this->baseUrl . $method;

        try {
            $response = $this->http->post($url, [
                'json' => array_merge($params, ['auth' => $token]),
            ]);

            $data = json_decode($response->getBody()->getContents(), true);

            if (!empty($data['error'])) {
                $this->handleError($data);
            }

            return $data['result'] ?? $data;

        } catch (\GuzzleHttp\Exception\ClientException $e) {
            $statusCode = $e->getResponse()->getStatusCode();
            if ($statusCode === 401) {
                // Попробовать обновить токен
                $this->tokenStorage->refresh();
                return $this->call($method, $params);
            }
            throw new BitrixApiException("HTTP {$statusCode}: " . $e->getMessage(), $statusCode);
        }
    }

    private function handleError(array $data): void
    {
        $errorCode = $data['error'] ?? 'UNKNOWN';
        $errorDesc = $data['error_description'] ?? '';

        if ($errorCode === 'QUERY_LIMIT_EXCEEDED') {
            // Rate limit — задержка и повтор
            throw new RateLimitException($errorDesc);
        }

        if (in_array($errorCode, ['NO_AUTH_FOUND', 'expired_token', 'invalid_token'])) {
            throw new AuthException($errorDesc);
        }

        throw new BitrixApiException("{$errorCode}: {$errorDesc}");
    }

    /** Пакетный запрос — batch */
    public function batch(array $commands): array
    {
        $cmdParams = [];
        foreach ($commands as $key => $command) {
            $cmdParams[$key] = $command->toApiParam();
        }

        $result = $this->call('batch', ['cmd' => $cmdParams]);
        return $result['result'] ?? [];
    }
}

DTO и типизированные методы

Вместо работы с сырыми массивами — Data Transfer Objects:

namespace BitrixSdk\Dto\Crm;

class LeadCreateRequest
{
    public string $title;
    public ?string $name        = null;
    public ?string $lastName    = null;
    public ?string $phone       = null;
    public ?string $email       = null;
    public string $sourceId     = 'WEB';
    public ?string $comments    = null;
    public int $responsibleId   = 0;
    /** @var array<string, string> */
    public array $utmFields     = [];

    public function toApiArray(): array
    {
        $fields = [
            'TITLE'     => $this->title,
            'SOURCE_ID' => $this->sourceId,
        ];

        if ($this->name)     $fields['NAME']      = $this->name;
        if ($this->lastName) $fields['LAST_NAME']  = $this->lastName;
        if ($this->comments) $fields['COMMENTS']   = $this->comments;

        if ($this->phone) {
            $fields['PHONE'] = [['VALUE' => $this->phone, 'VALUE_TYPE' => 'WORK']];
        }
        if ($this->email) {
            $fields['EMAIL'] = [['VALUE' => $this->email, 'VALUE_TYPE' => 'WORK']];
        }

        foreach ($this->utmFields as $key => $value) {
            $fields[$key] = $value;
        }

        return $fields;
    }
}

class Lead
{
    public int $id;
    public string $title;
    public ?string $name;
    public ?string $lastName;
    public string $status;
    public float $opportunity;
    public \DateTimeImmutable $dateCreate;

    public static function fromApiArray(array $data): self
    {
        $lead              = new self();
        $lead->id          = (int)$data['ID'];
        $lead->title       = $data['TITLE'];
        $lead->name        = $data['NAME'] ?? null;
        $lead->lastName    = $data['LAST_NAME'] ?? null;
        $lead->status      = $data['STATUS_ID'];
        $lead->opportunity = (float)($data['OPPORTUNITY'] ?? 0);
        $lead->dateCreate  = new \DateTimeImmutable($data['DATE_CREATE']);
        return $lead;
    }
}

API-класс для лидов

namespace BitrixSdk\Api\Crm;

class LeadApi
{
    public function __construct(private BitrixClient $client) {}

    public function add(LeadCreateRequest $request): int
    {
        $result = $this->client->call('crm.lead.add', [
            'fields' => $request->toApiArray(),
        ]);
        return (int)$result;
    }

    public function get(int $id): Lead
    {
        $data = $this->client->call('crm.lead.get', ['id' => $id]);
        return Lead::fromApiArray($data);
    }

    /**
     * @return Lead[]
     */
    public function list(array $filter = [], array $select = [], int $start = 0): array
    {
        $params = ['filter' => $filter, 'start' => $start];
        if ($select) $params['select'] = $select;

        $data = $this->client->call('crm.lead.list', $params);
        return array_map(fn($item) => Lead::fromApiArray($item), $data);
    }

    public function update(int $id, array $fields): bool
    {
        return (bool)$this->client->call('crm.lead.update', [
            'id'     => $id,
            'fields' => $fields,
        ]);
    }
}

Точка входа SDK

namespace BitrixSdk;

class BitrixSdk
{
    private BitrixClient $client;
    private ?Crm\LeadApi $leadApi     = null;
    private ?Crm\DealApi $dealApi     = null;
    private ?Tasks\TaskApi $taskApi   = null;

    public static function create(string $webhookUrl): self
    {
        $sdk         = new self();
        $storage     = new Client\WebhookTokenStorage($webhookUrl);
        $sdk->client = new Client\BitrixClient($webhookUrl, $storage);
        return $sdk;
    }

    public static function createOAuth(string $domain, string $clientId, string $clientSecret, TokenStorage $storage): self
    {
        $sdk         = new self();
        $sdk->client = new Client\BitrixClient("https://{$domain}", $storage);
        return $sdk;
    }

    public function crm(): CrmFacade
    {
        return new CrmFacade($this->client);
    }

    public function tasks(): TasksFacade
    {
        return new TasksFacade($this->client);
    }
}

// Использование
$sdk  = BitrixSdk::create('https://company.bitrix24.ru/rest/1/webhook_token/');
$lead = new LeadCreateRequest();
$lead->title = 'Заявка с сайта';
$lead->name  = 'Иван';
$lead->phone = '+79001234567';
$leadId = $sdk->crm()->leads()->add($lead);

Rate Limiting и очередь

Битрикс24 ограничивает запросы: 2 запроса/сек для облачных порталов. При превышении — HTTP 503 с X-RateLimit-Reset. SDK должен это обрабатывать:

class RetryMiddleware
{
    private const MAX_RETRIES   = 3;
    private const RETRY_DELAYS  = [1, 2, 5]; // секунды

    public function handle(callable $next, string $method, array $params): array
    {
        for ($attempt = 0; $attempt <= self::MAX_RETRIES; $attempt++) {
            try {
                return $next($method, $params);
            } catch (RateLimitException $e) {
                if ($attempt === self::MAX_RETRIES) throw $e;
                sleep(self::RETRY_DELAYS[$attempt]);
            }
        }
        throw new BitrixApiException('Max retries exceeded');
    }
}

Для массовых операций (импорт 10 000 лидов) — использовать batch-метод Битрикс (до 50 команд за раз) и очередь (Laravel Queue, RabbitMQ, Redis Queue).

Сроки разработки

Вариант Состав Срок
Базовый SDK CRM-методы, HTTP-клиент, DTO, обработка ошибок 8–12 дней
Расширенный + Tasks, каталог, webhooks, rate limiting 14–20 дней
Полный SDK с тестами + PHPUnit тесты, CI/CD, packagist-пакет 20–30 дней