Подписывайте документы онлайн,
быстро и безопасно!

APB.DocumentSigner – это плагин, который поддерживает цифровую подпись документов с использованием одного или нескольких пользовательских сертификатов через браузер.

Скачать

Преимущества

Цифровая подпись

Поддерживает цифровую подпись документов XML следующих форматов:

XAdES_BES XAdES_XL XAdES_T XmlDsig
Графическая подпись

Позволяет управлять размером и расположением графических подписей на страницах PDF документов.

Работа в браузере

Легко интегрируется с браузерами Google Chrome и Mozila FireFox.

Простая установка

Состоит из плагина и клиентского приложения. Загрузка необходимых компонентов происходит автоматически. Минимальные системные требования: Windows 7 SP1

Кому полезен
APB.DocumentSigner?

Соответствует мировым техническим стандартам цифровых подписей.

Позволяет использовать цифровую подпись на любом веб-ресурсе, что решает следующие задачи:

  • создание документов с цифровой подписью
  • подтверждение личности подписавшего
  • гарантия целостности всего документа
  • защита персональных данных клиентов

Возможные сферы применения плагина:

  • клиентские порталы и электронные торговые площадки;
  • системы интернет-банкинга;
  • электронные офисы для системы корпоративного документооборота и сдачи отчетностей
  • Позволяет дистанционно, со своего компьютера подписывать клиентские документы
  • Дает возможность использовать любой защищенный носитель цифровой подписи
  • Гарантирует защиту персональных данных пользователя

Как начать пользоваться APB.DocumentSigner?

1

установите плагин для браузера

Установить
2

скачайте и установите компонент для работы плагина

Скачать

Для корректной работы компонента и плагина должен быть установлен .Net Framework 4.7.2

Примеры для разработчика

  1. Обратиться в ЗАО «Агропромбанк» для заключения соглашения об использовании плагина;
  2. Получить от ЗАО «Агропромбанк» ключ доступа к функциям плагина и указать его в структуре JSON сообщения (поле domainSignature);
  3. Реализовать функцию слушателя window.addEventListener('message', function(event){…}), которая будет ожидать ответа от плагина APB.DocumentSigner;
  4. Реализовать функцию отправки запроса плагину function SendRequest(base64Data,typeDocument, typeOperation).

    /*
    * Структура JSON сообщения
    * {
    *	"source" : "адрес отправителя",
    *	"destination" : "адрес получателя",
    *	"typeDocument" : "тип документа",
    *	"typeOperation" : "тип операции",
    *   "dataBlock" : "пересылаемые приложению данные(строка данных)",
    *	"domainSignature" : "сигнатура домена",
    *	------для XML------
    *	"method" : "алгоритм подписи(RSAwithSHA1 / RSAwithSHA256 / RSAwithSHA512)",
    *	"packing" : "тип контента (ENVELOPED / ENVELOPING / INTERNALLY_DETACHED / EXTERNALLY_DETACHED / HASH_INTERNALLY_DETACHED)",
    *	"format" : "формат подписи (XAdES_BES / XAdES_XL / XAdES_T / XmlDsig)",
    *   "timeStampUri : время подписи",
    *	"contentUri : id узла который будет подписан"
    *	------для PDF------
    *	"startX" : "координаты по оси Х",
    *	"startY" : "координаты по оси Y",
    *	"height" : "высота",
    *	"width" : "ширина",
    *	"pageNumber" : "номер страницы"
    * }
    */
    var SignExtension = SignExtension || {};
    SignExtension.Enum = {
        XmlSignMethod:{
            SHA1 : 1,
            SHA256 : 2,
            SHA512 : 3
        },
        XmlSignType:{
            Enveloped : 1,
            Enveloping : 2,
            InternallyDetached : 3,
            ExternallyDetached: 4,
            HashInternallyDetached: 5
        },
        XmlSignFormat:{
            XAdES_BES : 1,
            XAdES_XL : 2,
            XAdES_T : 3,
            XmlDsig : 4
        },
        //Тип операции
        TypeOperation:{
            //Подпись документа
            Signing: 1,
            //Проверка подписи документа
            Verifty: 2,
            // Ошибка. Этот тип отправляет background или native app в случае возникновения ошибки
            Error: 3,
            //Обновить страницу.
            NeedUpdate: 4,
            //Доступ. Этот тип отправляет native app в том случае, если сайт не меет доступ к плагину или версия плагина отличается от версии установленного app
            Access: 5
        },
        //тип документа
        TypeDocument:{
            XML: 1,
            PDF: 2
        },
        //идентификатор плагина
        ExtentionId: '{B01F58C6-F424-4711-9260-231A12BBEFE5}'
    };

    //-----------------------------------------------------------
    //хэш имени домена сайта (Здесь следует указать ключ доступа к функциям плагина)
    const DOMAIN_SIGNETURE = 'CvPk0Lxu77F/HWld4ukn2ATN7nZE1N+HJ+mEV+Qu7o7NRPyHLSnyihq5Z2c27f2tef/vv6V1fn6/16R3Sg6oAHNvQ+2saPyY6Xg8J8au3A18N' + 
    'gNe5Uya3L/OXVU0VDoeCpP+nAPLT2ZTmD19pQtJfboLvp9D1JXcmMl3KlltykooFUsJmFl4uTxQjbbgbmu6HL27PnGv7w/QNsFBxtTITBMD/uFQaCByNBDHaAjyz2EGgh3DWUl' + 
    'TaMf6bKwOVTF6cMfAgsPj7GJLBuRjSw3nqBBxv16YigdfNvfGf6wVFuu3e+g34qTKO28TrwiKWSE9Oxh0ih2n/9x8HABp7FczVQ==';
    //--------------------------------------------
    /*
    *	отправка запроса плагину
    *	->xmlString - xml строка
    *	->typeDocument - SignExtension.Enum.TypeDocument.XML (тип документа - xml)
    *	->typeOperation - SignExtension.Enum.TypeOperation.Signing (тип операции - подпись документа)
    */
    function SendRequest(xmlString,typeDocument, typeOperation)
    {
        var request;
        try
        {
            //разбор строки JSON
            request = JSON.parse('{}');
            SendMessage( xmlString, request, typeDocument, typeOperation );
        }
        catch (e)
        {
            return alert( "Request parse error: " + e.message );
        }
    }
    //------------------------------------------
    /*
    *	отправка сообщения в запросе
    *	->xmlString - xml строка
    *	->message - сообщение в формате JSON
    *	->typeDocument -SignExtension.Enum.TypeDocument.XML (тип документа - xml)
    *	->typeOperation - SignExtension.Enum.TypeOperation.Signing (тип операции - подпись документа)
    */
    function SendMessage(xmlString, message, typeDocument, typeOperation)
    {
        try
        {
            //адрес отправителя
            message.source = window.location.href;
            //тип документа
            message.typeDocument = parseInt(typeDocument, 10);
            //адрес получателя
            message.destination = SignExtension.Enum.ExtentionId;
            //сигнатура домена
            message.domainSignature = DOMAIN_SIGNETURE.toString();
            //тип операции
            message.typeOperation = SignExtension.Enum.TypeOperation.Signing;
            //блок данных
            message.dataBlock = xmlString;
            //алгоритм подписи
            message.method = SignExtension.Enum.XmlSignMethod.SHA256;
            //тип контента
            message.packing = SignExtension.Enum.XmlSignType.Enveloped;
            //формат подписи
            message.format = SignExtension.Enum.XmlSignFormat.XAdES_BES;
            //время подписи
            message.timeStampUri = "";
            //id узла который будет подписан. Если поле пустое, будет подписан весь документ.
            message.contentUri = "";

            //формат XAdES_BES не использует TimeStampUri
            if(message.format == SignExtension.Enum.XmlSignFormat.XAdES_BES)
            {
                if((message.timeStampUri !== ""))
                {
                    alert('For Signature format XAdES_BES field TimeStampUri must be Empty');
                    return;
                }
            }
            //отправка кросдоменного запроса
            window.postMessage(message,"*");
        }
        catch(e)
        {
            //отображение ошибки
            alert(e.message);
            // вывод исключения в консоль
            console.error(e);
        }

    }

    //получение результата от плагина
    window.addEventListener('message', function(event)
    {
        if(event.source != window)
            return;
        var message = event.data;
        //если есть адресс отправителя и сообщение пришло от плагина
        if(message.source && message.source === SignExtension.Enum.ExtentionId )
        {
            if(message.typeOperation)
            {
                //тип операции
                switch(message.typeOperation)
                {
                    //ошибка
                    case SignExtension.Enum.TypeOperation.Error:
                    {
                        if( message.message)
                        {
                            //ошибка от background
                            alert('Attention!\n' + message.message);
                        }
                        else
                        {
                            //ошибка от NativeApp
                            alert('Attention!\n' + message.dataBlock);
                        }
                        break;
                    }
                    //обновление страницы
                    case SignExtension.Enum.TypeOperation.NeedUpdate:
                    {
                        alert('Attention!\n  Background was updated \n ' + message.message);
                        break;
                    }
                    //доступ
                    case SignExtension.Enum.TypeOperation.Access:
                    {
                        alert('Error access! \n' + message.dataBlock);
                        break;
                    }
                    //подпись или проверка
                    default:
                    {
                        if(message.dataBlock)
                        {
                            //ответ полученный от приложения выводится в консоль
                            console.log(message.dataBlock);
                        }
                        break;
                    }
                }
            }
            else
            {
                //вывод в консоль
                console.log('Field :typeOperation not exist');
            }
        }
    });

    /*
    * Структура JSON сообщения
    * {
    *	"source" : "адрес отправителя",
    *	"destination" : "адрес получателя",
    *	"typeDocument" : "тип документа",
    *	"typeOperation" : "тип операции",
    *   "dataBlock" : "пересылаемые приложению данные(строка данных)",
    *	"domainSignature" : "сигнатура домена",
    *	------для XML------
    *	"method" : "алгоритм подписи(RSAwithSHA1 / RSAwithSHA256 / RSAwithSHA512)",
    *	"packing" : "тип контента (ENVELOPED / ENVELOPING / INTERNALLY_DETACHED / EXTERNALLY_DETACHED / HASH_INTERNALLY_DETACHED)",
    *	"format" : "формат подписи (XAdES_BES / XAdES_XL / XAdES_T / XmlDsig)",
    *   "timeStampUri : время подписи",
    *	"contentUri : id узла который будет подписан"
    *	------для PDF------
    *	"startX" : "координаты по оси Х",
    *	"startY" : "координаты по оси Y",
    *	"height" : "высота",
    *	"width" : "ширина",
    *	"pageNumber" : "номер страницы"
    * }
    */
    var SignExtension = SignExtension || {};
    SignExtension.Enum = {
        XmlSignMethod:{
            SHA1 : 1,
            SHA256 : 2,
            SHA512 : 3
        },
        XmlSignType:{
            Enveloped : 1,
            Enveloping : 2,
            InternallyDetached : 3,
            ExternallyDetached: 4,
            HashInternallyDetached: 5
        },
        XmlSignFormat:{
            XAdES_BES : 1,
            XAdES_XL : 2,
            XAdES_T : 3,
            XmlDsig : 4
        },
        //Тип операции
        TypeOperation:{
            //Подпись документа
            Signing: 1,
            //Проверка подписи документа
            Verifty: 2,
            // Ошибка. Этот тип отправляет background или native app в случае возникновения ошибки
            Error: 3,
            //Обновить страницу.
            NeedUpdate: 4,
            //Доступ. Этот тип отправляет native app в том случае, если сайт не меет доступ к плагину или версия плагина отличается от версии установленного app
            Access: 5
        },
        //тип документа
        TypeDocument:{
            XML: 1,
            PDF: 2
        },
        //идентификатор плагина
        ExtentionId: '{B01F58C6-F424-4711-9260-231A12BBEFE5}'
    };

    //-----------------------------------------------------------
    //хэш имени домена сайта (Здесь следует указать ключ доступа к функциям плагина)
    const DOMAIN_SIGNETURE = 'CvPk0Lxu77F/HWld4ukn2ATN7nZE1N+HJ+mEV+Qu7o7NRPyHLSnyihq5Z2c27f2tef/vv6V1fn6/16R3Sg6oAHNvQ+2saPyY6Xg8J8au3A18N' + 
    'gNe5Uya3L/OXVU0VDoeCpP+nAPLT2ZTmD19pQtJfboLvp9D1JXcmMl3KlltykooFUsJmFl4uTxQjbbgbmu6HL27PnGv7w/QNsFBxtTITBMD/uFQaCByNBDHaAjyz2EGgh3DWUl' + 
    'TaMf6bKwOVTF6cMfAgsPj7GJLBuRjSw3nqBBxv16YigdfNvfGf6wVFuu3e+g34qTKO28TrwiKWSE9Oxh0ih2n/9x8HABp7FczVQ==';
    //--------------------------------------------
    /*
    *	отправка запроса плагину
    *	->base64Data - загруженный документ в формате base64
    *	->typeDocument - SignExtension.Enum.TypeDocument.PDF (тип документа pdf)
    *	->typeOperation - SignExtension.Enum.TypeOperation.Signing (тип операции - подпись документа)
    */
    function SendRequest(base64Data,typeDocument, typeOperation)
    {
        var request;
        try
        {
            //разбор строки JSON
            request = JSON.parse('{}');
            SendMessage( base64Data, request, typeDocument, typeOperation );
        }
        catch (e)
        {
            return alert( "Request parse error: " + e.message );
        }
    }
    //------------------------------------------
    /*
    *	отправка сообщения в запросе
    *	->base64Data - данные файла в формате base64
    *	->message - сообщение в формате JSON
    *	->typeDocument - SignExtension.Enum.TypeDocument.PDF (тип документа pdf)
    *	->typeOperation - SignExtension.Enum.TypeOperation.Signing (тип операции - подпись документа)
    */
    function SendMessage(base64Data, message, typeDocument, typeOperation)
    {
        //адрес отправителя
        message.source = window.location.href;
        //тип документа
        message.typeDocument = parseInt(typeDocument, 10);
        //адрес получателя
        message.destination = SignExtension.Enum.ExtentionId;
        //сигнатура домена
        message.domainSignature = DOMAIN_SIGNETURE.toString();
        //тип операции
        message.typeOperation = SignExtension.Enum.TypeOperation.Signing;
        try
        {
            //координаты по оси Х
            message.startX = 10;
            //координаты по оси Y
            message.startY = 10;
            //высота
            message.height = '';
            //ширина
            message.width = '';
            //номер страницы. По умолчанию 0 - подпись будет отображаться на последней странице
            message.pageNumber = 0;
            //если есть заголовок "data:application/pdf;base64,..." удаляем его
            message.dataBlock = base64Data.substr(base64Data.indexOf(',') + 1);
            //отправка сообщения
            window.postMessage(message,"*");
        }
        catch(e)
        {
            //отображение ошибки
            alert(e.message);
            // вывод исключения в консоль
            console.error(e);
        }
    }


    //получение результата от плагина
    window.addEventListener('message', function(event)
    {
        if(event.source != window)
         return;
        var message = event.data;
        //если есть адресс отправителя и сообщение пришло от плагина
        if(message.source && message.source === SignExtension.Enum.ExtentionId )
        {
            if(message.typeOperation)
            {
                //тип операции
                switch(message.typeOperation)
                {
                    //ошибка
                    case SignExtension.Enum.TypeOperation.Error:
                    {
                        if( message.message)
                        {
                            //ошибка от background
                            alert('Attention!\n' + message.message);
                        }
                        else
                        {
                            //ошибка от NativeApp
                            alert('Attention!\n' + message.dataBlock);
                        }
                        break;
                    }
                    //обновление страницы
                    case SignExtension.Enum.TypeOperation.NeedUpdate:
                    {
                        alert('Attention!\n  Background was updated \n ' + message.message);
                        break;
                    }
                    //доступ
                    case SignExtension.Enum.TypeOperation.Access:
                    {
                        alert('Error access! \n' + message.dataBlock);
                        break;
                    }
                    //подпись или проверка
                    default:
                    {
                        if(message.dataBlock)
                        {
                            //Ответ полученный от приложения
                            console.log(message.dataBlock);
                        }
                        break;
                    }
                }
            }
            else
            {
            console.log('Field :typeOperation not exist');
            }
        }
    });

    /*
    * Структура JSON сообщения
    * {
    *	"source" : "адрес отправителя",
    *	"destination" : "адрес получателя",
    *	"typeDocument" : "тип документа",
    *	"typeOperation" : "тип операции",
    *   "dataBlock" : "пересылаемые приложению данные(строка данных)",
    *	"domainSignature" : "сигнатура домена",
    *	------для XML------
    *	"method" : "алгоритм подписи(RSAwithSHA1 / RSAwithSHA256 / RSAwithSHA512)",
    *	"packing" : "тип контента (ENVELOPED / ENVELOPING / INTERNALLY_DETACHED / EXTERNALLY_DETACHED / HASH_INTERNALLY_DETACHED)",
    *	"format" : "формат подписи (XAdES_BES / XAdES_XL / XAdES_T / XmlDsig)",
    *   "timeStampUri : время подписи",
    *	"contentUri : id узла который будет подписан"
    *	------для PDF------
    *	"startX" : "координаты по оси Х",
    *	"startY" : "координаты по оси Y",
    *	"height" : "высота",
    *	"width" : "ширина",
    *	"pageNumber" : "номер страницы"
    * }
    */
    var SignExtension = SignExtension || {};
    SignExtension.Enum = {
        XmlSignMethod:{
            SHA1 : 1,
            SHA256 : 2,
            SHA512 : 3
        },
        XmlSignType:{
            Enveloped : 1,
            Enveloping : 2,
            InternallyDetached : 3,
            ExternallyDetached: 4,
            HashInternallyDetached: 5
        },
        XmlSignFormat:{
            XAdES_BES : 1,
            XAdES_XL : 2,
            XAdES_T : 3,
            XmlDsig : 4
        },
        //Тип операции
        TypeOperation:{
            //Подпись документа
            Signing: 1,
            //Проверка подписи документа
            Verifty: 2,
            // Ошибка. Этот тип отправляет background или native app в случае возникновения ошибки
            Error: 3,
            //Обновить страницу.
            NeedUpdate: 4,
            //Доступ. Этот тип отправляет native app в том случае, если сайт не меет доступ к плагину или версия плагина отличается от версии установленного app
            Access: 5
        },
        //тип документа
        TypeDocument:{
            XML: 1,
            PDF: 2
        },
        //идентификатор плагина
        ExtentionId: '{B01F58C6-F424-4711-9260-231A12BBEFE5}'
    };

    //-----------------------------------------------------------
    //хэш имени домена сайта (Здесь следует указать ключ доступа к функциям плагина)
    const DOMAIN_SIGNETURE = 'CvPk0Lxu77F/HWld4ukn2ATN7nZE1N+HJ+mEV+Qu7o7NRPyHLSnyihq5Z2' + 
    'c27f2tef/vv6V1fn6/16R3Sg6oAHNvQ+2saPyY6Xg8J8au3A18NgNe5Uya3L/OXVU0VDoeCpP+nAPLT2ZTmD1' + 
    '9pQtJfboLvp9D1JXcmMl3KlltykooFUsJmFl4uTxQjbbgbmu6HL27PnGv7w/QNsFBxtTITBMD/uFQaCByNBD' + 
    'HaAjyz2EGgh3DWUlTaMf6bKwOVTF6cMfAgsPj7GJLBuRjSw3nqBBxv16YigdfNvfGf6wVFuu3e+g34qTKO28T' + 
    'rwiKWSE9Oxh0ih2n/9x8HABp7FczVQ==';
    //--------------------------------------------
    /*
    *	отправка запроса плагину
    *	->data - загруженный документ в формате base64(документ PDF)/ xml строка (документ xml)
    *	->typeDocument - SignExtension.Enum.TypeDocument.PDF (тип документа pdf)/SignExtension.Enum.TypeDocument.XML(тип документа xml)
    *	->typeOperation - SignExtension.Enum.TypeOperation.Verifty (тип операции - проверка подписи документа)
    */
    function SendRequest(data,typeDocument, typeOperation)
    {
        var request;
        try
        {
            //разбор строки JSON
            request = JSON.parse('{}');
            SendMessage( base64Data, request, typeDocument, typeOperation );
        }
        catch (e)
        {
            //отображение ошибки
            return alert( "Request parse error: " + e.message );
        }
    }
    //------------------------------------------
    /*
    *	отправка сообщения в запросе
    *	->data - загруженный документ в формате base64(документ PDF)/ xml строка (документ xml)
    *	->message - сообщение в формате JSON
    *	->typeDocument - SignExtension.Enum.TypeDocument.PDF (тип документа pdf)/SignExtension.Enum.TypeDocument.XML(тип документа xml)
    *	->typeOperation - SignExtension.Enum.TypeOperation.Verifty (тип операции - проверка подписи документа)
    */
    function SendMessage(data, message, typeDocument, typeOperation)
    {
        //адрес отправителя
        message.source = window.location.href;
        //тип документа
        message.typeDocument = parseInt(typeDocument, 10);
        //адрес получателя
        message.destination = SignExtension.Enum.ExtentionId;
        //сигнатура домена
        message.domainSignature = DOMAIN_SIGNETURE.toString();
        //тип операции
        message.typeOperation = SignExtension.Enum.TypeOperation.Verifty;
        try
        {
            //тип документа PDF
            if(typeDocument ===  SignExtension.Enum.TypeDocument.PDF )
            {
                message.dataBlock = data.substr(data.indexOf(',') + 1);
            }
            //тип документа XML
            else if(typeDocument === SignExtension.Enum.TypeDocument.XML)
            {
                message.dataBlock = data;
            }
            else
            {
                alert("Unckown typeDocument");
                return;
            }
            window.postMessage(message,"*");
        }
        catch(e)
        {
            //отображение ошибки
            alert(e.message);
            // вывод исключения в консоль
            console.error(e);
        }
    }

    //получение результата от плагина
    window.addEventListener('message', function(event)
    {
        if(event.source != window)
            return;
        var message = event.data;
        //если есть адресс отправителя и сообщение пришло от плагина
        if(message.source && message.source === SignExtension.Enum.ExtentionId )
        {
            if(message.typeOperation)
            {
                //тип операции
                switch(message.typeOperation)
                {
                    //ошибка
                    case SignExtension.Enum.TypeOperation.Error:
                    {
                        if( message.message)
                        {
                            //ошибка от background
                            alert('Attention!\n' + message.message);
                        }
                        else
                        {
                            //ошибка от NativeApp
                            alert('Attention!\n' + message.dataBlock);
                        }
                        break;
                    }
                    //обновление страницы
                    case SignExtension.Enum.TypeOperation.NeedUpdate:
                    {
                        alert('Attention!\n  Background was updated \n ' + message.message);
                        break;
                    }
                    //доступ
                    case SignExtension.Enum.TypeOperation.Access:
                    {
                        alert('Error access! \n' + message.dataBlock);
                        break;
                    }
                    //подпись или проверка
                    default:
                    {
                        if(message.dataBlock)
                        {
                            //Ответ полученный от приложения
                            console.log(message.dataBlock);
                            //AddEmbed(message.dataBlock);
                        }
                        break;
                        }
                    }
                }
            else
            {
                console.log('Field :typeOperation not exist');
            }
        }
    });
Введите xml документ:
Подписанный документ
Результат