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/sdk | 8.2+ | Laravel, Symfony |
verstka/sdk-php74 | 7.4–8.1 | core SDK, CallbackDispatcher |
Оба пакета используют namespace Verstka\Sdk\ и одинаковый публичный API core-клиента. В один проект их ставить не нужно — выберите пакет по версии PHP.
Установка
composer require verstka/sdk-php74Требования:
| Требование | Значение |
|---|---|
| PHP | 7.4 – 8.1 |
| Расширения | ext-json, ext-hash, ext-zip |
| HTTP client | Guzzle 7 |
Конфигурация
Обычно достаточно указать apiKey, apiSecret и публичный callbackUrl вашего сайта:
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 придет при сохранении публикации в редакторе.
Дополнительные настройки:
$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
);| Параметр | По умолчанию | Описание |
|---|---|---|
apiUrl | https://api.r2.verstka.org/integration | Базовый URL API Verstka |
maxContentSize | 200 * 1024 * 1024 (200 MiB) | Максимальный размер ZIP в байтах |
requestTimeout | 60.0 | Таймаут session/open (секунды) |
downloadTimeout | 120.0 | Таймаут скачивания ZIP (секунды) |
debug | false | Добавлять debug_info в ответ callback |
1. Открыть редактор из админки
В админке лучше сделать кнопку обычной ссылкой, которая открывается в новой вкладке и ведет на route вашего backend:
<a
href="/admin/verstka/edit?post=123"
target="_blank"
rel="noopener noreferrer"
>
Редактировать в Verstka
</a>Backend route проверяет права пользователя, загружает статью из CMS, получает editorUrl через SDK и делает redirect:
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.
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:
use Verstka\Sdk\Storage\LocalStorageAdapter;
$storage = new LocalStorageAdapter(
'/var/www/uploads',
'https://cdn.example.com/uploads'
);3. Принять callback после Save
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 шрифтов
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:
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. |
См. также
- PHP SDK (8.2+) — Laravel, Symfony
- Интеграция API — flow без SDK
- Интеграция — общий обзор