Files
kupshop/bundles/KupShop/AgeVerifyBundle/Utils/VerifaceUtil.php
2025-08-02 16:30:27 +02:00

214 lines
7.8 KiB
PHP

<?php
declare(strict_types=1);
namespace KupShop\AgeVerifyBundle\Utils;
use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\AgeVerifyBundle\Exception\VeriFaceException;
use KupShop\GraphQLBundle\EventListener\JsShopRefreshListener;
use KupShop\KupShopBundle\Context\DomainContext;
use KupShop\KupShopBundle\Context\UserContext;
use Query\Operator;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Contracts\Service\Attribute\Required;
use veriface\Dto\IndicatorDto;
use veriface\VeriFace;
class VerifaceUtil
{
protected ?VeriFace $veriFace = null;
#[Required]
public AgeVerifyUtil $ageVerifyUtil;
#[Required]
public DomainContext $domainContext;
#[Required]
public UserContext $userContext;
#[Required]
public SessionInterface $session;
public const MESSAGE = 'Veriface - Ověření plnoletosti se nezdařilo.';
public function __construct()
{
$dbcfg = \Settings::getDefault();
$apiKey = $dbcfg['age_verify']['veriface']['api_key'] ?? false;
if ($apiKey) {
$this->veriFace = VeriFace::byApiKey($apiKey);
}
}
protected function getMessage()
{
if ($user = $this->userContext->getActive()) {
return self::MESSAGE.': '.$user->email;
}
return self::MESSAGE;
}
public function getRedirectUrl(): string
{
$this->checkVeriface();
if (!($email = $this->userContext->getActive()?->email)) {
$data = $this->session->get('verifaceData');
$email = $data['email'] ?? '';
}
$verification = $this->veriFace->createVerification(type: 'LINK_LONG', referenceId: $email);
return 'https://app.veriface.eu/?oc='.$verification->openCode.'&redirectUri='.$this->getRedirectUri();
}
public function saveData($sessionId, $user = null): bool
{
$this->checkVeriface();
$verification = $this->veriFace->getVerification($sessionId);
if ($verification === null) {
$this->ageVerifyUtil->addErrorMessage('Ověření plnoletosti se nezdařilo.');
addActivityLog(ActivityLog::SEVERITY_WARNING,
ActivityLog::TYPE_COMMUNICATION,
$this->getMessage(),
['message' => 'Nepodařilo se získat data z Veriface.', 'sessionId' => $sessionId]);
return false;
}
// Pro zalogování
$status = [
'verifaceStatus' => $verification->status,
'endUserStatus' => $verification->verificationEndUserStatus ?? '',
'sessionId' => $sessionId,
'documentStatus' => $verification->documentStatus,
'selfieStatus' => $verification->selfieStatus,
'livenessCheckStatus' => $verification->livenessCheckStatus,
'extractedData' => json_encode($verification->extractedData),
];
// Uložení průběhu v čitelnější formě
foreach ($verification->indicators as $key => $indicator) {
$status["indicator_{$key}"] = json_encode($indicator);
}
// Ověření chcíplo na straně uživatele
if ($verification->verificationEndUserStatus != 'SUCCESS') {
$this->ageVerifyUtil->addErrorMessage('Ověření plnoletosti se nezdařilo.');
$status['message'] = 'Chyba v procesu ověření.';
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_COMMUNICATION, $this->getMessage(), $status);
return false;
}
$verifaceName = $verification->name;
if ($verifaceName) {
$nameParts = explode(' ', $verifaceName);
$firstname = reset($nameParts);
$surname = end($nameParts);
if (str_contains($firstname, '/')) {
$firstname = explode('/', $firstname)[1];
}
if (str_contains($surname, '/')) {
$surname = explode('/', $surname)[1];
}
$verifaceName = "{$firstname} {$surname}";
}
$age = array_filter($verification->indicators, function ($dto) {
return $dto->code == 'document_age.age' && $dto->status == 'OK';
});
if (empty($age)) {
$this->ageVerifyUtil->addErrorMessage('Ověření plnoletosti se nezdařilo.');
$status['message'] = 'Nepodařilo se získat věk.';
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_COMMUNICATION, $this->getMessage(), $status);
return false;
}
/** @var IndicatorDto $age */
$age = reset($age);
// Registrace z košíku
if ($data = $this->session->get('verifaceData')) {
/** @var \User $user */
$user = sqlGetConnection()->transactional(function () use ($data) {
$idUser = addUserEmail(email: $data['email'], fields: ['figure' => 'Y', 'phone' => $data['phone']]);
return \User::createFromId($idUser);
});
$user->login(getUserKey());
$user->updatePassword($data['password']);
$this->session->remove('verifaceData');
if (findModule(\Modules::JS_SHOP)) {
$this->session->set(JsShopRefreshListener::SESSION_NAME, true);
}
if ($firstname && $surname) {
sqlQueryBuilder()->update('users')
->directValues([
'name' => ucfirst(mb_strtolower($firstname)),
'surname' => ucfirst(mb_strtolower($surname)),
])
->where(Operator::equals(['id' => $user->id]))
->execute();
}
} else {
// Když si nepošlu usera ze shora (webhook) tak zkusím přihlášeného
if (!$user) {
$user = $this->userContext->getActive();
}
if ($user) {
$transliterator = \Transliterator::createFromRules(':: Any-Latin; :: Latin-ASCII; :: NFD; :: [:Nonspacing Mark:] Remove; :: Lower(); :: NFC;',
\Transliterator::FORWARD);
$eshopName = "{$user->name} {$user->surname}";
similar_text($transliterator->transliterate($eshopName), $transliterator->transliterate($verifaceName), $percent);
if ($percent < 80) {
$this->ageVerifyUtil->addErrorMessage('Ověření plnoletosti se nezdařilo: jméno a přijmení se neshoduje s údaji v e-shopu.');
$status['message'] = 'Jméno a příjmení v eshopu se neshoduje s údaji z dokladu.';
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_COMMUNICATION, $this->getMessage(), $status);
return false;
}
} else {
$this->ageVerifyUtil->addErrorMessage('Ověření plnoletosti se nezdařilo.');
$status['message'] = 'Není přihlašený uživatel.';
addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_COMMUNICATION, $this->getMessage(), $status);
return false;
}
}
// Plnoletý = 18+ a validní status
$this->ageVerifyUtil->setVerificationData($age->params >= 18 && in_array($verification->status,
['VERIFIED', 'VERIFIED_WARNING', 'VERIFIED_MANUAL']) ? 'Y' : 'N',
'veriface',
\DateTime::createFromFormat('d.m.Y', $verification->birthDate)->format('Y-m-d'),
$user->id);
return true;
}
protected function checkVeriface(): void
{
if ($this->veriFace === null) {
throw new VeriFaceException('Veriface není inicializován. Je vyplněný API klíč?');
}
}
protected function getRedirectUri()
{
return "{$this->domainContext->getActiveWithScheme()}/_veriface";
}
}