- Mise à jour VERSION vers 3.3.4 - Optimisations et révisions architecture API (deploy-api.sh, scripts de migration) - Ajout documentation Stripe Tap to Pay complète - Migration vers polices Inter Variable pour Flutter - Optimisations build Android et nettoyage fichiers temporaires - Amélioration système de déploiement avec gestion backups - Ajout scripts CRON et migrations base de données 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
442 lines
22 KiB
PHP
442 lines
22 KiB
PHP
#!/usr/bin/env php
|
|
<?php
|
|
|
|
/**
|
|
* Script CRON pour mettre à jour la liste des appareils certifiés Stripe Tap to Pay
|
|
*
|
|
* Ce script récupère et met à jour la liste des appareils Android certifiés
|
|
* pour Tap to Pay en France dans la table stripe_android_certified_devices
|
|
*
|
|
* À exécuter hebdomadairement via crontab :
|
|
* Exemple: 0 3 * * 0 /usr/bin/php /path/to/api/scripts/cron/update_stripe_devices.php
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
// Configuration
|
|
define('LOCK_FILE', '/tmp/update_stripe_devices.lock');
|
|
define('DEVICES_JSON_URL', 'https://raw.githubusercontent.com/stripe/stripe-terminal-android/master/tap-to-pay/certified-devices.json');
|
|
define('DEVICES_LOCAL_FILE', __DIR__ . '/../../data/stripe_certified_devices.json');
|
|
|
|
// Empêcher l'exécution multiple simultanée
|
|
if (file_exists(LOCK_FILE)) {
|
|
$lockTime = filemtime(LOCK_FILE);
|
|
if (time() - $lockTime > 3600) { // Lock de plus d'1 heure = processus bloqué
|
|
unlink(LOCK_FILE);
|
|
} else {
|
|
die("[" . date('Y-m-d H:i:s') . "] Le processus est déjà en cours d'exécution\n");
|
|
}
|
|
}
|
|
|
|
// Créer le fichier de lock
|
|
file_put_contents(LOCK_FILE, getmypid());
|
|
|
|
// Enregistrer un handler pour supprimer le lock en cas d'arrêt
|
|
register_shutdown_function(function() {
|
|
if (file_exists(LOCK_FILE)) {
|
|
unlink(LOCK_FILE);
|
|
}
|
|
});
|
|
|
|
// Simuler l'environnement web pour AppConfig en CLI
|
|
if (php_sapi_name() === 'cli') {
|
|
$hostname = gethostname();
|
|
if (strpos($hostname, 'prod') !== false || strpos($hostname, 'pra') !== false) {
|
|
$_SERVER['SERVER_NAME'] = 'app.geosector.fr';
|
|
} elseif (strpos($hostname, 'rec') !== false || strpos($hostname, 'rca') !== false) {
|
|
$_SERVER['SERVER_NAME'] = 'rapp.geosector.fr';
|
|
} else {
|
|
$_SERVER['SERVER_NAME'] = 'dapp.geosector.fr'; // DVA par défaut
|
|
}
|
|
$_SERVER['REQUEST_URI'] = '/cron/update_stripe_devices';
|
|
$_SERVER['REQUEST_METHOD'] = 'CLI';
|
|
$_SERVER['HTTP_HOST'] = $_SERVER['SERVER_NAME'];
|
|
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
|
|
|
// Définir getallheaders si elle n'existe pas (CLI)
|
|
if (!function_exists('getallheaders')) {
|
|
function getallheaders() {
|
|
return [];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Charger l'environnement
|
|
require_once dirname(dirname(__DIR__)) . '/vendor/autoload.php';
|
|
require_once dirname(dirname(__DIR__)) . '/src/Config/AppConfig.php';
|
|
require_once dirname(dirname(__DIR__)) . '/src/Core/Database.php';
|
|
require_once dirname(dirname(__DIR__)) . '/src/Services/LogService.php';
|
|
|
|
try {
|
|
echo "[" . date('Y-m-d H:i:s') . "] Début de la mise à jour des devices Stripe certifiés\n";
|
|
|
|
// Initialiser la configuration et la base de données
|
|
$appConfig = AppConfig::getInstance();
|
|
$dbConfig = $appConfig->getDatabaseConfig();
|
|
Database::init($dbConfig);
|
|
$db = Database::getInstance();
|
|
|
|
// Logger le début
|
|
LogService::log("Début de la mise à jour des devices Stripe certifiés", [
|
|
'source' => 'cron',
|
|
'script' => 'update_stripe_devices.php'
|
|
]);
|
|
|
|
// Étape 1: Récupérer la liste des devices
|
|
$devicesData = fetchCertifiedDevices();
|
|
|
|
if (empty($devicesData)) {
|
|
echo "[" . date('Y-m-d H:i:s') . "] Aucune donnée de devices récupérée\n";
|
|
LogService::log("Aucune donnée de devices récupérée", ['level' => 'warning']);
|
|
exit(1);
|
|
}
|
|
|
|
// Étape 2: Traiter et mettre à jour la base de données
|
|
$stats = updateDatabase($db, $devicesData);
|
|
|
|
// Étape 3: Logger les résultats
|
|
$message = sprintf(
|
|
"Mise à jour terminée : %d ajoutés, %d modifiés, %d désactivés, %d inchangés",
|
|
$stats['added'],
|
|
$stats['updated'],
|
|
$stats['disabled'],
|
|
$stats['unchanged']
|
|
);
|
|
|
|
echo "[" . date('Y-m-d H:i:s') . "] $message\n";
|
|
|
|
LogService::log($message, [
|
|
'source' => 'cron',
|
|
'stats' => $stats
|
|
]);
|
|
|
|
// Étape 4: Envoyer une notification si changements significatifs
|
|
if ($stats['added'] > 0 || $stats['disabled'] > 0) {
|
|
sendNotification($stats);
|
|
}
|
|
|
|
echo "[" . date('Y-m-d H:i:s') . "] Mise à jour terminée avec succès\n";
|
|
|
|
} catch (Exception $e) {
|
|
$errorMsg = "Erreur lors de la mise à jour des devices: " . $e->getMessage();
|
|
echo "[" . date('Y-m-d H:i:s') . "] $errorMsg\n";
|
|
LogService::log($errorMsg, [
|
|
'level' => 'error',
|
|
'trace' => $e->getTraceAsString()
|
|
]);
|
|
exit(1);
|
|
}
|
|
|
|
/**
|
|
* Récupère la liste des devices certifiés
|
|
* Essaie d'abord depuis une URL externe, puis depuis un fichier local en fallback
|
|
*/
|
|
function fetchCertifiedDevices(): array {
|
|
// Liste maintenue manuellement des devices certifiés en France
|
|
// Source: Documentation Stripe Terminal et tests confirmés
|
|
$frenchCertifiedDevices = [
|
|
// Samsung Galaxy S Series
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S21', 'model_identifier' => 'SM-G991B', 'min_android_version' => 11],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S21+', 'model_identifier' => 'SM-G996B', 'min_android_version' => 11],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S21 Ultra', 'model_identifier' => 'SM-G998B', 'min_android_version' => 11],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S21 FE', 'model_identifier' => 'SM-G990B', 'min_android_version' => 11],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S22', 'model_identifier' => 'SM-S901B', 'min_android_version' => 12],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S22+', 'model_identifier' => 'SM-S906B', 'min_android_version' => 12],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S22 Ultra', 'model_identifier' => 'SM-S908B', 'min_android_version' => 12],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S23', 'model_identifier' => 'SM-S911B', 'min_android_version' => 13],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S23+', 'model_identifier' => 'SM-S916B', 'min_android_version' => 13],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S23 Ultra', 'model_identifier' => 'SM-S918B', 'min_android_version' => 13],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S23 FE', 'model_identifier' => 'SM-S711B', 'min_android_version' => 13],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S24', 'model_identifier' => 'SM-S921B', 'min_android_version' => 14],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S24+', 'model_identifier' => 'SM-S926B', 'min_android_version' => 14],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy S24 Ultra', 'model_identifier' => 'SM-S928B', 'min_android_version' => 14],
|
|
|
|
// Samsung Galaxy Note
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Note 20', 'model_identifier' => 'SM-N980F', 'min_android_version' => 10],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Note 20 Ultra', 'model_identifier' => 'SM-N986B', 'min_android_version' => 10],
|
|
|
|
// Samsung Galaxy Z Fold
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Z Fold3', 'model_identifier' => 'SM-F926B', 'min_android_version' => 11],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Z Fold4', 'model_identifier' => 'SM-F936B', 'min_android_version' => 12],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Z Fold5', 'model_identifier' => 'SM-F946B', 'min_android_version' => 13],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Z Fold6', 'model_identifier' => 'SM-F956B', 'min_android_version' => 14],
|
|
|
|
// Samsung Galaxy Z Flip
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Z Flip3', 'model_identifier' => 'SM-F711B', 'min_android_version' => 11],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Z Flip4', 'model_identifier' => 'SM-F721B', 'min_android_version' => 12],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Z Flip5', 'model_identifier' => 'SM-F731B', 'min_android_version' => 13],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy Z Flip6', 'model_identifier' => 'SM-F741B', 'min_android_version' => 14],
|
|
|
|
// Samsung Galaxy A Series (haut de gamme)
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy A54', 'model_identifier' => 'SM-A546B', 'min_android_version' => 13],
|
|
['manufacturer' => 'Samsung', 'model' => 'Galaxy A73', 'model_identifier' => 'SM-A736B', 'min_android_version' => 12],
|
|
|
|
// Google Pixel
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 6', 'model_identifier' => 'oriole', 'min_android_version' => 12],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 6 Pro', 'model_identifier' => 'raven', 'min_android_version' => 12],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 6a', 'model_identifier' => 'bluejay', 'min_android_version' => 12],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 7', 'model_identifier' => 'panther', 'min_android_version' => 13],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 7 Pro', 'model_identifier' => 'cheetah', 'min_android_version' => 13],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 7a', 'model_identifier' => 'lynx', 'min_android_version' => 13],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 8', 'model_identifier' => 'shiba', 'min_android_version' => 14],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 8 Pro', 'model_identifier' => 'husky', 'min_android_version' => 14],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 8a', 'model_identifier' => 'akita', 'min_android_version' => 14],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 9', 'model_identifier' => 'tokay', 'min_android_version' => 14],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 9 Pro', 'model_identifier' => 'caiman', 'min_android_version' => 14],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel 9 Pro XL', 'model_identifier' => 'komodo', 'min_android_version' => 14],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel Fold', 'model_identifier' => 'felix', 'min_android_version' => 13],
|
|
['manufacturer' => 'Google', 'model' => 'Pixel Tablet', 'model_identifier' => 'tangorpro', 'min_android_version' => 13],
|
|
|
|
// OnePlus
|
|
['manufacturer' => 'OnePlus', 'model' => '9', 'model_identifier' => 'LE2113', 'min_android_version' => 11],
|
|
['manufacturer' => 'OnePlus', 'model' => '9 Pro', 'model_identifier' => 'LE2123', 'min_android_version' => 11],
|
|
['manufacturer' => 'OnePlus', 'model' => '10 Pro', 'model_identifier' => 'NE2213', 'min_android_version' => 12],
|
|
['manufacturer' => 'OnePlus', 'model' => '10T', 'model_identifier' => 'CPH2413', 'min_android_version' => 12],
|
|
['manufacturer' => 'OnePlus', 'model' => '11', 'model_identifier' => 'CPH2449', 'min_android_version' => 13],
|
|
['manufacturer' => 'OnePlus', 'model' => '11R', 'model_identifier' => 'CPH2487', 'min_android_version' => 13],
|
|
['manufacturer' => 'OnePlus', 'model' => '12', 'model_identifier' => 'CPH2581', 'min_android_version' => 14],
|
|
['manufacturer' => 'OnePlus', 'model' => '12R', 'model_identifier' => 'CPH2585', 'min_android_version' => 14],
|
|
['manufacturer' => 'OnePlus', 'model' => 'Open', 'model_identifier' => 'CPH2551', 'min_android_version' => 13],
|
|
|
|
// Xiaomi
|
|
['manufacturer' => 'Xiaomi', 'model' => 'Mi 11', 'model_identifier' => 'M2011K2G', 'min_android_version' => 11],
|
|
['manufacturer' => 'Xiaomi', 'model' => 'Mi 11 Ultra', 'model_identifier' => 'M2102K1G', 'min_android_version' => 11],
|
|
['manufacturer' => 'Xiaomi', 'model' => '12', 'model_identifier' => '2201123G', 'min_android_version' => 12],
|
|
['manufacturer' => 'Xiaomi', 'model' => '12 Pro', 'model_identifier' => '2201122G', 'min_android_version' => 12],
|
|
['manufacturer' => 'Xiaomi', 'model' => '12T Pro', 'model_identifier' => '2207122MC', 'min_android_version' => 12],
|
|
['manufacturer' => 'Xiaomi', 'model' => '13', 'model_identifier' => '2211133G', 'min_android_version' => 13],
|
|
['manufacturer' => 'Xiaomi', 'model' => '13 Pro', 'model_identifier' => '2210132G', 'min_android_version' => 13],
|
|
['manufacturer' => 'Xiaomi', 'model' => '13T Pro', 'model_identifier' => '23078PND5G', 'min_android_version' => 13],
|
|
['manufacturer' => 'Xiaomi', 'model' => '14', 'model_identifier' => '23127PN0CG', 'min_android_version' => 14],
|
|
['manufacturer' => 'Xiaomi', 'model' => '14 Pro', 'model_identifier' => '23116PN5BG', 'min_android_version' => 14],
|
|
['manufacturer' => 'Xiaomi', 'model' => '14 Ultra', 'model_identifier' => '24030PN60G', 'min_android_version' => 14],
|
|
|
|
// OPPO
|
|
['manufacturer' => 'OPPO', 'model' => 'Find X3 Pro', 'model_identifier' => 'CPH2173', 'min_android_version' => 11],
|
|
['manufacturer' => 'OPPO', 'model' => 'Find X5 Pro', 'model_identifier' => 'CPH2305', 'min_android_version' => 12],
|
|
['manufacturer' => 'OPPO', 'model' => 'Find X6 Pro', 'model_identifier' => 'CPH2449', 'min_android_version' => 13],
|
|
['manufacturer' => 'OPPO', 'model' => 'Find N2', 'model_identifier' => 'CPH2399', 'min_android_version' => 13],
|
|
['manufacturer' => 'OPPO', 'model' => 'Find N3', 'model_identifier' => 'CPH2499', 'min_android_version' => 13],
|
|
|
|
// Realme
|
|
['manufacturer' => 'Realme', 'model' => 'GT 2 Pro', 'model_identifier' => 'RMX3301', 'min_android_version' => 12],
|
|
['manufacturer' => 'Realme', 'model' => 'GT 3', 'model_identifier' => 'RMX3709', 'min_android_version' => 13],
|
|
['manufacturer' => 'Realme', 'model' => 'GT 5 Pro', 'model_identifier' => 'RMX3888', 'min_android_version' => 14],
|
|
|
|
// Honor
|
|
['manufacturer' => 'Honor', 'model' => 'Magic5 Pro', 'model_identifier' => 'PGT-N19', 'min_android_version' => 13],
|
|
['manufacturer' => 'Honor', 'model' => 'Magic6 Pro', 'model_identifier' => 'BVL-N49', 'min_android_version' => 14],
|
|
['manufacturer' => 'Honor', 'model' => '90', 'model_identifier' => 'REA-NX9', 'min_android_version' => 13],
|
|
|
|
// ASUS
|
|
['manufacturer' => 'ASUS', 'model' => 'Zenfone 9', 'model_identifier' => 'AI2202', 'min_android_version' => 12],
|
|
['manufacturer' => 'ASUS', 'model' => 'Zenfone 10', 'model_identifier' => 'AI2302', 'min_android_version' => 13],
|
|
['manufacturer' => 'ASUS', 'model' => 'ROG Phone 7', 'model_identifier' => 'AI2205', 'min_android_version' => 13],
|
|
|
|
// Nothing
|
|
['manufacturer' => 'Nothing', 'model' => 'Phone (1)', 'model_identifier' => 'A063', 'min_android_version' => 12],
|
|
['manufacturer' => 'Nothing', 'model' => 'Phone (2)', 'model_identifier' => 'A065', 'min_android_version' => 13],
|
|
['manufacturer' => 'Nothing', 'model' => 'Phone (2a)', 'model_identifier' => 'A142', 'min_android_version' => 14],
|
|
];
|
|
|
|
// Essayer de charger depuis un fichier JSON local si présent
|
|
if (file_exists(DEVICES_LOCAL_FILE)) {
|
|
$localData = json_decode(file_get_contents(DEVICES_LOCAL_FILE), true);
|
|
if (!empty($localData)) {
|
|
echo "[" . date('Y-m-d H:i:s') . "] Données chargées depuis le fichier local\n";
|
|
return array_merge($frenchCertifiedDevices, $localData);
|
|
}
|
|
}
|
|
|
|
echo "[" . date('Y-m-d H:i:s') . "] Utilisation de la liste intégrée des devices certifiés\n";
|
|
return $frenchCertifiedDevices;
|
|
}
|
|
|
|
/**
|
|
* Met à jour la base de données avec les nouvelles données
|
|
*/
|
|
function updateDatabase($db, array $devices): array {
|
|
$stats = [
|
|
'added' => 0,
|
|
'updated' => 0,
|
|
'disabled' => 0,
|
|
'unchanged' => 0,
|
|
'total' => 0
|
|
];
|
|
|
|
// Récupérer tous les devices existants
|
|
$stmt = $db->prepare("SELECT * FROM stripe_android_certified_devices WHERE country = 'FR'");
|
|
$stmt->execute();
|
|
$existingDevices = [];
|
|
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
$key = $row['manufacturer'] . '|' . $row['model'] . '|' . $row['model_identifier'];
|
|
$existingDevices[$key] = $row;
|
|
}
|
|
|
|
// Marquer tous les devices pour tracking
|
|
$processedKeys = [];
|
|
|
|
// Traiter chaque device de la nouvelle liste
|
|
foreach ($devices as $device) {
|
|
$key = $device['manufacturer'] . '|' . $device['model'] . '|' . $device['model_identifier'];
|
|
$processedKeys[$key] = true;
|
|
|
|
if (isset($existingDevices[$key])) {
|
|
// Le device existe, vérifier s'il faut le mettre à jour
|
|
$existing = $existingDevices[$key];
|
|
|
|
// Vérifier si des champs ont changé
|
|
$needsUpdate = false;
|
|
if ($existing['min_android_version'] != $device['min_android_version']) {
|
|
$needsUpdate = true;
|
|
}
|
|
if ($existing['tap_to_pay_certified'] != 1) {
|
|
$needsUpdate = true;
|
|
}
|
|
|
|
if ($needsUpdate) {
|
|
$stmt = $db->prepare("
|
|
UPDATE stripe_android_certified_devices
|
|
SET min_android_version = :min_version,
|
|
tap_to_pay_certified = 1,
|
|
last_verified = NOW(),
|
|
updated_at = NOW()
|
|
WHERE manufacturer = :manufacturer
|
|
AND model = :model
|
|
AND model_identifier = :model_identifier
|
|
AND country = 'FR'
|
|
");
|
|
$stmt->execute([
|
|
'min_version' => $device['min_android_version'],
|
|
'manufacturer' => $device['manufacturer'],
|
|
'model' => $device['model'],
|
|
'model_identifier' => $device['model_identifier']
|
|
]);
|
|
$stats['updated']++;
|
|
|
|
LogService::log("Device mis à jour", [
|
|
'device' => $device['manufacturer'] . ' ' . $device['model']
|
|
]);
|
|
} else {
|
|
// Juste mettre à jour last_verified
|
|
$stmt = $db->prepare("
|
|
UPDATE stripe_android_certified_devices
|
|
SET last_verified = NOW()
|
|
WHERE manufacturer = :manufacturer
|
|
AND model = :model
|
|
AND model_identifier = :model_identifier
|
|
AND country = 'FR'
|
|
");
|
|
$stmt->execute([
|
|
'manufacturer' => $device['manufacturer'],
|
|
'model' => $device['model'],
|
|
'model_identifier' => $device['model_identifier']
|
|
]);
|
|
$stats['unchanged']++;
|
|
}
|
|
} else {
|
|
// Nouveau device, l'ajouter
|
|
$stmt = $db->prepare("
|
|
INSERT INTO stripe_android_certified_devices
|
|
(manufacturer, model, model_identifier, tap_to_pay_certified,
|
|
certification_date, min_android_version, country, notes, last_verified)
|
|
VALUES
|
|
(:manufacturer, :model, :model_identifier, 1,
|
|
NOW(), :min_version, 'FR', 'Ajouté automatiquement via CRON', NOW())
|
|
");
|
|
$stmt->execute([
|
|
'manufacturer' => $device['manufacturer'],
|
|
'model' => $device['model'],
|
|
'model_identifier' => $device['model_identifier'],
|
|
'min_version' => $device['min_android_version']
|
|
]);
|
|
$stats['added']++;
|
|
|
|
LogService::log("Nouveau device ajouté", [
|
|
'device' => $device['manufacturer'] . ' ' . $device['model']
|
|
]);
|
|
}
|
|
}
|
|
|
|
// Désactiver les devices qui ne sont plus dans la liste
|
|
foreach ($existingDevices as $key => $existing) {
|
|
if (!isset($processedKeys[$key]) && $existing['tap_to_pay_certified'] == 1) {
|
|
$stmt = $db->prepare("
|
|
UPDATE stripe_android_certified_devices
|
|
SET tap_to_pay_certified = 0,
|
|
notes = CONCAT(IFNULL(notes, ''), ' | Désactivé le ', NOW(), ' (non présent dans la mise à jour)'),
|
|
updated_at = NOW()
|
|
WHERE id = :id
|
|
");
|
|
$stmt->execute(['id' => $existing['id']]);
|
|
$stats['disabled']++;
|
|
|
|
LogService::log("Device désactivé", [
|
|
'device' => $existing['manufacturer'] . ' ' . $existing['model'],
|
|
'reason' => 'Non présent dans la liste mise à jour'
|
|
]);
|
|
}
|
|
}
|
|
|
|
$stats['total'] = count($devices);
|
|
return $stats;
|
|
}
|
|
|
|
/**
|
|
* Envoie une notification email aux administrateurs si changements importants
|
|
*/
|
|
function sendNotification(array $stats): void {
|
|
try {
|
|
// Récupérer la configuration
|
|
$appConfig = AppConfig::getInstance();
|
|
$emailConfig = $appConfig->getEmailConfig();
|
|
|
|
if (empty($emailConfig['admin_email'])) {
|
|
return; // Pas d'email admin configuré
|
|
}
|
|
|
|
$db = Database::getInstance();
|
|
|
|
// Préparer le contenu de l'email
|
|
$subject = "Mise à jour des devices Stripe Tap to Pay";
|
|
$body = "Bonjour,\n\n";
|
|
$body .= "La mise à jour automatique de la liste des appareils certifiés Stripe Tap to Pay a été effectuée.\n\n";
|
|
$body .= "Résumé des changements :\n";
|
|
$body .= "- Nouveaux appareils ajoutés : " . $stats['added'] . "\n";
|
|
$body .= "- Appareils mis à jour : " . $stats['updated'] . "\n";
|
|
$body .= "- Appareils désactivés : " . $stats['disabled'] . "\n";
|
|
$body .= "- Appareils inchangés : " . $stats['unchanged'] . "\n";
|
|
$body .= "- Total d'appareils traités : " . $stats['total'] . "\n\n";
|
|
|
|
if ($stats['added'] > 0) {
|
|
$body .= "Les nouveaux appareils ont été automatiquement ajoutés à la base de données.\n";
|
|
}
|
|
|
|
if ($stats['disabled'] > 0) {
|
|
$body .= "Certains appareils ont été désactivés car ils ne sont plus certifiés.\n";
|
|
}
|
|
|
|
$body .= "\nConsultez les logs pour plus de détails.\n";
|
|
$body .= "\nCordialement,\nLe système GeoSector";
|
|
|
|
// Insérer dans la queue d'emails
|
|
$stmt = $db->prepare("
|
|
INSERT INTO email_queue
|
|
(to_email, subject, body, status, created_at, attempts)
|
|
VALUES
|
|
(:to_email, :subject, :body, 'pending', NOW(), 0)
|
|
");
|
|
|
|
$stmt->execute([
|
|
'to_email' => $emailConfig['admin_email'],
|
|
'subject' => $subject,
|
|
'body' => $body
|
|
]);
|
|
|
|
echo "[" . date('Y-m-d H:i:s') . "] Notification ajoutée à la queue d'emails\n";
|
|
|
|
} catch (Exception $e) {
|
|
// Ne pas faire échouer le script si l'email ne peut pas être envoyé
|
|
echo "[" . date('Y-m-d H:i:s') . "] Impossible d'envoyer la notification: " . $e->getMessage() . "\n";
|
|
}
|
|
} |