В документации Adobe сочетается большой объем информации и плохая организация этой информации. Поэтому когда перед мной стала задача отправлять документы через Adobe Sign Api, я потратил несколько дней чтобы понять как всё это работает.
И вот моё решение перед вами. Надеюсь, оно сэкономит время и нервы тех кому только предстоит разобраться в этом.
Порядок действий:
Создаем статичный ключ для работы с API - Access token
Получаем домены для работы с API - Base uris
Загружаем документ
Отправляем документ на подпись
Проверяем статус подписи
Сохраняем подписанный файл
Создаем статичный ключ для работы с API - Access token
Заходим в свой аккаунт на сайте Adobe Sign API: https://secure.echosign.com/public/login. Переходим на страницу Account. Выбираем Personal Preferences и Access Tokens.
Нажимаем на плюсик справа, вводим название, выбираем доступы и сохраняем.
Какие доступы нам нужны?
На этот вопрос у меня ответа нет, поэтому я выбрал все доступы, чтобы наверняка заработало. Да, это не безопасно, но зато так точно будет работать. Мне было важно, чтобы оно заработало.
После сохранения, кликаем на наш токен и нажимаем сверху “Integration Key”, чтобы получить наш токен.
Далее в перменной $accessToken
будет именно этот токен.
Получаем домены для работы с API - Base uris
<?php
// Access token, полученный выше
$accessToken = '';
// Laravel фасад:
// GET запрос
// Доп. заголовок: Bearer $accessToken
// URL: https://api.adobesign.com/api/rest/v6/baseUris
$response = Http::withToken($accessToken)
->get('https://api.adobesign.com/api/rest/v6/baseUris');
// В ответе JSON с полем apiAccessPoint
$apiAccessPoint = $response->json('apiAccessPoint');
В $apiAccessPoint
домен для API запросов.
Загружаем документ
<?php
// Access token, полученный выше
$accessToken = '';
// Домен для API запросов, полученный выше
$apiAccessPoint = '';
// Путь к pdf шаблону
$template = file_get_contents($pathToTemplate);
// Laravel фасад:
// POST multipart/form-data запрос
// Доп. заголовок: Bearer $accessToken
// URL: $apiAccessPoint.'/api/rest/v6/transientDocuments'
// В теле указываем название файла, mime тип и содержимое файла
$response = Http
::withToken($accessToken)
->baseUrl($apiAccessPoint)
->asMultipart()
->post('/api/rest/v6/transientDocuments', [
'File-Name' => 'document.pdf',
'Mime-Type' => 'application/pdf',
'File' => $template
]);
// В ответе JSON с полем transientDocumentId, что является ID загруженного дока
$transientDocumentID = $response->json('transientDocumentId');
if ( ! $transientDocumentID) {
// Если не пришел ID документа, то обрабатываем ошибку
}
В переменной $transientDocumentID
будет ID загруженного документа.
Отправляем документ на подпись
Далее мне надо было понять как отправить документ на подпись.
Сначала я пытался добавить в документ виджеты. Виджет - это поле ввода в которое пользователь может внести свои данные, включая подпись. Но виджетам необходимо указывать координаты, которые непонятно как связаны с реальным документом.
Поэтому после нескольких часов поиска в интернете, я нашел руководство по тегам, которые можно добавить в шаблон, чтобы поля появились сами собой.
Например, чтобы появилось поле подписи, нужно ввести тег {{ es:signer:signature }}
В документе это может выглядеть так:
Документ #1234
Исполнитель: Дмитрий Дмитриевич {{es:signer:signature }}
Далее необходимо сформировать тело запроса. Оно содержит некоторое количество полей:
<?php
// Функция для формирования тела запроса. Используется ниже
function getBodyForSignDocument($documentID, $email): array
{
return [
// ID документа, полученный выше
"fileInfos" => [
[
"transientDocumentId" => $documentID
]
],
// Название документа, которое увидит клиент
"name" => "Series Document",
"participantSetsInfo" => [
[
"order" => 1,
"role" => "SIGNER",
"memberInfos" => [
[
// Почта клиента
"email" => $email,
"id" => 1
]
]
]
],
"signatureType" => "ESIGN",
"state" => "IN_PROCESS"
];
}
Теперь необходимо выполнить запрос на отправку файла на подпись:
<?php
// Access token, полученный выше
$accessToken = '';
// Домен для API запросов, полученный выше
$apiAccessPoint = '';
// Тело запроса, функция которого писана выше
$bodyForSignDocument = getBodyForSignDocument($transientDocumentID, $email);
// Laravel фасад:
// POST application/json запрос
// Доп. заголовок: Bearer $accessToken
// URL: $apiAccessPoint.'/api/rest/v6/agreements'
// Тело запроса описано выше
$response = Http::withToken(self::API_TOKEN)
->baseUrl($apiAccessPoint)
->asJson()
->post(
'/api/rest/v6/agreements',
$bodyForSignDocument
);
// В ответе JSON с ID загруженного документа. Он понадобится ниже
$documentID = $response->json('id');
if ($response->status() != '201' || ! $documentID) {
// Если ID не пришел или документ не был первично обработан Adobe, обрабатываем ошибку
}
В переменной $documentID
содержится ID документа, который был отправлен на подпись.
Проверяем статус подписи
<?php
// Access token, полученный выше
$accessToken = '';
// Домен для API запросов, полученный выше
$apiAccessPoint = '';
// ID документа, полученный выше
$documentID
// Laravel фасад:
// GET запрос
// Доп. заголовок: Bearer $accessToken
// URL: $apiAccessPoint.'/api/rest/v6/agreements/'.$documentID
$response = Http::withToken(self::API_TOKEN)
->baseUrl($apiAccessPoint)
->get('/api/rest/v6/agreements/' . $documentID);
// В ответе JSON с полем status
$status = $response->json('status');
if ($status !== 'SIGNED') {
// Если статус не SIGNED, то ждем пока подпишут
}
Сохраняем подписанный файл
<?php
// Access token, полученный выше
$accessToken = '';
// Домен для API запросов, полученный выше
$apiAccessPoint = '';
// ID документа, полученный выше
$documentID
// Полный путь до файла
$fileURLPath = $apiAccessPoint . 'api/rest/v6/agreements/' . $documentID . '/combinedDocument';
// Laravel фасад:
// GET запрос
// Доп. заголовок: Bearer $accessToken
// URL: $apiAccessPoint.$fileURLPath
$fileContent = Http::withToken(self::API_TOKEN)
->baseUrl($apiAccessPoint)
->get($fileURLPath);
// В теле ответа будет подписанный PDF файл, если раннее в статусе было SIGNED
$fileContent = $fileContent->body();
Источники. Примечания
Источники
Общий гайд по Adobe Sign API - можно ознакомиться для общего понимания API
Описание запросов к API 6й версии - тут подробно описаны методы для отправки документа на подпись
Гайд от Adobe по Access Token - не уверен что читал именно этот гайд, поэтому могу лишь посоветовать бегло посмотреть что к чему тут
Руководство по тегам в Adobe Sign API - советую внимательно прочитать
Личный кабинет в Adobe Sign - на всякий случай
Касательно авторизации
Изначально Adobe просит использовать авторизацию через кнопку "Войти через Adobe". Но такой способ мне не подходил, ибо система должна функционировать автономно без вмешательства пользователей. Авторизация - тоже вмешательство.
Именно поэтому была найдена альтернатива в виде статичного токена - access token.
Касательно параметров в POST методе /api/rest/v6/agreements
Советую ознакомиться с описанием запросов к API 6й версии для понимание что можно добавить и изменить.
Например, можно не отправлять сразу документ, а подготовить его, добавив те виджеты. И только потом отправлять. Либо же, можно добавить какие-то данные в документ через автозамену тегов в формат {{var.name}}
Прошлая статья на тему Adobe
"Генерация файлов с Adobe" - в статье описаны методы формирования файлов из doсx шаблонов.