diff --git a/config/config.xml.default b/config/config.xml.default index 7eb313e836723950782ad7a95ddbbb649cef0940..16f1e791a98da36b9594e0811d00aeada2e4c376 100755 --- a/config/config.xml.default +++ b/config/config.xml.default @@ -35,6 +35,32 @@ <organizationalUnitCode></organizationalUnitCode> <signatureIdOverride></signatureIdOverride> <!-- 1 for provider (fournisseur) signature, 2 for Contralia signature, leave blank to use client signature (default) --> </docaposteSignature> + <metaSignSignature> + <enable>false</enable> + <url></url> + <port></port> + <instance></instance> + <certPath></certPath> + <certPass></certPass> + <certType></certType> + <metaSign> + <inDelegationOf></inDelegationOf> + <secret> + <password></password> + <type></type> + </secret> + <signatureKeyId></signatureKeyId> + <signatureProfile> + <signaturePolicyOid></signaturePolicyOid> + <attachment></attachment> + <format></format> + <augmentationLevel></augmentationLevel> + <signatureAlgoId></signatureAlgoId> + <archive></archive> + <requireSigningTime></requireSigningTime> + </signatureProfile> + </metaSign> + </metaSignSignature> <!-- Sort by the more secure to the less secure mode --> <signatureModes> <!-- <mode> @@ -65,6 +91,11 @@ <subject></subject> <keyUsage>digitalSignature</keyUsage> </mode> --> + <!-- <mode> + <id>eidas_metasign</id> + <color>#00FF00</color> + <keyUsage>metaSignSignature</keyUsage> + </mode> --> <!-- <mode> <id>eidas</id> <color>#00FF00</color> diff --git a/lang/en.json b/lang/en.json index 4bfab44034c51d94156e5f107721cf0289c8cef5..7cfeaca1c3be7c8bc995c6a7f2778e3bba0c170e 100755 --- a/lang/en.json +++ b/lang/en.json @@ -666,7 +666,10 @@ "hardDelete": "Delete files", "hardDeleted": "Deleted files", "cannotAcces": "Unable to access document", - "inputCardReaderUpdateCerts": "Card entry detected, please update your certificates", - "outputCardReaderUpdateCerts": "Card output detected, please update your certificates" + "metaSignSignatureDisabled": "The metaSignSignature parameter is disabled", + "eidas_metasign": "Metasign Stamp", + "eidas_metasignUser": "Metasign Stamp", + "inputCardReaderUpdateCerts": "Card entry detected, updating certificates...", + "outputCardReaderUpdateCerts": "Card output detected, updating certificates..." } -} \ No newline at end of file +} diff --git a/lang/fr.json b/lang/fr.json index 3d7c3c12a990b6ca279f5c3ccf1428ddf39a5de7..29b28724f647df17acdca9f487c0bb8a01c978d0 100755 --- a/lang/fr.json +++ b/lang/fr.json @@ -665,6 +665,9 @@ "cannotAcces": "Impossible d'accéder au document", "softDeleted": "Marqué comme supprimé", "hardDeleted":"Fichiers supprimés", + "metaSignSignatureDisabled": "Le paramètre metaSignSignature n'est pas activé", + "eidas_metasign": "Cachet Metasign", + "eidas_metasignUser": "Cachet Metasign", "inputCardReaderUpdateCerts": "Une entrée de carte détectée, actualisation des certificats...", "outputCardReaderUpdateCerts": "Une sortie de carte détectée, actualisation des certificats..." } diff --git a/src/app/document/controllers/DocumentController.php b/src/app/document/controllers/DocumentController.php index 84a4d0944fa1ec4cb78cd87df8e6c1c32e25451d..b2cd37b8459b52873588a309522f0f60cb5d77c5 100755 --- a/src/app/document/controllers/DocumentController.php +++ b/src/app/document/controllers/DocumentController.php @@ -460,6 +460,7 @@ class DocumentController $hasEidas = false; + $hasMetaSignSignature = false; $hasElectronicSignature = false; foreach ($body['workflow'] as $key => $workflow) { $processingUser = null; @@ -521,6 +522,9 @@ class DocumentController if (in_array($workflow['signatureMode'], ['eidas', 'rgs_2stars_timestamped', 'inca_card_eidas'])) { $hasEidas = true; } + if ($workflow['signatureMode'] == 'eidas_metasign' && $workflow['mode'] == 'sign') { + $hasMetaSignSignature = true; + } if ($workflow['signatureMode'] != 'stamp' && $workflow['mode'] == 'sign') { $hasElectronicSignature = true; } @@ -529,7 +533,8 @@ class DocumentController $libDir = CoreConfigModel::getLibrariesDirectory(); $loadedXml = CoreConfigModel::getConfig(); - if ($loadedXml->docaposteSignature->enable == 'true' && $hasEidas && (empty($libDir) || !is_file($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php'))) { + if (($loadedXml->docaposteSignature->enable == 'true' || $loadedXml->metaSignSignature->enable == 'true') && + ($hasEidas || $hasMetaSignSignature) && (empty($libDir) || !is_file($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php'))) { return $response->withStatus(500)->withJson(['errors' => 'SetaPDF-Signer library is not installed', 'lang' => 'setAPdfSignerError']); } @@ -772,6 +777,12 @@ class DocumentController return $response->withStatus(500)->withJson(['errors' => $result['errors']]); } } + if ($loadedXml->metaSignSignature->enable == 'true' && $hasMetaSignSignature) { + $metaSignInit = MetaSignSignatureController::init(); + if (!empty($metaSignInit['errors'])) { + return $response->withStatus($metaSignInit['code'])->withJson(['errors' => $metaSignInit['errors']]); + } + } if (empty($body['workflow'][0]['userId'])) { if ($body['workflow'][0]['externalInformations']['type'] == 'yousign') { @@ -816,16 +827,20 @@ class DocumentController } require_once($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php'); - if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && $workflow['signature_mode'] != 'eidas') { + if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && !in_array($workflow['signature_mode'], ['eidas', 'eidas_metasign'])) { $url = UrlController::getCoreUrl(); if (strpos($url, 'https://') !== 0) { return $response->withStatus(400)->withJson(['errors' => 'Url is not secured (https needed)', 'lang' => 'securedUrlNeeded']); } } } + if (in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas']) && $loadedXml->docaposteSignature->enable != 'true') { return $response->withStatus(400)->withJson(['errors' => 'docaposteSignature is disabled', 'lang' => 'docaposteSignatureDisabled']); } + if ($workflow['signature_mode'] == 'eidas_metasign' && $loadedXml->metaSignSignature->enable != 'true') { + return $response->withStatus(400)->withJson(['errors' => 'metaSignSignature is disabled', 'lang' => 'metaSignSignatureDisabled']); + } $body = $request->getParsedBody(); if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && $workflow['signature_mode'] == 'stamp') { @@ -1044,7 +1059,7 @@ class DocumentController } } - if (in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) { + if (in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas', 'eidas_metasign'])) { if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && $workflow['mode'] == 'sign') { $imageSignature = false; $adr = AdrModel::getDocumentsAdr([ @@ -1054,6 +1069,10 @@ class DocumentController ]); $docserver = DocserverModel::getByType(['type' => 'ESIGN', 'select' => ['path']]); $pathToDocument = $docserver['path'] . $adr[0]['path'] . $adr[0]['filename']; + + if ($loadedXml->metaSignSignature->enable == 'true' && $workflow['signature_mode'] == 'eidas_metasign') { + $pathToDocument = MetaSignSignatureController::getDocumentPath(['documentId' => (int) $args['id']]); + } $tmpPath = CoreConfigModel::getTmpPath(); $signedDocumentPath = $tmpPath . $GLOBALS['id'] . '_' . rand() . '_signedDocument.pdf'; $writer = new \SetaPDF_Core_Writer_File($signedDocumentPath); @@ -1092,39 +1111,63 @@ class DocumentController $signPosX = ($signature['positionX'] * $format['width']) / 100; $signPosY = ($signature['positionY'] * $format['height']) / 100; } - $return = DigitalSignatureController::signHashes([ - 'signatureId' => $workflow['digital_signature_id'], - 'documentId' => $args['id'], - 'signatureInfo' => [ - 'page' => $signature['page'], - 'positionX' => $signPosX, - 'positionY' => $signPosY, - 'filePath' => $imageTmpPath, - 'signWidth' => $signWidth - ], - 'isLastSignature' => !isset($body['signatures'][$key + 1]), - 'workflowId' => $workflow['id'] - ]); + if ($loadedXml->docaposteSignature->enable == 'true' && !empty($workflow['digital_signature_id']) && in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) { + $return = DigitalSignatureController::signHashes([ + 'signatureId' => $workflow['digital_signature_id'], + 'documentId' => $args['id'], + 'signatureInfo' => [ + 'page' => $signature['page'], + 'positionX' => $signPosX, + 'positionY' => $signPosY, + 'filePath' => $imageTmpPath, + 'signWidth' => $signWidth + ], + 'isLastSignature' => !isset($body['signatures'][$key + 1]), + 'workflowId' => $workflow['id'] + ]); + } else if ($loadedXml->metaSignSignature->enable == 'true' && $workflow['signature_mode'] == 'eidas_metasign') { + $return = MetaSignSignatureController::signDocument([ + 'documentId' => (int) $args['id'], + 'signatureInfo' => [ + 'page' => $signature['page'], + 'positionX' => $signPosX, + 'positionY' => $signPosY, + 'filePath' => $imageTmpPath, + 'signWidth' => $signWidth + ], + 'isLastSignature' => !isset($body['signatures'][$key + 1]) + ]); + } if (!empty($return['errors'])) { - return $response->withStatus(400)->withJson($return); + return $response->withStatus($return['code'] ?? 400)->withJson(['errors' => $return['errors']]); } $imageSignature = true; } } } } - if (!$imageSignature) { + if (!$imageSignature && $loadedXml->docaposteSignature->enable == 'true' && !empty($workflow['digital_signature_id']) && in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) { $return = DigitalSignatureController::signHashes([ - 'signatureId' => $workflow['digital_signature_id'], - 'documentId' => $args['id'], - 'isLastSignature' => true, - 'workflowId' => $workflow['id'] + 'signatureId' => $workflow['digital_signature_id'], + 'documentId' => $args['id'], + 'workflowId' => $workflow['id'], + 'isLastSignature' => true ]); if (!empty($return['errors'])) { return $response->withStatus(400)->withJson($return); } } - } elseif (DocumentController::ACTIONS[$args['actionId']] == 'REF' && $workflow['mode'] == 'sign') { + if (!$imageSignature && $loadedXml->metaSignSignature->enable == 'true' && $workflow['signature_mode'] == 'eidas_metasign') { + $return = MetaSignSignatureController::signDocument(['documentId' => (int) $args['id'], 'isLastSignature' => true]); + if (!empty($return['errors'])) { + return $response->withStatus($return['code'])->withJson(['errors' => $return['errors']]); + } + } + } elseif (DocumentController::ACTIONS[$args['actionId']] == 'REF' && + $workflow['mode'] == 'sign' && + $loadedXml->docaposteSignature->enable == 'true' && + !empty($workflow['digital_signature_id']) && in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) { + $return = DigitalSignatureController::abort(['signatureId' => $workflow['digital_signature_id'], 'documentId' => $args['id']]); if (!empty($return['errors'])) { return $response->withStatus(400)->withJson($return); diff --git a/src/app/document/controllers/MetaSignSignatureController.php b/src/app/document/controllers/MetaSignSignatureController.php new file mode 100644 index 0000000000000000000000000000000000000000..67fa497546af7d15ad2bbf2b98da7118adcd6908 --- /dev/null +++ b/src/app/document/controllers/MetaSignSignatureController.php @@ -0,0 +1,318 @@ +<?php + +/** +* Copyright Maarch since 2022 under license. +* See LICENSE.txt file at the root folder for more details. +* This file is part of Maarch software. +* +*/ + +/** +* @brief MetaSign Signature Controller +* @author dev@maarch.org +*/ + +namespace Document\controllers; + +use Docserver\controllers\DocserverController; +use Docserver\models\AdrModel; +use Docserver\models\DocserverModel; +use Document\models\DocumentModel; +use SrcCore\models\CoreConfigModel; +use SrcCore\models\CurlModel; +use User\models\UserModel; +use Workflow\models\WorkflowModel; +use SrcCore\models\ValidatorModel; + +class MetaSignSignatureController +{ + public static $signatureLength = 30000; + + + /** + * @description Get config for Metasign signature + * @return false|array + */ + private static function getConfig() + { + $loadedXml = CoreConfigModel::getConfig(); + if ($loadedXml->metaSignSignature->enable == 'true') { + $config = [ + 'url' => (string)$loadedXml->metaSignSignature->url, + 'port' => (string)$loadedXml->metaSignSignature->port, + 'instance' => (string)$loadedXml->metaSignSignature->instance, + 'certPath' => (string)$loadedXml->metaSignSignature->certPath, + 'certPass' => (string)$loadedXml->metaSignSignature->certPass, + 'certType' => (string)$loadedXml->metaSignSignature->certType, + 'metaSign' => [ + 'inDelegationOf' => (string)$loadedXml->metaSignSignature->metaSign->inDelegationOf, + 'secret' => [ + "password" => (string)$loadedXml->metaSignSignature->metaSign->secret->password, + "type" => (string)$loadedXml->metaSignSignature->metaSign->secret->type + ], + 'signatureKeyId' => (string)$loadedXml->metaSignSignature->metaSign->signatureKeyId, + 'signatureProfile' => [ + 'profile' => [ + 'signaturePolicyOid' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->signaturePolicyOid, + 'attachment' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->attachment, + 'format' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->format, + 'augmentationLevel' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->augmentationLevel, + 'signatureAlgoId' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->signatureAlgoId, + 'archive' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->archive, + 'requireSigningTime' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->requireSigningTime, + ] + ] + ] + ]; + return $config; + } else { + return false; + } + } + + /** + * @description Check if the user/certificate can sign documents + * @return array|true errors|true + */ + public static function init() + { + $config = MetaSignSignatureController::getConfig(); + if(empty($config)) { + return ['code' => 400, 'errors' => "MetaSgin configuration not found!"]; + } + + $curlResponse = CurlModel::exec([ + 'url' => $config['url'] . (empty($config['port']) ? '' : ":{$config['port']}") . "/servlets/{$config['instance']}/com.bull.security.signserver.rest/signserver/info", + 'method' => 'GET', + 'headers' => ['content-type:application/json', 'Accept: application/json'], + 'options' => [ + CURLOPT_SSLCERT => $config['certPath'], + CURLOPT_SSLCERTPASSWD => $config['certPass'], + CURLOPT_SSLCERTTYPE => $config['certType'] + ] + ]); + + if ($curlResponse['code'] != 200) { + return ['code' => $curlResponse['code'], 'errors' => $curlResponse['errors']]; + } elseif (empty($curlResponse['response']['methods'])) { + return ['code' => 500, 'errors' => "MetaSign api endpoints not found"]; + }elseif (!empty($curlResponse['response']['methods']) && !in_array("sigOps/signDoc", $curlResponse['response']['methods'])) { + return ['code' => 405, 'errors' => "User does not have access to API endpoint to 'sign document' on MetaSign"]; + } + return true; + } + + /** + * @description Get document path from docserver + * @param array $args + * @return string|array filePath|errors + */ + public static function getDocumentPath(array $args) + { + ValidatorModel::notEmpty($args, ['documentId']); + ValidatorModel::intType($args, ['documentId']); + + $adr = AdrModel::getDocumentsAdr([ + 'select' => ['type', 'CONCAT(path, filename) as path_and_filename'], + 'where' => ['main_document_id = ?', "type IN ('DOC', 'ESIGN')"], + 'data' => [$args['documentId']] + ]); + if (empty($adr)) { + return ['code' => 404, 'errors' => '[MetaSignSignatureController][getDocumentPath] Document does not exist']; + } + + $docAdr = []; + $docTypes = array_column($adr, 'path_and_filename', 'type'); + + if (!empty($docTypes['DOC'])) { + $docAdr = ['type' => 'DOC', 'pathAndFilename' => $docTypes['DOC']]; + } + if (!empty($docTypes['ESIGN'])) { + $docAdr = ['type' => 'ESIGN', 'pathAndFilename' => $docTypes['ESIGN']]; + } + + $docserver = DocserverModel::getByType(['type' => $docAdr['type'], 'select' => ['path']]); + if (empty($docserver['path']) || !file_exists($docserver['path'])) { + return ['code' => 404, 'errors' => 'Docserver does not exist']; + } + + $pathToDocument = $docserver['path'] . $docAdr['pathAndFilename']; + if (!is_file($pathToDocument) || !is_readable($pathToDocument)) { + return ['code' => 404, 'errors' => 'Document not found on docserver or not readable']; + } + + return $pathToDocument; + } + + /** + * @description Prepare, sign and save document + * @param array $args + * @return true|array + */ + public static function signDocument(array $args) + { + ValidatorModel::notEmpty($args, ['documentId']); + ValidatorModel::intType($args, ['documentId']); + ValidatorModel::arrayType($args, ['signatureInfo']); + + $config = MetaSignSignatureController::getConfig(); + if(empty($config)) { + return ['code' => 400, 'errors' => "MetaSign configuration not found!"]; + } + + $pathToDocument = MetaSignSignatureController::getDocumentPath(['documentId' => $args['documentId']]); + if (!empty($pathToDocument['errors'])) { + return $pathToDocument; + } + + $libDir = CoreConfigModel::getLibrariesDirectory(); + if (empty($libDir) || !is_file($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php')) { + return ['code' => 404, 'errors' => 'SetaPDF-Signer library is not installed']; + } + require_once($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php'); + + $tmpPath = CoreConfigModel::getTmpPath(); + $signedDocumentPath = $tmpPath . $GLOBALS['id'] . '_' . rand() . '_signedDocument.pdf'; + $writer = new \SetaPDF_Core_Writer_File($signedDocumentPath); + $document = \SetaPDF_Core_Document::loadByFilename($pathToDocument, $writer); + + $signer = new \SetaPDF_Signer($document); + + $user = UserModel::getById(['id' => $GLOBALS['id'], 'select' => ['firstname', 'lastname', 'email']]); + $signer->setName($user['firstname'] . ' ' . $user['lastname'] . ' ('. $user['email'] . ')'); + $signer->setReason('Signature du document par ' . $user['firstname'] . ' ' . $user['lastname']); + $signer->setLocation('Maarch Parapheur'); + + $signer->setSignatureContentLength(self::$signatureLength); + $signer->setAllowSignatureContentLengthChange(true); + + if (!empty($args['signatureInfo'])) { + $image = \SetaPDF_Core_Image::getByPath($args['signatureInfo']['filePath']); + $imageXObject = $image->toXObject($document); + $width = $args['signatureInfo']['signWidth']; + $height = $imageXObject->getHeight($width); + $signatureFieldWith = $width > 200 ? $width : 200; + + $fieldName = $signer->addSignatureField( + 'Signature_' . rand(), + $args['signatureInfo']['page'], + \SetaPDF_Signer_SignatureField::POSITION_LEFT_TOP, + ['x' => $args['signatureInfo']['positionX'], 'y' => -$args['signatureInfo']['positionY']], + $signatureFieldWith, + $height + 50 + )->getQualifiedName(); + + $signer->setSignatureFieldName($fieldName); + + $xObject = \SetaPDF_Core_XObject_Form::create($document, [0, 0, $signatureFieldWith, $height + 50]); + $canvas = $xObject->getCanvas(); + $imageXObject->draw($canvas, 0, 50, $width, $height); + + $font = new \SetaPDF_Core_Font_Type0_Subset( + $document, + __DIR__ . '/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf' + ); + + $loadedXml = CoreConfigModel::getConfig(); + if ($loadedXml->textWithDigitalSignature == 'true') { + $textBlock = new \SetaPDF_Core_Text_Block($font, 7); + $textBlock->setWidth($signatureFieldWith); + $textBlock->setLineHeight(14); + $textBlock->setPadding(2); + $textBlock->setText("Signé électroniquement par : " . $user['firstname'] . ' ' . $user['lastname'] . "\nLe " . date('c')); + $textBlock->draw($canvas, 0, 30); + } + + $appearance = new \SetaPDF_Signer_Signature_Appearance_XObject($xObject); + $signer->setAppearance($appearance); + } else { + $fieldName = $signer->addSignatureField()->getQualifiedName(); + $signer->setSignatureFieldName($fieldName); + } + + $tmpDocument = $signer->preSign(new \SetaPDF_Core_Writer_TempFile()); + + $fileHash = hash_file('sha256', $tmpDocument->getHashFile()->getPath()); + $binaryHash = hex2bin($fileHash); + $resultSignature = MetaSignSignatureController::signHash([ + 'config' => $config, + 'docHash' => base64_encode($binaryHash)]); + if (!empty($resultSignature['errors']) || !empty($resultSignature['code'])) { + return ['code' => $resultSignature['code'], 'errors' => $resultSignature['errors']]; + } + + try { + $signer->saveSignature($tmpDocument, $resultSignature['signatureContent']); + } catch (\SetaPDF_Signer_Exception_ContentLength $e) { + self::$signatureLength = self::$signatureLength + 1000; + MetaSignSignatureController::signDocument($args); + return true; + } + + $storeResInfos = DocserverController::storeResourceOnDocServer([ + 'encodedFile' => base64_encode(file_get_contents($signedDocumentPath)), + 'format' => 'pdf', + 'docserverType' => 'ESIGN' + ]); + + if (!empty($storeResInfos['errors'])) { + return ['errors' => $storeResInfos['errors']]; + } + + AdrModel::deleteDocumentAdr([ + 'where' => ['main_document_id = ?', 'type = ?'], + 'data' => [$args['documentId'], 'ESIGN'] + ]); + AdrModel::createDocumentAdr([ + 'documentId' => $args['documentId'], + 'type' => 'ESIGN', + 'path' => $storeResInfos['path'], + 'filename' => $storeResInfos['filename'], + 'fingerprint' => $storeResInfos['fingerprint'] + ]); + unlink($signedDocumentPath); + + return true; + } + + /** + * @description Send document hash to be signed from MetaSign server + * @param array $args + * @return array Return signature content from MetaSign server + */ + private static function signHash(array $args) + { + ValidatorModel::notEmpty($args, ['docHash', 'config']); + ValidatorModel::stringType($args, ['docHash']); + ValidatorModel::arrayType($args, ['config']); + + $curlResponse = CurlModel::exec([ + 'url' => $args['config']['url'] . (empty($args['config']['port']) ? '' : ":{$args['config']['port']}") . "/servlets/{$args['config']['instance']}/com.bull.security.signserver.rest/signserver/sigOps/signDoc", + 'method' => 'POST', + 'headers' => ['content-type:application/json', 'Accept: application/json'], + 'options' => [ + CURLOPT_SSLCERT => $args['config']['certPath'], + CURLOPT_SSLCERTPASSWD => $args['config']['certPass'], + CURLOPT_SSLCERTTYPE => $args['config']['certType'] + ], + 'body' => json_encode([ + "inDelegationOf" => $args['config']['metaSign']['inDelegationOf'], + "secret" => [ + "password" => $args['config']['metaSign']['secret']['password'], + "type" => $args['config']['metaSign']['secret']['type'] + ], + "signatureKeyId" => $args['config']['metaSign']['signatureKeyId'], + "signatureProfile" => $args['config']['metaSign']['signatureProfile'], + "document" => [ + "docHash" => $args['docHash'] + ] + ]) + ]); + + if ($curlResponse['code'] != 200) { + return ['code' => $curlResponse['code'], 'errors' => $curlResponse['response']['errorInfo'] ?? $curlResponse['errors']]; + } + + return ['signatureContent' => base64_decode($curlResponse['response']['signatureContent']['bytes'])]; + } +} \ No newline at end of file diff --git a/src/app/history/controllers/HistoryController.php b/src/app/history/controllers/HistoryController.php index 2d0270b5472506a3745dad4f000935ab805e9804..adf0e120988ef8b057ae43fa180cd7cde72b7c57 100644 --- a/src/app/history/controllers/HistoryController.php +++ b/src/app/history/controllers/HistoryController.php @@ -402,7 +402,7 @@ class HistoryController $workflowTerminated = true; $workflowCompleted = true; foreach ($workflow as $step) { - if (!$hasCertificate && in_array($step['signature_mode'], ['eidas', 'rgs_2stars', 'rgs_2stars_timestamped', 'inca_card', 'inca_card_eidas'])) { + if (!$hasCertificate && in_array($step['signature_mode'], ['eidas', 'eidas_metasign', 'rgs_2stars', 'rgs_2stars_timestamped', 'inca_card', 'inca_card_eidas'])) { $hasCertificate = true; } if (empty($step['status'])) { diff --git a/src/core/models/CurlModel.php b/src/core/models/CurlModel.php index e84922af4dd32e169ab285346cef2879fb70ef79..6392ea6c725221a5c9f8bfa2d4195cfe2c15bc8d 100755 --- a/src/core/models/CurlModel.php +++ b/src/core/models/CurlModel.php @@ -22,7 +22,7 @@ class CurlModel { ValidatorModel::notEmpty($args, ['url', 'method']); ValidatorModel::stringType($args, ['url', 'method']); - ValidatorModel::arrayType($args, ['headers', 'queryParams', 'basicAuth', 'bearerAuth']); + ValidatorModel::arrayType($args, ['headers', 'queryParams', 'basicAuth', 'bearerAuth', 'options']); ValidatorModel::boolType($args, ['isXml']); $args['isXml'] = $args['isXml'] ?? false; @@ -54,6 +54,13 @@ class CurlModel } } + //Options + if (!empty($args['options'])) { + foreach ($args['options'] as $key => $option) { + $opts[$key] = $option; + } + } + //Body if (!empty($args['body'])) { $opts[CURLOPT_POSTFIELDS] = $args['body'];