214 lines
7.8 KiB
PHP
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";
|
|
}
|
|
}
|