189 lines
6.7 KiB
PHP
189 lines
6.7 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../db/config.php';
|
|
require_once __DIR__ . '/../mail/MailService.php';
|
|
require_once __DIR__ . '/app.php';
|
|
|
|
class NotificationService
|
|
{
|
|
/**
|
|
* Send a notification for a specific event.
|
|
*
|
|
* @param string $eventName The event name (e.g., 'shipment_created')
|
|
* @param array $user The recipient user array (must contain 'id', 'email', 'full_name', 'role')
|
|
* @param array $data Data to replace in placeholders (e.g., ['shipment_id' => 123])
|
|
* @param string|null $lang 'en' or 'ar'. If null, sends both combined.
|
|
*/
|
|
public static function send(string $eventName, array $user, array $data = [], ?string $lang = null)
|
|
{
|
|
$pdo = db();
|
|
$stmt = $pdo->prepare("SELECT * FROM notification_templates WHERE event_name = ?");
|
|
$stmt->execute([$eventName]);
|
|
$template = $stmt->fetch();
|
|
|
|
if (!$template) {
|
|
error_log("Notification template not found: $eventName");
|
|
return;
|
|
}
|
|
|
|
// Prepare data for replacement
|
|
$placeholders = [];
|
|
$values = [];
|
|
$data['user_name'] = $user['full_name'] ?? 'User';
|
|
|
|
foreach ($data as $key => $val) {
|
|
$placeholders[] = '{' . $key . '}';
|
|
$values[] = $val;
|
|
}
|
|
|
|
// Determine Subject and Body based on Lang
|
|
$subject = '';
|
|
$body = '';
|
|
$whatsapp = '';
|
|
|
|
if ($lang === 'en') {
|
|
$subject = $template['email_subject_en'];
|
|
$body = $template['email_body_en'];
|
|
$whatsapp = $template['whatsapp_body_en'];
|
|
} elseif ($lang === 'ar') {
|
|
$subject = $template['email_subject_ar'];
|
|
$body = $template['email_body_ar'];
|
|
$whatsapp = $template['whatsapp_body_ar'];
|
|
} else {
|
|
// Combined
|
|
$subject = $template['email_subject_en'] . ' / ' . $template['email_subject_ar'];
|
|
$body = $template['email_body_en'] . "\n\n---\n\n" . $template['email_body_ar'];
|
|
$whatsapp = $template['whatsapp_body_en'] . "\n\n" . $template['whatsapp_body_ar'];
|
|
}
|
|
|
|
// Replace
|
|
$subject = str_replace($placeholders, $values, $subject);
|
|
$body = str_replace($placeholders, $values, $body);
|
|
$whatsapp = str_replace($placeholders, $values, $whatsapp);
|
|
|
|
// Send Email
|
|
if (!empty($user['email'])) {
|
|
// Convert newlines to BR for HTML
|
|
$htmlBody = nl2br(htmlspecialchars($body));
|
|
MailService::sendMail($user['email'], $subject, $htmlBody, $body);
|
|
}
|
|
|
|
// Send WhatsApp if enabled
|
|
if (get_setting('whatsapp_enabled') === '1') {
|
|
$phone = self::getPhoneNumber($user);
|
|
if ($phone) {
|
|
// Return value ignored in async/background context, but logged inside
|
|
self::sendWhatsApp($phone, $whatsapp);
|
|
} else {
|
|
error_log("WHATSAPP Notification skipped for {$user['email']}: Phone number not found.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve phone number for a user, fetching from profile if necessary.
|
|
*/
|
|
private static function getPhoneNumber(array $user): ?string
|
|
{
|
|
if (!empty($user['phone'])) {
|
|
return $user['phone'];
|
|
}
|
|
|
|
if (empty($user['id']) || empty($user['role'])) {
|
|
return null;
|
|
}
|
|
|
|
$pdo = db();
|
|
if ($user['role'] === 'shipper') {
|
|
$stmt = $pdo->prepare("SELECT phone FROM shipper_profiles WHERE user_id = ?");
|
|
$stmt->execute([$user['id']]);
|
|
return $stmt->fetchColumn() ?: null;
|
|
} elseif ($user['role'] === 'truck_owner') {
|
|
$stmt = $pdo->prepare("SELECT phone FROM truck_owner_profiles WHERE user_id = ?");
|
|
$stmt->execute([$user['id']]);
|
|
return $stmt->fetchColumn() ?: null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Send a WhatsApp message via Wablas API.
|
|
* @return array ['success' => bool, 'message' => string, 'response' => mixed]
|
|
*/
|
|
public static function sendWhatsApp(string $phone, string $message): array
|
|
{
|
|
// 1. Format Phone Number
|
|
// Remove non-numeric characters
|
|
$phone = preg_replace('/[^0-9]/', '', $phone);
|
|
|
|
// If 8 digits, prepend 968 (Oman country code)
|
|
if (strlen($phone) === 8) {
|
|
$phone = '968' . $phone;
|
|
}
|
|
|
|
// 2. Get Settings
|
|
$domain = get_setting('wablas_domain');
|
|
$token = get_setting('wablas_api_token');
|
|
|
|
if (!$domain || !$token) {
|
|
error_log("WHATSAPP Error: Wablas domain or token not configured.");
|
|
return ['success' => false, 'message' => 'Domain or Token missing'];
|
|
}
|
|
|
|
// Ensure domain has no trailing slash and correct scheme
|
|
$domain = rtrim($domain, '/');
|
|
// If domain doesn't start with http/https, prepend https://
|
|
if (!preg_match('/^https?:\/\//', $domain)) {
|
|
$domain = 'https://' . $domain;
|
|
}
|
|
|
|
// 3. Send API Request
|
|
// Endpoint: /api/send-message (StandardWablas)
|
|
$url = $domain . "/api/send-message";
|
|
|
|
$payload = json_encode([
|
|
'phone' => $phone,
|
|
'message' => $message,
|
|
]);
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
"Authorization: $token",
|
|
"Content-Type: application/json"
|
|
]);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
|
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$curlErr = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if ($curlErr) {
|
|
error_log("WHATSAPP cURL Error: $curlErr");
|
|
return ['success' => false, 'message' => "Connection error: $curlErr"];
|
|
}
|
|
|
|
$decoded = json_decode($response, true);
|
|
$statusMsg = $decoded['message'] ?? $response;
|
|
|
|
// Log result
|
|
error_log("WHATSAPP Sent to $phone. Status: $httpCode. Response: " . substr($response, 0, 100));
|
|
|
|
// Wablas usually returns {'status': true, ...} or {'status': 'pending'}
|
|
// We consider 200 OK and no explicit 'status': false as success for now
|
|
$isSuccess = ($httpCode >= 200 && $httpCode < 300);
|
|
if (isset($decoded['status']) && $decoded['status'] === false) {
|
|
$isSuccess = false;
|
|
}
|
|
|
|
return [
|
|
'success' => $isSuccess,
|
|
'message' => "API ($httpCode): " . (is_string($statusMsg) ? $statusMsg : json_encode($statusMsg)),
|
|
'response' => $decoded
|
|
];
|
|
}
|
|
} |