Skip to content

PHP SDK для PHP 7.4

Composer-пакет verstka/sdk-php74 помогает реализовать интеграцию Verstka на legacy PHP backend: открыть редактор, принять callback после сохранения, скачать ZIP, сохранить медиа, обновить HTML/JSON и вернуть ответ Verstka.

Перед этой страницей лучше прочитать общий flow: ОбзорИнтеграция

Репозиторий: github.com/verstka/verstka-sdk-php74 Packagist: packagist.org/packages/verstka/sdk-php74

Выбор пакета

ПакетPHPОсобенности
verstka/sdk8.2+Laravel, Symfony
verstka/sdk-php747.4–8.1core SDK, CallbackDispatcher

Оба пакета используют namespace Verstka\Sdk\ и одинаковый публичный API core-клиента. В один проект их ставить не нужно — выберите пакет по версии PHP.

Установка

bash
composer require verstka/sdk-php74

Требования:

ТребованиеЗначение
PHP7.4 – 8.1
Расширенияext-json, ext-hash, ext-zip
HTTP clientGuzzle 7

Конфигурация

Обычно достаточно указать apiKey, apiSecret и публичный callbackUrl вашего сайта:

php
use Verstka\Sdk\Config\VerstkaConfig;

$config = new VerstkaConfig(
    'verstka-api-key',                              // apiKey
    'verstka-api-secret',                           // apiSecret
    'https://site.example/verstka/callback'         // callbackUrl
);

callbackUrl должен быть доступен Verstka backend снаружи. На этот URL Verstka придет при сохранении публикации в редакторе.

Дополнительные настройки:

php
$config = new VerstkaConfig(
    'verstka-api-key',                              // apiKey
    'verstka-api-secret',                           // apiSecret
    'https://site.example/verstka/callback',        // callbackUrl
    'https://api.r2.verstka.org/integration',              // apiUrl
    200 * 1024 * 1024,                              // maxContentSize
    60.0,                                           // requestTimeout
    120.0,                                          // downloadTimeout
    false                                           // debug
);
ПараметрПо умолчаниюОписание
apiUrlhttps://api.r2.verstka.org/integrationБазовый URL API Verstka
maxContentSize200 * 1024 * 1024 (200 MiB)Максимальный размер ZIP в байтах
requestTimeout60.0Таймаут session/open (секунды)
downloadTimeout120.0Таймаут скачивания ZIP (секунды)
debugfalseДобавлять debug_info в ответ callback

1. Открыть редактор из админки

В админке лучше сделать кнопку обычной ссылкой, которая открывается в новой вкладке и ведет на route вашего backend:

html
<a
  href="/admin/verstka/edit?post=123"
  target="_blank"
  rel="noopener noreferrer"
>
  Редактировать в Verstka
</a>

Backend route проверяет права пользователя, загружает статью из CMS, получает editorUrl через SDK и делает redirect:

php
use Verstka\Sdk\Client\VerstkaClient;
use Verstka\Sdk\Config\VerstkaConfig;

function openVerstkaEditor(int $articleId, User $user, VerstkaConfig $config): void
{
    $article = ArticleRepository::find($articleId);

    if (!UserPolicy::canEdit($user, $article)) {
        throw new RuntimeException('Access denied');
    }

    $client = new VerstkaClient($config);

    $editorUrl = $client->getEditorUrl(
        (string) $article->id,
        $article->vms_json,
        []
    );

    header('Location: ' . $editorUrl, true, 302);
    exit;
}

Если статья открывается впервые, vmsJson можно не передавать или передать null. Если статья уже редактировалась в Verstka, передайте последний сохраненный vmsJson.

vmsJson и metadata принимают массив или JSON-строку. SDK автоматически добавляет version: "php_<sdk-version>" в metadata.

2. Сохранить файлы через StorageAdapter

SDK скачивает ZIP и извлекает файлы, но не знает, где ваш сайт хранит медиа. Реализуйте StorageAdapter — сохраните файл и верните публичный URL.

php
use Verstka\Sdk\Storage\StorageAdapter;

final class CmsStorage implements StorageAdapter
{
    public function saveMedia(
        string $filename,
        string $tempPath,
        string $materialId,
        array $metadata
    ): string {
        return $this->saveToCdn("articles/$materialId/$filename", $tempPath);
    }

    public function saveFontFile(
        string $filename,
        string $tempPath,
        string $materialId,
        array $metadata
    ): string {
        return $this->saveToCdn("verstka/fonts/$filename", $tempPath);
    }

    public function saveFontsManifest(
        string $filename,
        string $tempPath,
        string $materialId,
        array $metadata
    ): string {
        return $this->saveToCdn("verstka/fonts/$filename", $tempPath);
    }
}

Для локальной разработки можно использовать LocalStorageAdapter:

php
use Verstka\Sdk\Storage\LocalStorageAdapter;

$storage = new LocalStorageAdapter(
    '/var/www/uploads',
    'https://cdn.example.com/uploads'
);

3. Принять callback после Save

php
use Verstka\Sdk\Client\VerstkaClient;
use Verstka\Sdk\Finalize\ContentFinalizeContext;
use Verstka\Sdk\Finalize\ContentFinalizeResult;

$client = new VerstkaClient($config);
$storage = new CmsStorage();

$result = $client->processMaterialCallback(
    $requestPayload,
    $_SERVER['HTTP_X_VERSTKA_SIGNATURE'] ?? '',
    $storage,
    function (ContentFinalizeContext $ctx): ContentFinalizeResult {
        ArticleRepository::saveVerstkaContent(
            $ctx->materialId,
            $ctx->vmsHtml,
            $ctx->vmsJson,
            $ctx->metadata
        );

        return new ContentFinalizeResult(true, $ctx->vmsJson);
    }
);

header('Content-Type: application/json');
echo json_encode($result->toResponse());

ContentFinalizeContext содержит materialId, metadata, vmsJson, vmsHtml и savedMediaUrls. К моменту вызова onFinalize SDK уже заменил dummy-* URL на публичные из StorageAdapter.

Ответ Verstka: {"rc": 1, "rm": "...", "data": {...}}. rc: 1 — успех, rc: 0 — ошибка или отклонение.

4. Обработать callback шрифтов

php
use Verstka\Sdk\Finalize\FontsFinalizeContext;
use Verstka\Sdk\Finalize\FontsFinalizeResult;

$result = $client->processFontsCallback(
    $requestPayload,
    $_SERVER['HTTP_X_VERSTKA_SIGNATURE'] ?? '',
    $storage,
    function (FontsFinalizeContext $ctx): FontsFinalizeResult {
        SiteSettings::set('verstka_fonts_css_url', $ctx->cssUrl);
        SiteSettings::set('verstka_fonts_json_url', $ctx->jsonUrl);

        return new FontsFinalizeResult(true, $ctx->fonts);
    }
);

onFinalize для fonts можно не передавать, если достаточно сохранения файлов через storage и возврата обновленного дерева fonts в Verstka.

5. Единый callback endpoint

В отличие от verstka/sdk, пакет для PHP 7.4 не включает готовые адаптеры Laravel/Symfony. Для одного POST-endpoint используйте CallbackDispatcher:

php
use Verstka\Sdk\Integration\CallbackDispatcher;
use Verstka\Sdk\Finalize\ContentFinalizeContext;
use Verstka\Sdk\Finalize\ContentFinalizeResult;
use Verstka\Sdk\Finalize\FontsFinalizeContext;
use Verstka\Sdk\Finalize\FontsFinalizeResult;

try {
    $response = CallbackDispatcher::dispatch(
        $client,
        $requestPayload,
        $_SERVER['HTTP_X_VERSTKA_SIGNATURE'] ?? '',
        $storage,
        function (ContentFinalizeContext $ctx): ContentFinalizeResult {
            ArticleRepository::saveVerstkaContent(
                $ctx->materialId,
                $ctx->vmsHtml,
                $ctx->vmsJson,
                $ctx->metadata
            );
            return new ContentFinalizeResult(true, $ctx->vmsJson);
        },
        function (FontsFinalizeContext $ctx): FontsFinalizeResult {
            SiteSettings::set('verstka_fonts_css_url', $ctx->cssUrl);
            return new FontsFinalizeResult(true, $ctx->fonts);
        }
    );

    header('Content-Type: application/json');
    echo json_encode($response);
} catch (\Throwable $e) {
    $error = CallbackDispatcher::mapException($e);
    http_response_code($error->status);
    header('Content-Type: application/json');
    echo json_encode($error->toArray());
}

Диспетчер смотрит на $payload['event']: site_fonts_updated — fonts flow, остальное — material flow.

Metadata, PreSave, Callback authorization

Эти темы одинаковы для обоих PHP-пакетов. Подробнее:

Справочник методов

МетодНазначение
VerstkaClient::getEditorUrl(...)Открывает сессию через POST /session/open и возвращает URL редактора.
VerstkaClient::processMaterialCallback(...)Обрабатывает article_saved: подпись, ZIP, медиа, onFinalize.
VerstkaClient::processFontsCallback(...)Обрабатывает site_fonts_updated: подпись, fonts ZIP, font files, manifests.
StorageAdapter::saveMedia(...)Сохраняет файл из vms_media/* и возвращает публичный URL.
StorageAdapter::saveFontFile(...)Сохраняет файл шрифта и возвращает публичный URL.
StorageAdapter::saveFontsManifest(...)Сохраняет vms_fonts.css или vms_fonts.json и возвращает URL.
LocalStorageAdapterФайловая reference-реализация storage adapter.
CallbackDispatcher::dispatch(...)Маршрутизирует callback по полю event.
CallbackDispatcher::mapException(...)Преобразует исключения SDK в HTTP-ответ.
SignatureService::signMaterial(...)Строит HMAC для material_id:url.
SignatureService::verifySignature(...)Проверяет HMAC.
UrlBuilder::buildAuthorizedContentUrl(...)Добавляет api_key и material_id к content_url.

См. также