Connexion tocken, stripe 3D, tracking analytic
This commit is contained in:
1 parent
1deb30fcd1
commit
bd311da711
17 files changed
+3324
-455
No files matched your search
@@ -1,36 +1,37 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
|
||||
/**
|
||||
* UI helper: affiche une jolie carte centrée puis exit.
|
||||
* $type: 'error' | 'info' | 'success'
|
||||
*/
|
||||
function ui_exit(string $title, string $message, int $status = 400, string $type = 'error', ?string $cta_href = '/', ?string $cta_label = null): void {
|
||||
function ui_exit(string $title, string $message, int $status = 400, string $type = 'error', ?string $cta_href = '/', ?string $cta_label = null): void
|
||||
{
|
||||
http_response_code($status);
|
||||
$title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
|
||||
$message = nl2br(htmlspecialchars($message, ENT_QUOTES, 'UTF-8'));
|
||||
$title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
|
||||
$message = nl2br(htmlspecialchars($message, ENT_QUOTES, 'UTF-8'));
|
||||
$cta_href = $cta_href ? htmlspecialchars($cta_href, ENT_QUOTES, 'UTF-8') : null;
|
||||
$cta_label = $cta_label ?? 'OK';
|
||||
|
||||
// Styles d'icône selon le type
|
||||
// Styles d'icône selon le type
|
||||
$iconBorder = '#B91C1C'; // rouge par défaut (error)
|
||||
$iconBg = 'rgba(185,28,28,.08)';
|
||||
$iconRing = 'rgba(185,28,28,.25)';
|
||||
$checkCSS = ''; // pour success
|
||||
if ($type === 'info') {
|
||||
$iconBorder = '#1D4ED8';
|
||||
$iconBg = 'rgba(29,78,216,.08)';
|
||||
$iconRing = 'rgba(29,78,216,.25)';
|
||||
$iconBg = 'rgba(29,78,216,.08)';
|
||||
$iconRing = 'rgba(29,78,216,.25)';
|
||||
} elseif ($type === 'success') {
|
||||
$iconBorder = '#1E8050';
|
||||
$iconBg = 'rgba(30,128,80,.08)';
|
||||
$iconRing = 'rgba(30,128,80,.20)';
|
||||
$checkCSS = 'width:48px;height:36px;border:5px solid #1e8050;border-top:0;border-left:0;transform:rotate(45deg);';
|
||||
$iconBg = 'rgba(30,128,80,.08)';
|
||||
$iconRing = 'rgba(30,128,80,.20)';
|
||||
$checkCSS = 'width:48px;height:36px;border:5px solid #1e8050;border-top:0;border-left:0;transform:rotate(45deg);';
|
||||
}
|
||||
|
||||
echo '<!DOCTYPE html><html lang="fr"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">';
|
||||
echo '<title>'.$title.'</title>';
|
||||
echo '<title>' . $title . '</title>';
|
||||
echo '<style>
|
||||
html,body{height:100%;margin:0}
|
||||
body{display:flex;align-items:center;justify-content:center;background:#8CA9FF;font-family:Montserrat,system-ui,Segoe UI,Roboto,Arial}
|
||||
@@ -44,26 +45,26 @@ function ui_exit(string $title, string $message, int $status = 400, string $type
|
||||
</style></head><body><div class="card">';
|
||||
|
||||
// Icône
|
||||
echo '<div style="width:102px;height:102px;border-radius:50%;background:'.$iconBg.';border:3px solid '.$iconRing.';display:flex;align-items:center;justify-content:center;margin:0 auto 20px;">';
|
||||
echo '<div style="width:102px;height:102px;border-radius:50%;background:' . $iconBg . ';border:3px solid ' . $iconRing . ';display:flex;align-items:center;justify-content:center;margin:0 auto 20px;">';
|
||||
if ($type === 'success') {
|
||||
echo '<div style="'.$checkCSS.'"></div>';
|
||||
echo '<div style="' . $checkCSS . '"></div>';
|
||||
} elseif ($type === 'info') {
|
||||
echo '<div style="width:14px;height:48px;border-left:5px solid '.$iconBorder.';position:relative;">
|
||||
<div style="position:absolute;top:-18px;left:-5px;width:10px;height:10px;background:'.$iconBorder.';border-radius:50%;"></div>
|
||||
echo '<div style="width:14px;height:48px;border-left:5px solid ' . $iconBorder . ';position:relative;">
|
||||
<div style="position:absolute;top:-18px;left:-5px;width:10px;height:10px;background:' . $iconBorder . ';border-radius:50%;"></div>
|
||||
</div>';
|
||||
} else { // error
|
||||
echo '<div style="position:relative;width:48px;height:48px;">
|
||||
<div style="position:absolute;top:0;left:22px;width:5px;height:48px;background:'.$iconBorder.';transform:rotate(45deg);border-radius:2px;"></div>
|
||||
<div style="position:absolute;top:0;left:22px;width:5px;height:48px;background:'.$iconBorder.';transform:rotate(-45deg);border-radius:2px;"></div>
|
||||
<div style="position:absolute;top:0;left:22px;width:5px;height:48px;background:' . $iconBorder . ';transform:rotate(45deg);border-radius:2px;"></div>
|
||||
<div style="position:absolute;top:0;left:22px;width:5px;height:48px;background:' . $iconBorder . ';transform:rotate(-45deg);border-radius:2px;"></div>
|
||||
</div>';
|
||||
}
|
||||
echo '</div>';
|
||||
|
||||
echo '<h1>'.$title.'</h1>';
|
||||
echo '<p>'.$message.'</p>';
|
||||
echo '<h1>' . $title . '</h1>';
|
||||
echo '<p>' . $message . '</p>';
|
||||
|
||||
if ($cta_href) {
|
||||
echo '<div class="row"><a class="btn btn-outline" href="'.$cta_href.'">'.$cta_label.'</a></div>';
|
||||
echo '<div class="row"><a class="btn btn-outline" href="' . $cta_href . '">' . $cta_label . '</a></div>';
|
||||
}
|
||||
|
||||
echo '</div></body></html>';
|
||||
@@ -76,7 +77,7 @@ function ui_exit(string $title, string $message, int $status = 400, string $type
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
|
||||
ui_exit(
|
||||
$translations['err_acces_incorrect_titre'] ?? 'Accès incorrect',
|
||||
$translations['err_acces_incorrect_msg'] ?? "Cette page doit être appelée depuis le formulaire d'inscription.",
|
||||
$translations['err_acces_incorrect_msg'] ?? "Cette page doit être appelée depuis le formulaire d'inscription.",
|
||||
405,
|
||||
'info',
|
||||
'inscription_praticien.php',
|
||||
@@ -106,7 +107,7 @@ if ($nom === '' || $prenom === '' || $email === '' || $mdp === '') {
|
||||
}
|
||||
|
||||
// Email valide + pas d'injection d'entêtes
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL) || preg_match('/[\r\n]/', $email)) {
|
||||
if (! filter_var($email, FILTER_VALIDATE_EMAIL) || preg_match('/[\r\n]/', $email)) {
|
||||
ui_exit(
|
||||
$translations['err_titre'] ?? 'Un problème est survenu',
|
||||
$translations['err_email_non_valide'] ?? 'Email invalide.',
|
||||
@@ -128,20 +129,24 @@ if (strlen($siret) !== 14) {
|
||||
}
|
||||
|
||||
// Luhn
|
||||
function luhnCheck($num) {
|
||||
function luhnCheck($num)
|
||||
{
|
||||
$arr = str_split(strrev($num));
|
||||
$sum = 0;
|
||||
foreach ($arr as $i => $n) {
|
||||
$n = (int)$n;
|
||||
$n = (int) $n;
|
||||
if ($i % 2) {
|
||||
$n *= 2;
|
||||
if ($n > 9) $n -= 9;
|
||||
if ($n > 9) {
|
||||
$n -= 9;
|
||||
}
|
||||
|
||||
}
|
||||
$sum += $n;
|
||||
}
|
||||
return $sum % 10 === 0;
|
||||
}
|
||||
if (!luhnCheck($siret)) {
|
||||
if (! luhnCheck($siret)) {
|
||||
ui_exit(
|
||||
$translations['err_titre'] ?? 'Un problème est survenu',
|
||||
$translations['err_siret_invalide'] ?? 'Numéro SIRET invalide (échec vérification).',
|
||||
@@ -199,66 +204,89 @@ try {
|
||||
}
|
||||
|
||||
// 1) Préparer la date d'hier pour forcer l'expiration immédiate
|
||||
$hier = date('Y-m-d', strtotime('-1 day'));
|
||||
$hier = date('Y-m-d', strtotime('-1 day'));
|
||||
|
||||
// 2) Créer le praticien avec les champs d'abonnement initialisés
|
||||
$stmt = $pdo->prepare("
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO praticien (
|
||||
nom,
|
||||
prenom,
|
||||
email,
|
||||
siret,
|
||||
accepted_cgu,
|
||||
abonnement_id,
|
||||
nom,
|
||||
prenom,
|
||||
email,
|
||||
siret,
|
||||
accepted_cgu,
|
||||
abonnement_id,
|
||||
date_expiration
|
||||
) VALUES (
|
||||
:nom,
|
||||
:prenom,
|
||||
:email,
|
||||
:siret,
|
||||
:accepted_cgu,
|
||||
NULL,
|
||||
:nom,
|
||||
:prenom,
|
||||
:email,
|
||||
:siret,
|
||||
:accepted_cgu,
|
||||
NULL,
|
||||
:date_exp
|
||||
)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
'nom' => $nom,
|
||||
'prenom' => $prenom,
|
||||
'email' => $email,
|
||||
'siret' => $siret,
|
||||
'accepted_cgu' => $accept_cgu,
|
||||
'date_exp' => $hier // On met hier pour que le script de vérification dise "C'est expiré !"
|
||||
]);
|
||||
$praticien_id = (int)$pdo->lastInsertId();
|
||||
$stmt->execute([
|
||||
'nom' => $nom,
|
||||
'prenom' => $prenom,
|
||||
'email' => $email,
|
||||
'siret' => $siret,
|
||||
'accepted_cgu' => $accept_cgu,
|
||||
'date_exp' => $hier, // On met hier pour que le script de vérification dise "C'est expiré !"
|
||||
]);
|
||||
$praticien_id = (int) $pdo->lastInsertId();
|
||||
|
||||
// 2) Créer le compte
|
||||
$mot_de_passe_hash = password_hash($mdp, PASSWORD_DEFAULT);
|
||||
$token = bin2hex(random_bytes(32));
|
||||
$token_autologin = bin2hex(random_bytes(32));
|
||||
$token_autologin_expire = (new DateTime('+60 minutes'))->format('Y-m-d H:i:s');
|
||||
|
||||
$mot_de_passe_hash = password_hash($mdp, PASSWORD_DEFAULT);
|
||||
$token = bin2hex(random_bytes(32));
|
||||
$token_validation_expire = (new DateTime('+6 hours'))->format('Y-m-d H:i:s');
|
||||
$token_autologin = bin2hex(random_bytes(32));
|
||||
$token_autologin_expire = (new DateTime('+60 minutes'))->format('Y-m-d H:i:s');
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO compte (email, mot_de_passe, role, reference_id, token_validation, email_valide, token_autologin, token_autologin_expire)
|
||||
VALUES (:email, :mdp, 'praticien', :ref_id, :token, 0, :al, :al_exp)
|
||||
INSERT INTO compte (
|
||||
email,
|
||||
mot_de_passe,
|
||||
role,
|
||||
reference_id,
|
||||
token_validation,
|
||||
token_validation_expire,
|
||||
email_valide,
|
||||
token_autologin,
|
||||
token_autologin_expire
|
||||
)
|
||||
VALUES (
|
||||
:email,
|
||||
:mdp,
|
||||
'praticien',
|
||||
:ref_id,
|
||||
:token,
|
||||
:token_expire,
|
||||
0,
|
||||
:al,
|
||||
:al_exp
|
||||
)
|
||||
");
|
||||
$stmt->execute([
|
||||
'email' => $email,
|
||||
'mdp' => $mot_de_passe_hash,
|
||||
'ref_id' => $praticien_id,
|
||||
'token' => $token,
|
||||
'al' => $token_autologin,
|
||||
'al_exp' => $token_autologin_expire,
|
||||
]);
|
||||
|
||||
$stmt->execute([
|
||||
'email' => $email,
|
||||
'mdp' => $mot_de_passe_hash,
|
||||
'ref_id' => $praticien_id,
|
||||
'token' => $token,
|
||||
'token_expire' => $token_validation_expire,
|
||||
'al' => $token_autologin,
|
||||
'al_exp' => $token_autologin_expire,
|
||||
]);
|
||||
|
||||
// Commit avant envoi mail
|
||||
$pdo->commit();
|
||||
|
||||
} catch (Throwable $e) {
|
||||
if ($pdo->inTransaction()) $pdo->rollBack();
|
||||
error_log('Inscription praticien - DB error: '.$e->getMessage());
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
error_log('Inscription praticien - DB error: ' . $e->getMessage());
|
||||
ui_exit(
|
||||
$translations['err_titre'] ?? 'Un problème est survenu',
|
||||
$translations['err_serveur'] ?? 'Erreur serveur.',
|
||||
@@ -271,7 +299,7 @@ $stmt->execute([
|
||||
// =====================
|
||||
// Email de validation
|
||||
// =====================
|
||||
$validation_url = "https://uslugi.fr/validation.php?token=" . urlencode($token) . "&al=" . urlencode($token_autologin);
|
||||
$validation_url = "https://uslugi.fr/validation.php?token=" . urlencode($token) . "&al=" . urlencode($token_autologin);
|
||||
$validation_url_html = htmlspecialchars($validation_url, ENT_QUOTES, 'UTF-8');
|
||||
$prenom_nom = htmlspecialchars("$prenom $nom", ENT_QUOTES, 'UTF-8');
|
||||
|
||||
@@ -295,17 +323,17 @@ $html = "<!DOCTYPE html>
|
||||
</head>
|
||||
<body>
|
||||
<div class='mail-container'>
|
||||
<div class='title'>".sprintf($translations['mail_valid_bonjour_nom'], $prenom_nom)."</div>
|
||||
<p>".$translations['mail_valid_merci_praticien']."</p>
|
||||
<p>".$translations['mail_valid_action']."</p>
|
||||
<a href='$validation_url_html' class='btn'>".$translations['mail_valid_btn']."</a>
|
||||
<p class='link-fallback'>".$translations['mail_valid_fallback']."<br>
|
||||
<div class='title'>" . sprintf($translations['mail_valid_bonjour_nom'], $prenom_nom) . "</div>
|
||||
<p>" . $translations['mail_valid_merci_praticien'] . "</p>
|
||||
<p>" . $translations['mail_valid_action'] . "</p>
|
||||
<a href='$validation_url_html' class='btn'>" . $translations['mail_valid_btn'] . "</a>
|
||||
<p class='link-fallback'>" . $translations['mail_valid_fallback'] . "<br>
|
||||
<a href='$validation_url_html'>$validation_url_html</a>
|
||||
</p>
|
||||
<div class='footer'>
|
||||
".$translations['mail_valid_expire']."<br>
|
||||
".$translations['mail_valid_ignore']."<br><br>
|
||||
".$translations['mail_valid_signature']."
|
||||
" . $translations['mail_valid_expire'] . "<br>
|
||||
" . $translations['mail_valid_ignore'] . "<br><br>
|
||||
" . $translations['mail_valid_signature'] . "
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
@@ -313,13 +341,13 @@ $html = "<!DOCTYPE html>
|
||||
|
||||
// Texte alternative
|
||||
$text = strip_tags(
|
||||
sprintf($translations['mail_valid_bonjour_nom'], "$prenom $nom")."\n\n".
|
||||
$translations['mail_valid_merci_praticien']."\n".
|
||||
$translations['mail_valid_action']."\n".
|
||||
($translations['mail_valid_fallback'] ?? 'Si le bouton ne fonctionne pas, utilisez ce lien :')."\n".
|
||||
$validation_url."\n\n".
|
||||
$translations['mail_valid_expire']."\n".
|
||||
$translations['mail_valid_ignore']."\n".
|
||||
sprintf($translations['mail_valid_bonjour_nom'], "$prenom $nom") . "\n\n" .
|
||||
$translations['mail_valid_merci_praticien'] . "\n" .
|
||||
$translations['mail_valid_action'] . "\n" .
|
||||
($translations['mail_valid_fallback'] ?? 'Si le bouton ne fonctionne pas, utilisez ce lien :') . "\n" .
|
||||
$validation_url . "\n\n" .
|
||||
$translations['mail_valid_expire'] . "\n" .
|
||||
$translations['mail_valid_ignore'] . "\n" .
|
||||
($translations['mail_valid_signature'] ?? 'USLUGI.FR')
|
||||
);
|
||||
|
||||
@@ -334,7 +362,7 @@ list($sent, $err) = uslugi_mail(
|
||||
]
|
||||
);
|
||||
|
||||
if (!$sent) {
|
||||
if (! $sent) {
|
||||
error_log("Validation mail NOT sent to $email : $err");
|
||||
// On ne bloque pas l’utilisateur : il pourra redemander un mail.
|
||||
}
|
||||
@@ -344,7 +372,7 @@ if (!$sent) {
|
||||
// =====================
|
||||
echo '
|
||||
<!DOCTYPE html><html lang="fr"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>'.htmlspecialchars($translations['insc_merci_titre'] ?? 'Merci !', ENT_QUOTES, 'UTF-8').'</title>
|
||||
<title>' . htmlspecialchars($translations['insc_merci_titre'] ?? 'Merci !', ENT_QUOTES, 'UTF-8') . '</title>
|
||||
<style>
|
||||
html,body{height:100%;margin:0}
|
||||
body{display:flex;align-items:center;justify-content:center;background:#8CA9FF;font-family:Montserrat,system-ui,Segoe UI,Roboto,Arial}
|
||||
@@ -360,11 +388,11 @@ echo '
|
||||
<div style="width:102px;height:102px;border-radius:50%;background:rgba(30,128,80,.08);border:3px solid rgba(30,128,80,.20);display:flex;align-items:center;justify-content:center;margin:0 auto 20px;">
|
||||
<div style="width:48px;height:36px;border:5px solid #1e8050;border-top:0;border-left:0;transform:rotate(45deg);"></div>
|
||||
</div>
|
||||
<h1>'.htmlspecialchars($translations['insc_merci_titre'] ?? 'Merci !', ENT_QUOTES, 'UTF-8').'</h1>
|
||||
<p>'.htmlspecialchars($translations['insc_merci_ligne1'] ?? 'Votre compte a bien été créé.', ENT_QUOTES, 'UTF-8').'</p>
|
||||
<p>'.htmlspecialchars($translations['insc_merci_ligne2'] ?? 'Vérifiez vos emails pour valider votre adresse.', ENT_QUOTES, 'UTF-8').'</p>
|
||||
<h1>' . htmlspecialchars($translations['insc_merci_titre'] ?? 'Merci !', ENT_QUOTES, 'UTF-8') . '</h1>
|
||||
<p>' . htmlspecialchars($translations['insc_merci_ligne1'] ?? 'Votre compte a bien été créé.', ENT_QUOTES, 'UTF-8') . '</p>
|
||||
<p>' . htmlspecialchars($translations['insc_merci_ligne2'] ?? 'Vérifiez vos emails pour valider votre adresse.', ENT_QUOTES, 'UTF-8') . '</p>
|
||||
<div class="row">
|
||||
<a class="btn btn-outline" href="/">'.htmlspecialchars($translations['retour_acceuil'] ?? 'Retour à l’accueil', ENT_QUOTES, 'UTF-8').'</a>
|
||||
<a class="btn btn-outline" href="/">' . htmlspecialchars($translations['retour_acceuil'] ?? 'Retour à l’accueil', ENT_QUOTES, 'UTF-8') . '</a>
|
||||
</div>
|
||||
</div>
|
||||
</body></html>';
|
||||
Reference in new issue
Block a user