Newer
Older
<?php
/**
* Copyright Maarch since 2008 under license.
* See LICENSE.txt file at the root folder for more details.
* This file is part of Maarch software.
*
*/
/**
* @brief Yousign Controller
* @author dev@maarch.org
*/
namespace Workflow\controllers;
use Attachment\controllers\AttachmentController;
use Attachment\models\AttachmentModel;
use Docserver\controllers\DocserverController;
use Docserver\models\AdrModel;
use Document\controllers\DocumentController;
use ExternalSignatoryBook\models\ExternalSignatoryBookModel;
use Slim\Http\Request;
use Slim\Http\Response;
use SrcCore\controllers\UrlController;
use SrcCore\models\CoreConfigModel;
use SrcCore\models\ValidatorModel;
use Workflow\models\WorkflowExternalInformationModel;
use Workflow\models\WorkflowModel;
class YousignController
{
public static function createProcedure(array $args)
{
$workflowExternalInformations = WorkflowExternalInformationModel::getByWorkflowId(['select' => ['*'], 'workflowId' => $args['workflowId']]);
if (empty($workflowExternalInformations)) {
return ['errors' => 'No external informations found'];
}
$externalSB = ExternalSignatoryBookModel::getById(['select' => ['*'], 'id' => $workflowExternalInformations['external_signatory_book_id']]);
if (empty($externalSB)) {
return ['errors' => 'No external signatory book configuration found'];
} elseif ($externalSB['type'] != 'yousign') {
return ['errors' => 'External signatory book configuration is invalid'];
}
$externalSB['connection_data'] = json_decode($externalSB['connection_data'], true);
$workflowExternalInformations['informations'] = json_decode($workflowExternalInformations['informations'], true);
'url' => "{$externalSB['connection_data']['apiUri']}/files",
'bearerAuth' => ['token' => $externalSB['connection_data']['apiKey']],
'method' => 'POST',
'headers' => ['content-type:application/json'],
'body' => json_encode([
'name' => "{$args['name']}.pdf",
'content' => $args['encodedDocument']
])
]);
if ($fileResponse['code'] != 201) {
return ['errors' => json_encode($fileResponse['response'])];
}
$fileId = $fileResponse['response']['id'];
$trunkedFileId = str_replace('/files/', '', $fileId);
$procedureResponse = CurlModel::exec([
'url' => "{$externalSB['connection_data']['apiUri']}/procedures",
'bearerAuth' => ['token' => $externalSB['connection_data']['apiKey']],
'method' => 'POST',
'headers' => ['content-type:application/json'],
'body' => json_encode([
'name' => $args['name'],
'description' => $args['description'],
'members' => [
[
'firstname' => $workflowExternalInformations['firstname'],
'lastname' => $workflowExternalInformations['lastname'],
'email' => $workflowExternalInformations['email'],
'phone' => $workflowExternalInformations['phone'],
'operationLevel' => 'custom',
'operationCustomModes' => [$workflowExternalInformations['informations']['security']],
'type' => $workflowExternalInformations['role'] == 'visa' ? 'validator' : 'signer',
'fileObjects' => [
[
'file' => $fileId,
'page' => 1,
'position' => $args['position']
]
]
]
],
'config' => [
'email' => [
'member.started' => [
[
"subject" => "Hey! You are invited to sign!",
"message" => "Hello <tag data-tag-type=\"string\" data-tag-name=\"recipient.firstname\"></tag> <tag data-tag-type=\"string\" data-tag-name=\"recipient.lastname\"></tag>, <br><br> You have ben invited to sign a document, please click on the following button to read it: <tag data-tag-type=\"button\" data-tag-name=\"url\" data-tag-title=\"Access to documents\">Access to documents</tag>",
"to" => ["@member"]
]
]
],
'webhook' => [
'procedure.finished' => [
[
'url' => UrlController::getCoreUrl() . "rest/documents/{$args['documentId']}/workflows/{$args['workflowId']}/files/{$trunkedFileId}",
'method' => 'GET',
]
],
'procedure.refused' => [
[
'url' => UrlController::getCoreUrl() . "rest/documents/{$args['documentId']}/workflows/{$args['workflowId']}/files/{$trunkedFileId}",
'method' => 'GET',
]
]
]
]
])
]);
if ($procedureResponse['code'] != 201) {
return ['errors' => json_encode($procedureResponse['response'])];
}
$attachments = AttachmentModel::getByDocumentId(['select' => ['id', 'title'], 'documentId' => $args['documentId']]);
foreach ($attachments as $attachment) {
$content = AttachmentController::getContentPath(['id' => $attachment['id']]);
$content = file_get_contents($content['path']);
$fileResponse = CurlModel::exec([
'url' => "{$externalSB['connection_data']['apiUri']}/files",
'bearerAuth' => ['token' => $externalSB['connection_data']['apiKey']],
'method' => 'POST',
'headers' => ['content-type:application/json'],
'body' => json_encode([
'name' => "{$attachment['title']}.pdf",
'content' => base64_encode($content),
'procedure' => $procedureResponse['response']['id'],
'type' => 'attachment'
])
]);
if ($fileResponse['code'] != 201) {
return ['errors' => json_encode($fileResponse['response'])];
}
$workflowExternalInformations['informations']['yousignFileId'] = $fileId;
$workflowExternalInformations['informations']['yousignProcedureId'] = $procedureResponse['response']['id'];
$informations = json_encode($workflowExternalInformations['informations']);
WorkflowExternalInformationModel::update(['set' => ['informations' => $informations], 'where' => ['workflow_id = ?'], 'data' => [$args['workflowId']]]);
return true;
}
public function getByFileId(Request $request, Response $response, array $args)
{
$workflow = WorkflowModel::get([
'select' => [1],
'where' => ['main_document_id = ?', 'id = ?', 'status is null'],
'data' => [$args['id'], $args['workflowId']]
]);
if (empty($workflow[0])) {
return $response->withStatus(403)->withJson(['errors' => 'Workflow does not exist']);
}
$workflowExternalInformations = WorkflowExternalInformationModel::getByWorkflowId(['select' => ['informations', 'external_signatory_book_id'], 'workflowId' => $args['workflowId']]);
if (empty($workflowExternalInformations)) {
return $response->withStatus(403)->withJson(['errors' => 'Workflow does not exist']);
}
$informations = json_decode($workflowExternalInformations['informations'], true);
if ($informations['yousignFileId'] != "/files/{$args['fileId']}") {
return $response->withStatus(403)->withJson(['errors' => 'Unauthorized fileId']);
}
$externalSB = ExternalSignatoryBookModel::getById(['select' => ['*'], 'id' => $workflowExternalInformations['external_signatory_book_id']]);
if (empty($externalSB)) {
return $response->withStatus(400)->withJson(['errors' => 'No external signatory book configuration found']);
} elseif ($externalSB['type'] != 'yousign') {
return $response->withStatus(400)->withJson(['errors' => 'External signatory book configuration is invalid']);
}
$externalSB['connection_data'] = json_decode($externalSB['connection_data'], true);
$trunkedProcedureId = str_replace('/procedures/', '', $informations['yousignProcedureId']);
$procedureResponse = CurlModel::exec([
'url' => "{$externalSB['connection_data']['apiUri']}/procedures/{$trunkedProcedureId}",
'bearerAuth' => ['token' => $externalSB['connection_data']['apiKey']],
'method' => 'GET',
'headers' => ['content-type:application/json']
]);
if ($procedureResponse['code'] != 200) {
return ['errors' => json_encode($procedureResponse['response'])];
if (!in_array($procedureResponse['response']['status'], ['finished', 'refused'])) {
return $response->withStatus(403)->withJson(['errors' => 'Procedure is not finished']);
if ($procedureResponse['response']['status'] == 'finished') {
$fileResponse = CurlModel::exec([
'url' => "{$externalSB['connection_data']['apiUri']}/files/{$args['fileId']}/download",
'bearerAuth' => ['token' => $externalSB['connection_data']['apiKey']],
'method' => 'GET',
'headers' => ['content-type:application/json']
]);
if ($fileResponse['code'] != 200) {
return $response->withStatus(400)->withJson(['errors' => json_encode($fileResponse['response'])]);
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
}
$storeInfos = DocserverController::storeResourceOnDocServer([
'encodedFile' => $fileResponse['response'],
'format' => 'pdf',
'docserverType' => 'DOC'
]);
if (!empty($storeInfos['errors'])) {
return $response->withStatus(500)->withJson(['errors' => $storeInfos['errors']]);
}
AdrModel::deleteDocumentAdr([
'where' => ['main_document_id = ?', 'type = ?'],
'data' => [$args['id'], 'DOC']
]);
AdrModel::createDocumentAdr([
'documentId' => $args['id'],
'type' => 'DOC',
'path' => $storeInfos['path'],
'filename' => $storeInfos['filename'],
'fingerprint' => $storeInfos['fingerprint']
]);
$storeInfos = DocserverController::storeResourceOnDocServer([
'encodedFile' => $fileResponse['response'],
'format' => 'pdf',
'docserverType' => 'ESIGN'
]);
if (!empty($storeInfos['errors'])) {
return $response->withStatus(500)->withJson(['errors' => $storeInfos['errors']]);
}
AdrModel::deleteDocumentAdr([
'where' => ['main_document_id = ?', 'type = ?'],
'data' => [$args['id'], 'ESIGN']
]);
AdrModel::createDocumentAdr([
'documentId' => $args['id'],
'type' => 'ESIGN',
'path' => $storeInfos['path'],
'filename' => $storeInfos['filename'],
'fingerprint' => $storeInfos['fingerprint']
]);
AdrModel::deleteDocumentAdr([
'where' => ['main_document_id = ?', 'type like ?'],
'data' => [$args['id'], 'TNL%']
]);
$configPath = CoreConfigModel::getConfigPath();
exec("php src/app/convert/scripts/ThumbnailScript.php '{$configPath}' {$args['id']} 'document' 0 > /dev/null &");
}
$GLOBALS['webhook'] = 'yousign webhook';
$GLOBALS['id'] = 0;
DocumentController::endAction([
'id' => $args['id'],
'workflowId' => $args['workflowId'],
'status' => $procedureResponse['response']['status'] == 'finished' ? 'VAL' : 'REF',
'note' => $procedureResponse['response']['members'][0]['comment'] ?? null
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
public static function deleteProcedureByWorkflowId(array $args)
{
$workflowExternalInformations = WorkflowExternalInformationModel::getByWorkflowId(['select' => ['informations', 'external_signatory_book_id'], 'workflowId' => $args['workflowId']]);
if (empty($workflowExternalInformations)) {
return ['errors' => 'Workflow does not exist'];
}
$informations = json_decode($workflowExternalInformations['informations'], true);
$externalSB = ExternalSignatoryBookModel::getById(['select' => ['*'], 'id' => $workflowExternalInformations['external_signatory_book_id']]);
if (empty($externalSB)) {
return ['errors' => 'No external signatory book configuration found'];
} elseif ($externalSB['type'] != 'yousign') {
return ['errors' => 'External signatory book configuration is invalid'];
}
$externalSB['connection_data'] = json_decode($externalSB['connection_data'], true);
$trunkedProcedureId = str_replace('/procedures/', '', $informations['yousignProcedureId']);
$procedureResponse = CurlModel::exec([
'url' => "{$externalSB['connection_data']['apiUri']}/procedures/{$trunkedProcedureId}",
'bearerAuth' => ['token' => $externalSB['connection_data']['apiKey']],
'method' => 'DELETE'
]);
if ($procedureResponse['code'] != 204) {
return ['errors' => json_encode($procedureResponse['response'])];
}
return true;
}
public static function formatExternalInformations(array $args)
{
ValidatorModel::stringType($args, ['security']);
$informations = [
'type' => 'yousign',
'security' => 'sms',
'role' => 'sign'
];
if (!empty($args['security']) && $args['security'] == 'email') {
$informations['security'] = 'email';
}
if (!empty($args['role']) && $args['role'] == 'visa') {
$informations['role'] = 'visa';
}
return $informations;
}