Sign 26.900.0: представитель компании подписывает кадровые документы Госключом
Sign 26.900.0 для коробочного Битрикс24 добавляет в мастер КЭДО выбор, чем подписывает представитель компании: УКЭП или Госключом. Выбор появится только у компаний с провайдером goskey-lite и только там, где его открыл сервис подписи. Ещё переписали повторную отправку документа из таймлайна, и uid участника из чужого документа она больше не примет.
Новое
Выберите, чем подпишет представитель компании
На шаге сторон в мастере кадрового документа появился список «Способ подписи представителя» с двумя значениями: «УКЭП» и «Госключ (УКЭП для Гендиректора)». Список виден, если у компании выбран провайдер goskey-lite и сервис подписи вернул флаг goskey_representative_signing_available. В PHP флаг лежит в Item\Company::$goskeyRepresentativeSigningAvailable, отдельно от промо-флага goskeyLiteAvailable. Если goskey-lite ограничен тарифом, флаг сбрасывается в false. Раскаткой управляет сервис подписи по client id, он и решает, кому показывать список.
Если сервис подписи прислал для представителя поле СНИЛС, модуль оставляет его только при подписи Госключом и помечает обязательным. В остальных случаях поле выбрасывается.
Обрабатывайте отказ при сохранении сторон
Сам портал проверяет только два условия. Госключ допустим, когда представитель задан конкретным человеком (роль из структуры компании не подходит) и провайдер документа GOS_KEY_LITE. Отказ приходит с кодом SIGNING_METHOD_PERMISSION_REQUIRED, а проверка стоит в трёх местах:
- AJAX
sign.api_v1.document.member.checkRepresentativeSigningMethodс параметрамиdocumentUid,representativeId,signingMethodиrepresentativeEntityType(по умолчаниюEntityType::USER). Нужно правоACTION_DOCUMENT_EDITилиACTION_B2E_DOCUMENT_EDIT. Мастер вызывает его, когда уходит со шага.representativeIdпроверяется только на> 0и дальше не используется. setupB2ePartiesпринимаетsigningMethodу участника с ролью assignee и проверяет то же самое. На неизвестное значение он отвечает «InvalidsigningMethodvalue».loadтеперь отдаётsigningMethodкаждого участника.Service\Sign\Document\DirectorSigningGuardService::check()срабатывает на пути к подписанию, его вызываютOperation\ConfigureDocumentиConfigureFillAndStart. Во втором проверку продублировали, потому что документ в статусе READY проходит мимоConfigureDocument.
Если у вас свой мастер или документы запускаются из кода, обрабатывайте ошибку SIGNING_METHOD_PERMISSION_REQUIRED и при сохранении сторон, и при старте. Одного checkRepresentativeSigningMethod для этого мало: мастер берёт его ответ как подсказку, а сохранение сторон и старт проверяют заново. Код ошибки сравнивайте с константой DirectorSigningGuardService::ERROR_CODE_NOT_ALLOWED.
Значения лежат в Type\Member\SigningMethod: GOS_KEY = 'goskey', UKEP = 'ukep', плюс getAll() и isValid(). Класс повторяет закрытый \Bitrix\SignSafe\Type\Member\SigningMethod. Неизвестное значение signsafe считает невыбранным способом, то есть УКЭП, поэтому портал отказывает явно и мусор не сохраняет. Экшены мастера прогоняют значение через SigningMethod::isValid(). Делайте так же, когда пишете способ сами через новый последний параметр MemberService::addForDocument(..., signingMethod: ...).
DirectorSigningGuardService можно получить через Container::getDirectorSigningGuardService() (сервис sign.service.sign.document.directorSigningGuard) и вызвать заранее. Вот как найти документы, где представитель выбрал Госключ, и узнать, какие из них проверку не пройдут:
<?php declare(strict_types=1);
use Bitrix\Main\Loader;
use Bitrix\Sign\Internal\MemberTable;
use Bitrix\Sign\Service\Container;
use Bitrix\Sign\Type\Member\Role;
use Bitrix\Sign\Type\Member\SigningMethod;
Loader::requireModule('sign');
$rows = MemberTable::query()
->setSelect(['DOCUMENT_ID'])
->where('ROLE', Role::convertRoleToInt(Role::ASSIGNEE))
->where('SIGNING_METHOD', SigningMethod::GOS_KEY)
->setOrder(['ID' => 'DESC'])
->setLimit(50)
->fetchAll();
$container = Container::instance();
$documents = $container->getDocumentRepository();
$guard = $container->getDirectorSigningGuardService();
foreach ($rows as $row) {
$document = $documents->getById((int)$row['DOCUMENT_ID']);
if ($document === null) {
continue;
}
$result = $guard->check($document);
if (!$result->isSuccess()) {
printf("%d: %s\n", $document->id, implode('; ', $result->getErrorMessages()));
}
}
ROLE в таблице хранится числом, поэтому роль переводится через Role::convertRoleToInt().
Что сломается
Передавайте зависимости ConfigureFillAndStart по именам
Как и в 26.800.0, новый параметр вставили в середину конструктора. В Operation\ConfigureFillAndStart::__construct параметр ?DirectorSigningGuardService $directorSigningGuardService стоит перед ?DocumentAgentService $documentAgentService. new ConfigureFillAndStart($uid) работает как раньше. Если же вы передавали DocumentAgentService четвёртым аргументом, например мок в тесте, получите TypeError.
Новые параметры MemberService::addForDocument, Item\Company, Item\B2e\RequiredField и Item\Api\Property\Request\Signing\Configure\Member добавлены в конец сигнатур и необязательны.
БД
В b_sign_member появилась колонка SIGNING_METHOD varchar(20), в Bitrix\Sign\Internal\MemberTable — поле SIGNING_METHOD (StringField, size 20, nullable). MemberRepository его читает и пишет, а у Item\Member есть свойство signingMethod.
Мелочи и находки
- Повторная отправка из таймлайна (
Controller\Internal\Document::resendFileAction) для документов версии 2 и новее теперь всегда идёт через сервис подписи: кадровые получаютsendInvite, остальныеresendMessage. Раньше через сервис шла только версия 2, и всегда черезsendInvite. V3 и V4, а с V4 создаются все новые документы, уходили в старыйProxy::sendCommand('document.resend').memberHashтеперь должен быть uid участника этого же документа, иначе ответACCESS_DENIED: раньше значение из запроса без проверки подставлялось в путь запроса к сервису подписи. Прокси остался только для V1, и там участник, которого не нашли по хешу, тоже даётACCESS_DENIED. - В
Item\Member::__constructмеждуroleиconfiguredпоявился?string $signingMethod. Сдвиг заденет только вызов, где по позиции передано двадцать аргументов и больше. - В
.settings.phpпоявился регионmd: адрес сервисаhttps://sign.bitrix24.eu, доменhttps://www.bitrix24.md. Включеныservice.publicity,service.b2e.publicity,service.b2e.document-message.publicityиservice.b2e.robot.publicity, аservice.b2e.init-by-employee.publicityвыключен. - У
Item\B2e\RequiredFieldпоявился флагrequired(по умолчанию true). Он читается из ключаrequiredв списке полей и отдаётся вtoArray().