antonowano/mindbox

Mindbox API integration library

Maintainers

Package info

github.com/antonowano/mindbox

pkg:composer/antonowano/mindbox

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.1 2026-07-26 07:17 UTC

This package is auto-updated.

Last update: 2026-07-26 07:19:09 UTC


README

Mindbox - это российская экосистема для email-, sms-, push-рассылок с персонализацией маркетинга и цен.

Эта библиотека предоставляет удобные классы для быстрой интеграции с API-методами Mindbox на PHP. А продуманные интерфейсы помогут быстро расширить функциональность библиотеки.

Установка

composer require antonowano/mindbox

Библиотека зависит только от интерфейсов PSR. Для работы нужны реализации:

  • PSR-18 / PSR-17 - HTTP-клиент и фабрики запросов/стримов (например, Guzzle: composer require guzzlehttp/guzzle);
  • PSR-3 - логгер, если используете SilentApiClient (например, Monolog: composer require monolog/monolog).

SilentApiClient оборачивает обычный клиент, ловит исключения и пишет их в лог вместо проброса наружу.

Параметры интеграции

Для работы клиента нужны:

Параметр Описание
endpointId Идентификатор эндпоинта в Mindbox
secretKey Секретный ключ API
defaultPrefix Префикс операций по умолчанию (например, Website.)
deviceUuid UUID устройства для операций с needDeviceUuid: true

В боевом приложении deviceUuid берётся из cookie mindboxDeviceUUID (его выставляет JS SDK Mindbox).

Примеры использования

Синхронный запрос (получить профиль)

$data = $apiClient->sync(new DefaultJsonOperation(
    name: '{prefix}GetProfile',
    needDeviceUuid: false,
    requestData: [
        'customer' => [
            'ids' => [
                'webID' => 3165145,
            ],
        ],
    ],
));

Асинхронный запрос (просмотр товара)

$data = $apiClient->async(new DefaultJsonOperation(
    name: '{prefix}ViewProduct',
    needDeviceUuid: true,
    requestData: [
        'viewProduct' => [
            'productGroup' => [
                'ids' => [
                    'brandProducts' => 3914381,
                ],
            ],
        ],
    ],
));

Bulk-операция (массовое редактирование клиентов)

$csvFile = tmpfile();
fputcsv($csvFile, [
    'ExternalIdentityWebID',
    'IsSubscribedByEmail',
    'IsSubscribedByEmailOnService',
    'IsSubscribedByEmailOnTrigger',
    'IsSubscribedByEmailOnLoyalty',
], ';', '"', '\\');
fputcsv($csvFile, [
    '3165145',
    '0',
    '1',
    '1',
    '1',
], ';', '"', '\\');
rewind($csvFile);

$data = $apiClient->bulk(
    new DefaultBulkOperation(
        name: 'DirectCrm.Customers.Edit',
        resource: $csvFile,
    ),
    new MindboxTransactionId()
);

Эти же примеры с инициализацией можно найти в папке scripts/.

Свои классы

Для более элегантной работы с библиотекой лучше реализовывать собственные классы вместо DefaultIntegration, DefaultJsonOperation и других дефолтных реализаций. Интерфейсы Integration, AsyncOperation, SyncOperation и BulkOperation как раз для этого и предусмотрены.

CustomIntegration

Вместо DefaultIntegration можно описать своё поведение - например, читать deviceUuid из cookie:

use Antonowano\Mindbox\Integration;

readonly class CustomIntegration implements Integration
{
    public function endpointId(): string
    {
        return env('MINDBOX_ENDPOINT_ID');
    }

    public function secretKey(): string
    {
        return env('MINDBOX_SECRET_KEY');
    }

    public function defaultPrefix(): string
    {
        return env('MINDBOX_DEFAULT_PREFIX');
    }

    public function deviceUuid(): ?string
    {
        return $_COOKIE['mindboxDeviceUUID'] ?? null;
    }
}

ViewProduct

Вместо передачи массива в DefaultJsonOperation можно инкапсулировать операцию в отдельный класс:

use Antonowano\Mindbox\AsyncOperation;

readonly class ViewProduct implements AsyncOperation
{
    public function __construct(
        private int $productId,
    ) {
    }

    public function name(string $defaultPrefix): string
    {
        return $defaultPrefix . 'ViewProduct';
    }

    public function needDeviceUuid(): bool
    {
        return true;
    }

    public function requestData(): array
    {
        return [
            'viewProduct' => [
                'productGroup' => [
                    'ids' => [
                        'brandProducts' => $this->productId,
                    ],
                ],
            ],
        ];
    }
}

Использование:

$data = $apiClient->async(new ViewProduct($productId));

Такой подход делает вызовы API читаемее: в код передаются доменные данные, а детали формирования запроса остаются в классе операции.

Установка на Laravel

1. Установка пакета

composer require antonowano/mindbox

Отдельно ставить Guzzle и логгер не нужно: в Laravel уже есть Guzzle (через фреймворк) и PSR-3 логгер (Log).

2. Переменные окружения

Добавьте в .env:

MINDBOX_ENDPOINT_ID=company_endpoint_web
MINDBOX_SECRET_KEY=secret_key
MINDBOX_DEFAULT_PREFIX=Website.

3. Настройка конфига

Добавьте секцию mindbox в config/services.php:

'mindbox' => [
    'endpoint_id' => env('MINDBOX_ENDPOINT_ID'),
    'secret_key' => env('MINDBOX_SECRET_KEY'),
    'default_prefix' => env('MINDBOX_DEFAULT_PREFIX'),
],

После изменения .env в production не забудьте пересобрать кэш конфигурации:

php artisan config:cache

В коде значения читаются через config('services.mindbox.*'), а не через env() напрямую.

4. Регистрация в контейнере

В AppServiceProvider (или отдельном сервисе-провайдере):

use Antonowano\Mindbox\ApiClient;
use Antonowano\Mindbox\DefaultIntegration;
use Antonowano\Mindbox\Integration;
use Antonowano\Mindbox\MindboxApiClient;
use Antonowano\Mindbox\MindboxEndpointUrl;
use Antonowano\Mindbox\SilentApiClient;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use Illuminate\Support\Facades\Log;

public function register(): void
{
    $this->app->singleton(Integration::class, function () {
        return new DefaultIntegration(
            endpointId: config('services.mindbox.endpoint_id'),
            secretKey: config('services.mindbox.secret_key'),
            defaultPrefix: config('services.mindbox.default_prefix'),
            deviceUuid: $_COOKIE['mindboxDeviceUUID'] ?? null,
        );
    });

    $this->app->singleton(ApiClient::class, function ($app) {
        $integration = $app->make(Integration::class);
        $httpFactory = new HttpFactory();

        $client = new MindboxApiClient(
            integration: $integration,
            endpointUrl: new MindboxEndpointUrl($integration),
            httpClient: new Client(),
            requestFactory: $httpFactory,
            streamFactory: $httpFactory,
        );

        return $client;
        // или, если никогда не хотите обрабатывать Exception, тогда так:
        // return new SilentApiClient($client, Log::channel());
    });
}

Если вы не хотите обрабатывать исключения с помощью try..catch, тогда оберните зарегистрированный клиент классом SilentApiClient. Все Exception будут направлены в логгер, а само приложение не упадёт.

public function product(int $productId, ApiClient $client) {
    $client = new SilentApiClient($client, Log::channel());
    $client->async(new ViewProduct($productId));
}