Отправка файлов на подпись с Adobe Sign API

В документации Adobe сочетается большой объем информации и плохая организация этой информации. Поэтому когда перед мной стала задача отправлять документы через Adobe Sign Api, я потратил несколько дней чтобы понять как всё это работает. 

И вот моё решение перед вами. Надеюсь, оно сэкономит время и нервы тех кому только предстоит разобраться в этом. 

Порядок действий:

  1. Создаем статичный ключ для работы с API — Access token

  2. Получаем домены для работы с API — Base uris

  3. Загружаем документ

  4. Отправляем документ на подпись

  5. Проверяем статус подписи

  6. Сохраняем подписанный файл

Создаем статичный ключ для работы с API — Access token

Заходим в свой аккаунт на сайте Adobe Sign API: https://secure.echosign.com/public/login. Переходим на страницу Account. Выбираем Personal Preferences и Access Tokens.

3eebed08aa533a55edc7f403d7f3f478.png

Нажимаем на плюсик справа, вводим название, выбираем доступы и сохраняем.

Какие доступы нам нужны?

На этот вопрос у меня ответа нет, поэтому я выбрал все доступы, чтобы наверняка заработало. Да, это не безопасно, но зато так точно будет работать. Мне было важно, чтобы оно заработало.

После сохранения, кликаем на наш токен и нажимаем сверху «Integration Key», чтобы получить наш токен.

Далее в перменной $accessToken будет именно этот токен.

Получаем домены для работы с API — Base uris

get('https://api.adobesign.com/api/rest/v6/baseUris');

// В ответе JSON с полем apiAccessPoint 
$apiAccessPoint = $response->json('apiAccessPoint');

В $apiAccessPoint домен для API запросов.

Загружаем документ

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 }}

Далее необходимо сформировать тело запроса. Оно содержит некоторое количество полей:

 [
           [
               "transientDocumentId" => $documentID
           ]
       ],
       // Название документа, которое увидит клиент
       "name"                => "Series Document",
       "participantSetsInfo" => [
           [
               "order"       => 1,
               "role"        => "SIGNER",
               "memberInfos" => [
                   [
                       // Почта клиента
                       "email" => $email,
                       "id"    => 1
                   ]
               ]
           ]
       ],
       "signatureType"       => "ESIGN",
       "state"               => "IN_PROCESS"
   ];
}

Теперь необходимо выполнить запрос на отправку файла на подпись:

baseUrl($apiAccessPoint)
                ->asJson()
                ->post(
                    '/api/rest/v6/agreements',
                    $bodyForSignDocument
                );

// В ответе JSON с ID загруженного документа. Он понадобится ниже
$documentID = $response->json('id');
if ($response->status() != '201' || ! $documentID) {
   // Если ID не пришел или документ не был первично обработан Adobe, обрабатываем ошибку
}

В переменной $documentID содержится ID документа, который был отправлен на подпись.

Проверяем статус подписи

baseUrl($apiAccessPoint)
               ->get('/api/rest/v6/agreements/' . $documentID);

// В ответе JSON с полем status
$status = $response->json('status');
if ($status !== 'SIGNED') {
   // Если статус не SIGNED, то ждем пока подпишут
}

Сохраняем подписанный файл

baseUrl($apiAccessPoint)
                  ->get($fileURLPath);

// В теле ответа будет подписанный PDF файл, если раннее в статусе было SIGNED 
$fileContent = $fileContent->body();

Источники. Примечания

Источники

Касательно авторизации

Изначально Adobe просит использовать авторизацию через кнопку «Войти через Adobe». Но такой способ мне не подходил, ибо система должна функционировать автономно без вмешательства пользователей. Авторизация — тоже вмешательство.

Именно поэтому была найдена альтернатива в виде статичного токена — access token.

Касательно параметров в POST методе /api/rest/v6/agreements

Советую ознакомиться с описанием запросов к API 6й версии для понимание что можно добавить и изменить.

Например, можно не отправлять сразу документ, а подготовить его, добавив те виджеты. И только потом отправлять. Либо же, можно добавить какие-то данные в документ через автозамену тегов в формат {{var.name}}

Прошлая статья на тему Adobe

«Генерация файлов с Adobe» — в статье описаны методы формирования файлов из doсx шаблонов.

© Habrahabr.ru