Интеграция электронной подписи DocuSign на сайт
DocuSign — лидер рынка электронных подписей в США и Европе. Поддерживает юридически обязывающие подписи по стандартам eIDAS (Европа), UETA/ESIGN (США), и ряду национальных стандартов. Для российского рынка важно: DocuSign даёт простую электронную подпись (ПЭП), которая признаётся в суде при наличии соглашения сторон — для большинства коммерческих договоров этого достаточно.
Архитектура интеграции
Типовой флоу:
- На сайте пользователь заполняет данные → нажимает «Подписать договор»
- Бэкенд создаёт Envelope (конверт) в DocuSign с документом и получателями
- Пользователь перенаправляется на DocuSign для подписания (или получает email)
- После подписания DocuSign уведомляет сайт через webhook
- Бэкенд скачивает подписанный документ и сохраняет
Настройка приложения
В DocuSign Developer Portal: создать Integration Key → добавить redirect URI → запросить Secret Key. Для тестирования — бесплатная Demo среда (account-d.docusign.com).
composer require docusign/esign-client
// config/docusign.php
return [
'integrator_key' => env('DOCUSIGN_INTEGRATOR_KEY'),
'client_secret' => env('DOCUSIGN_CLIENT_SECRET'),
'account_id' => env('DOCUSIGN_ACCOUNT_ID'),
'base_url' => env('DOCUSIGN_BASE_URL', 'https://demo.docusign.net/restapi'),
'redirect_uri' => env('DOCUSIGN_REDIRECT_URI'),
];
OAuth: получение токена
DocuSign использует OAuth 2.0 Authorization Code Grant:
class DocuSignAuthService
{
public function getAuthUrl(): string
{
$params = http_build_query([
'response_type' => 'code',
'scope' => 'signature',
'client_id' => config('docusign.integrator_key'),
'redirect_uri' => config('docusign.redirect_uri'),
]);
// Demo: account-d.docusign.com, Prod: account.docusign.com
return 'https://account-d.docusign.com/oauth/auth?' . $params;
}
public function handleCallback(string $code): string
{
$response = Http::withBasicAuth(
config('docusign.integrator_key'),
config('docusign.client_secret')
)->asForm()->post('https://account-d.docusign.com/oauth/token', [
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => config('docusign.redirect_uri'),
]);
return $response->json('access_token');
}
}
Для серверных сценариев без участия пользователя — JWT Grant (сервис-аккаунт).
Создание конверта и отправка на подпись
class DocuSignEnvelopeService
{
public function createEnvelope(
string $accessToken,
string $pdfPath,
array $signers
): string {
$config = new \DocuSign\eSign\Configuration();
$config->setHost(config('docusign.base_url'));
$config->addDefaultHeader('Authorization', "Bearer {$accessToken}");
$apiClient = new \DocuSign\eSign\client\ApiClient($config);
$envelopesApi = new \DocuSign\eSign\Api\EnvelopesApi($apiClient);
// Документ из файла
$document = new \DocuSign\eSign\Model\Document([
'document_base64' => base64_encode(file_get_contents($pdfPath)),
'name' => 'Договор',
'file_extension' => 'pdf',
'document_id' => '1',
]);
// Место для подписи
$signHere = new \DocuSign\eSign\Model\SignHere([
'anchor_string' => '/sig1/', // или фиксированные координаты
'anchor_x_offset' => '20',
'anchor_y_offset' => '-10',
'anchor_units' => 'pixels',
]);
$recipientList = [];
foreach ($signers as $i => $signer) {
$tabs = new \DocuSign\eSign\Model\Tabs(['sign_here_tabs' => [$signHere]]);
$recipientList[] = new \DocuSign\eSign\Model\Signer([
'email' => $signer['email'],
'name' => $signer['name'],
'recipient_id' => (string)($i + 1),
'routing_order'=> (string)($i + 1),
'tabs' => $tabs,
]);
}
$envelopeDefinition = new \DocuSign\eSign\Model\EnvelopeDefinition([
'email_subject' => 'Пожалуйста, подпишите документ',
'documents' => [$document],
'recipients' => new \DocuSign\eSign\Model\Recipients([
'signers' => $recipientList,
]),
'status' => 'sent', // 'created' для черновика
]);
$result = $envelopesApi->createEnvelope(
config('docusign.account_id'),
$envelopeDefinition
);
return $result->getEnvelopeId();
}
}
Embedded Signing: подпись прямо на сайте
Вместо перехода на DocuSign — встроенный iframe или редирект обратно на сайт:
public function getSigningUrl(string $accessToken, string $envelopeId, array $signer): string
{
$config = new \DocuSign\eSign\Configuration();
$config->setHost(config('docusign.base_url'));
$config->addDefaultHeader('Authorization', "Bearer {$accessToken}");
$apiClient = new \DocuSign\eSign\client\ApiClient($config);
$envelopesApi = new \DocuSign\eSign\Api\EnvelopesApi($apiClient);
$viewRequest = new \DocuSign\eSign\Model\RecipientViewRequest([
'authentication_method' => 'none',
'client_user_id' => $signer['id'], // внутренний ID пользователя
'recipient_id' => '1',
'return_url' => route('contracts.signed'),
'user_name' => $signer['name'],
'email' => $signer['email'],
]);
$result = $envelopesApi->createRecipientView(
config('docusign.account_id'),
$envelopeId,
$viewRequest
);
return $result->getUrl(); // redirect сюда или открыть в iframe
}
Webhook: уведомление о подписании
public function handleDocuSignWebhook(Request $request): Response
{
// DocuSign отправляет XML
$xml = simplexml_load_string($request->getContent());
$status = (string)$xml->EnvelopeStatus->Status;
$envelopeId = (string)$xml->EnvelopeStatus->EnvelopeID;
if ($status === 'Completed') {
DownloadSignedDocumentJob::dispatch($envelopeId);
}
return response('OK', 200);
}
Сроки
Базовая интеграция (создание конверта + отправка email подписанту + webhook): 2–3 рабочих дня. Embedded signing с полным флоу внутри сайта и автоматическим скачиванием документа: 4–5 рабочих дней. В оценку входит регистрация приложения DocuSign, тестирование в Demo-среде и переключение на Production.







