File: /var/www/vhost/disk-apps/teamdemo.sports-crowd.com/app/Core/ZapSign/Application/ZapSignService.php
<?php
declare(strict_types=1);
namespace App\Core\ZapSign\Application;
use App\Core\ZapSign\DocumentStatusEnum;
use App\Core\ZapSign\DocumentTypesEnum;
use App\DocumentAnalytic;
use App\Services\AcademyDocumentService;
use App\Services\AcademyService;
use Illuminate\Http\Request;
use App\Http\Controllers\UtilController;
use App\IntegrationProvider;
use Illuminate\Support\Facades\DB;
class ZapSignService
{
private $academyDocumentService;
private $academyService;
private $utilController;
public function __construct()
{
$this->academyDocumentService = new AcademyDocumentService;
$this->academyService = new AcademyService;
$this->utilController = new UtilController;
}
public function autocomplete(Request $request)
{
if ($link = $this->academyDocumentService->validateDocumentStatus($request)) {
if ($link['r'] && str_contains($link['d'], 'zapsign')) {
return $link;
}
}
$validProviderData = $this->validateProviderData();
if (!$validProviderData['r']) {
return $validProviderData;
}
$providerData = $validProviderData['providerData'];
$data = $this->mapDataDocument($request);
$this->utilController->logFile(json_encode($data), 'zapsign');
$document = $this->createDocument($data, $providerData);
if (!$document['r']) {
return $document;
}
$this->registerDocumentAnalitics($document['data']);
$response = $this->mapResponse($request, $document['data']);
return $response;
}
public function webhooksListener(Request $request)
{
header('Content-Type: application/json');
$this->utilController->logFile($request, 'zapsign');
$content = json_decode($request->getContent(), true);
if (!$content) {
return array('r' => false, 'm' => __('messages.error_updating'));
}
$answers = $this->findValueByKey($content, 'answers');
$webhook = $this->findValueByValueKey($answers, 'webhook');
if ($webhook) {
if (!str_contains($webhook, $request->getSchemeAndHttpHost())) {
$this->resendWebhook($webhook, $request);
return;
}
}
$user = $this->findValueByValueKey($answers, 'academyUserId');
$document = $this->findValueByValueKey($answers, 'documentId');
$signed_file = $this->findValueByKey($content, 'signed_file');
if (!$user || !$document || !$signed_file) {
return array('r' => false, 'm' => __('messages.error_updating'));
}
$parameters = new \stdClass();
$parameters->user = $user;
$parameters->document = $document;
$parameters->file = $this->convertUrltoBase64($signed_file);
$parameters->extension = $this->convertUrltoExtension($signed_file);
$response = $this->academyDocumentService->uploadUserAcademyDocumentExternal($parameters);
$file = $response['r'] ? $response['data']['link'] : $signed_file;
$this->updateDocumentAnalitics($content, $file);
return $response;
}
public function documentAnalytics(Request $request)
{
$data = $this->mapDocumentAnalytics($request);
return view('document_analytics.report', compact('data'));
}
private function validateProviderData()
{
$providerData = $this->providerData();
if (!$providerData) {
return array("r" => false, "m" => __('messages.integrations.provider_not_found'));
} else if (!$providerData->active) {
return array("r" => false, "m" => __('messages.integrations.provider_not_active'));
}
return array("r" => true, "m" => __('messages.integrations.validate_data_successfully'), 'providerData' => $providerData);
}
private function providerData()
{
return IntegrationProvider::where('alias', 'zapsign')->where('active', 1)->first();
}
private function resendWebhook($webhook, $request)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $webhook);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request->getContent());
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
}
private function mapDataDocument($request)
{
$templateId = $this->academyDocumentService->getExternalFormId($request->get('documentId'));
$params = $this->encryptParamsData($request);
$academyUser = $this->academyService->find($request->get('academyUserId'));
$signerName = $academyUser ? $academyUser->advisor_name . ' ' . $academyUser->advisor_last_name : 'ZapSign';
$signerEmail = $academyUser ? $academyUser->advisor_mail : '';
$data = [
"template_id" => $templateId,
"signer_name" => $signerName,
"signer_email" => $signerEmail,
"send_automatic_email" => false,
"send_automatic_whatsapp" => false,
"lang" => "en-us",
"external_id" => null,
"signer_has_incomplete_fields" => true,
"data" => $params
];
return $data;
}
private function encryptParamsData($request)
{
$data = [];
$data[] = [
'de' => 'webhook',
'para' => $request->getSchemeAndHttpHost() . '/api/zapsign/webhooksListener'
];
$data[] = [
'de' => 'academyUserId',
'para' => $request->get('academyUserId') . ''
];
$data[] = [
'de' => 'documentId',
'para' => $request->get('documentId') . ''
];
$dataAcademy = $this->academyService->mapDataAcademy($request->get('academyUserId'));
$data = array_merge($data, $dataAcademy);
return $data;
}
private function createDocument($data, $providerData)
{
try {
$client = new \GuzzleHttp\Client();
$response = $client->post($providerData->endpoint . "/api/v1/models/create-doc/", [
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $providerData->password
],
'body' => json_encode($data),
]);
$body = $response->getBody()->getContents();
$body = json_decode($body, true);
return array("r" => true, "m" => __('messages.academy_document.document_uploaded_successfully'), "data" => $body);
} catch (\Exception $e) {
return array("r" => false, "m" => $e->getMessage());
}
}
private function registerDocumentAnalitics($data)
{
$token = $this->findValueByKey($data, 'token');
$name = $this->findValueByKey($data, 'name');
if ($token) {
DocumentAnalytic::updateOrCreate(
['token' => $token],
[
'token' => $token,
'name' => $name,
'status' => DocumentStatusEnum::PENDING,
'type' => DocumentTypesEnum::SIGNATURE
]
);
}
}
private function updateDocumentAnalitics($data, $file)
{
$token = $this->findValueByKey($data, 'token');
if ($token) {
DocumentAnalytic::updateOrCreate(
['token' => $token],
[
'token' => $token,
'status' => DocumentStatusEnum::SIGNED,
'file' => $file
]
);
}
}
private function mapResponse($request, $data)
{
$link = $this->findValueByKey($data, 'sign_url');
if ($link) {
$this->academyDocumentService->updateDocumentLink($request, $link);
return array("r" => true, "m" => __('messages.academy_document.sign_url_found_successfully'), "d" => $link);
} else {
return array("r" => false, "m" => __('messages.academy_document.sign_url_not_found'));
}
}
private function findValueByKey($jsonObject, $searchKey)
{
if (array_key_exists($searchKey, $jsonObject)) {
return $jsonObject[$searchKey];
}
foreach ($jsonObject as $key => $value) {
if (is_array($value)) {
$result = $this->findValueByKey($value, $searchKey);
if ($result !== null) {
return $result;
}
}
}
return null;
}
private function findValueByValueKey($data, $key)
{
$value;
foreach ($data as $item) {
if ($item['variable'] == $key) {
$value = $item['value'];
}
}
return $value;
}
private function convertUrltoBase64($url)
{
return chunk_split(base64_encode(file_get_contents($url)));
}
private function convertUrltoExtension($url)
{
return pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION);
}
private function mapDocumentAnalytics()
{
$data = DocumentAnalytic::select(
'name',
DB::raw('COUNT(*) AS created'),
DB::raw('COUNT(CASE WHEN status = "signed" THEN 1 END) AS signed'),
DB::raw('COUNT(CASE WHEN status = "pending" THEN 1 END) AS pending'),
DB::raw('COUNT(CASE WHEN status = "rejected" THEN 1 END) AS rejected'),
DB::raw('ROUND((COUNT(CASE WHEN status = "signed" THEN 1 END) / COUNT(*)) * 100) AS efficiency'),
)
->groupBy('name')
->get();
return $data;
}
}