Compare commits

3 Commits
3 changed files with 83 additions and 28 deletions
+12 -2
View File
@@ -37,8 +37,18 @@ try {
$stmt->execute(); $stmt->execute();
$logs = $stmt->fetchAll(PDO::FETCH_ASSOC); $logs = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Decrypt names or just return them // Decrypt names since they are encrypted in the passengers table
// (Names are not encrypted in this schema, only phones are, so we can return directly) foreach ($logs as &$log) {
if (!empty($log['first_name'])) {
$decName = $encryptionHelper->decryptData($log['first_name']);
if ($decName) $log['first_name'] = $decName;
}
if (!empty($log['last_name'])) {
$decName = $encryptionHelper->decryptData($log['last_name']);
if ($decName) $log['last_name'] = $decName;
}
}
unset($log);
// Aggregate statistics for Dashboard charts // Aggregate statistics for Dashboard charts
$sqlStats = "SELECT message_type, COUNT(*) as count $sqlStats = "SELECT message_type, COUNT(*) as count
+25 -6
View File
@@ -74,17 +74,23 @@ try {
$allPassengers = $stmtTarget->fetchAll(PDO::FETCH_ASSOC); $allPassengers = $stmtTarget->fetchAll(PDO::FETCH_ASSOC);
$targets = []; $targets = [];
$debugCounts = ['JO' => 0, 'SY' => 0, 'EG' => 0, 'IQ' => 0, 'UNKNOWN' => 0, 'DECRYPT_FAIL' => 0];
foreach ($allPassengers as $p) { foreach ($allPassengers as $p) {
$decryptedPhone = $encryptionHelper->decryptData($p['phone']); $decryptedPhone = $encryptionHelper->decryptData($p['phone']);
if (!$decryptedPhone) continue; if (!$decryptedPhone) {
$debugCounts['DECRYPT_FAIL']++;
continue;
}
$cleanPhone = preg_replace('/[^0-9]/', '', $decryptedPhone); $cleanPhone = preg_replace('/[^0-9]/', '', $decryptedPhone);
$pCountry = ''; $pCountry = 'UNKNOWN';
if (strpos($cleanPhone, '962') === 0 || strpos($cleanPhone, '07') === 0) $pCountry = 'JO'; if (strpos($cleanPhone, '962') === 0 || strpos($cleanPhone, '07') === 0) $pCountry = 'JO';
elseif (strpos($cleanPhone, '963') === 0 || (strpos($cleanPhone, '09') === 0 && strlen($cleanPhone) == 10)) $pCountry = 'SY'; elseif (strpos($cleanPhone, '963') === 0 || (strpos($cleanPhone, '09') === 0 && strlen($cleanPhone) == 10)) $pCountry = 'SY';
elseif (strpos($cleanPhone, '20') === 0 || (strpos($cleanPhone, '01') === 0 && strlen($cleanPhone) == 11)) $pCountry = 'EG'; elseif (strpos($cleanPhone, '20') === 0 || (strpos($cleanPhone, '01') === 0 && strlen($cleanPhone) == 11)) $pCountry = 'EG';
elseif (strpos($cleanPhone, '964') === 0) $pCountry = 'IQ'; elseif (strpos($cleanPhone, '964') === 0) $pCountry = 'IQ';
$debugCounts[$pCountry]++;
if ($pCountry === strtoupper($countryCode)) { if ($pCountry === strtoupper($countryCode)) {
$targets[] = ['passenger_id' => $p['passenger_id'], 'decrypted_phone' => $decryptedPhone]; $targets[] = ['passenger_id' => $p['passenger_id'], 'decrypted_phone' => $decryptedPhone];
} }
@@ -124,7 +130,10 @@ try {
$stmtToken->execute([':pid' => $passengerId]); $stmtToken->execute([':pid' => $passengerId]);
$fcmToken = $stmtToken->fetchColumn(); $fcmToken = $stmtToken->fetchColumn();
$pushSent = false;
if ($fcmToken) { if ($fcmToken) {
$decryptedToken = $encryptionHelper->decryptData($fcmToken);
if ($decryptedToken) {
// Send FCM Push Notification (Free channel - no anti-spam restriction needed) // Send FCM Push Notification (Free channel - no anti-spam restriction needed)
$fcmData = [ $fcmData = [
'type' => 'marketing_campaign', 'type' => 'marketing_campaign',
@@ -133,7 +142,7 @@ try {
]; ];
$fcmResult = sendFcmNotification( $fcmResult = sendFcmNotification(
$fcmToken, $decryptedToken,
$pushTitle, $pushTitle,
$pushBody, $pushBody,
$fcmData, $fcmData,
@@ -147,9 +156,13 @@ try {
$logStmt = $con->prepare("INSERT INTO marketing_campaigns_log (passenger_id, message_type, country_code, region_name, triggered_by) VALUES (?, 'push', ?, ?, 'autopilot')"); $logStmt = $con->prepare("INSERT INTO marketing_campaigns_log (passenger_id, message_type, country_code, region_name, triggered_by) VALUES (?, 'push', ?, ?, 'autopilot')");
$logStmt->execute([$passengerId, $countryCode, $regionName]); $logStmt->execute([$passengerId, $countryCode, $regionName]);
$dispatchedPassengers[] = $passengerId; $dispatchedPassengers[] = $passengerId;
$pushSent = true;
} }
} else { }
// Churned user (Deleted the app / No token) -> Send WhatsApp or SMS }
if (!$pushSent) {
// Fallback: Churned user (No token) OR Push failed -> Send WhatsApp or SMS
// Check anti-spam first to prevent unnecessary marketing cost // Check anti-spam first to prevent unnecessary marketing cost
if ($spamCount === 0) { if ($spamCount === 0) {
// Fetch and decrypt passenger phone number // Fetch and decrypt passenger phone number
@@ -206,7 +219,13 @@ try {
'whatsapp_sent_count' => $sentWhatsApp, 'whatsapp_sent_count' => $sentWhatsApp,
'sms_sent_count' => $sentSms 'sms_sent_count' => $sentSms
], ],
'total_dispatched' => count($dispatchedPassengers) 'total_dispatched' => count($dispatchedPassengers),
'debug_info' => [
'requested_country' => $countryCode,
'total_passengers_in_db' => count($allPassengers),
'matched_targets' => count($targets),
'distribution' => $debugCounts
]
]); ]);
} catch (Exception $e) { } catch (Exception $e) {
@@ -53,6 +53,32 @@ class EncryptionHelper
$decoded = base64_decode($cipherText, true); $decoded = base64_decode($cipherText, true);
if ($decoded === false) return false; if ($decoded === false) return false;
// محاولة أولى: استخراج IV عشوائي من أول 16 بايت (كما كان في encrypt_decrypt.php)
if (strlen($decoded) >= 16) {
$iv = substr($decoded, 0, 16);
$payload = substr($decoded, 16);
if (strlen($payload) > 0) {
$decrypted_rand = openssl_decrypt($payload, self::ALGO_CBC, $this->key, OPENSSL_RAW_DATA, $iv);
if ($decrypted_rand !== false) {
$pad = ord($decrypted_rand[strlen($decrypted_rand) - 1]);
if ($pad >= 1 && $pad <= 16) {
// Check if padding is valid
$isValidPad = true;
for ($i = 1; $i <= $pad; $i++) {
if (ord($decrypted_rand[strlen($decrypted_rand) - $i]) !== $pad) {
$isValidPad = false;
break;
}
}
if ($isValidPad) {
return substr($decrypted_rand, 0, -$pad);
}
}
}
}
}
// محاولة ثانية: IV ثابت
$decrypted = openssl_decrypt($decoded, self::ALGO_CBC, $this->key, OPENSSL_RAW_DATA, $this->cbcIv); $decrypted = openssl_decrypt($decoded, self::ALGO_CBC, $this->key, OPENSSL_RAW_DATA, $this->cbcIv);
if ($decrypted === false) return false; if ($decrypted === false) return false;