change whatsapp setting

This commit is contained in:
Flatlogic Bot 2026-03-13 13:31:02 +00:00
parent a3d27b0ee3
commit 3f3ac7d889
2 changed files with 189 additions and 29 deletions

View File

@ -2,37 +2,65 @@
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
require_once __DIR__ . '/includes/NotificationService.php';
ensure_schema();
$errors = [];
$success = '';
$testSuccess = '';
$testError = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$updates = [
'thawani_publishable_key' => trim($_POST['thawani_publishable_key'] ?? ''),
'thawani_secret_key' => trim($_POST['thawani_secret_key'] ?? ''),
'thawani_environment' => trim($_POST['thawani_environment'] ?? 'test'),
'wablas_domain' => trim($_POST['wablas_domain'] ?? ''),
'wablas_api_token' => trim($_POST['wablas_api_token'] ?? ''),
'wablas_secret_key' => trim($_POST['wablas_secret_key'] ?? ''),
'whatsapp_enabled' => isset($_POST['whatsapp_enabled']) ? '1' : '0',
'smtp_host' => trim($_POST['smtp_host'] ?? ''),
'smtp_port' => trim($_POST['smtp_port'] ?? ''),
'smtp_secure' => trim($_POST['smtp_secure'] ?? ''),
'smtp_user' => trim($_POST['smtp_user'] ?? ''),
'smtp_pass' => trim($_POST['smtp_pass'] ?? ''),
'mail_from' => trim($_POST['mail_from'] ?? ''),
'mail_from_name' => trim($_POST['mail_from_name'] ?? ''),
];
if (empty($errors)) {
$pdo = db();
foreach ($updates as $key => $val) {
$stmt = $pdo->prepare("INSERT INTO settings (setting_key, setting_value) VALUES (:k, :v) ON DUPLICATE KEY UPDATE setting_value = :v2");
$stmt->execute([':k' => $key, ':v' => $val, ':v2' => $val]);
if (isset($_POST['action']) && $_POST['action'] === 'test_whatsapp') {
$testPhone = trim($_POST['test_phone'] ?? '');
$testMessage = trim($_POST['test_message'] ?? '');
if ($testPhone === '') {
$testError = 'Phone number is required for testing.';
} else {
// Check if settings are saved first?
// We rely on get_setting() which reads from DB.
// If user just changed input but didn't save, it won't work.
// That's standard behavior.
try {
// We use the new public method in NotificationService
// This method handles the 968 prefix logic internally.
NotificationService::sendWhatsApp($testPhone, $testMessage ?: 'Test message from CargoLink');
$testSuccess = 'Test message sent (check logs/phone).';
} catch (Throwable $e) {
$testError = 'Error sending test: ' . $e->getMessage();
}
}
} else {
// Save Settings
$updates = [
'thawani_publishable_key' => trim($_POST['thawani_publishable_key'] ?? ''),
'thawani_secret_key' => trim($_POST['thawani_secret_key'] ?? ''),
'thawani_environment' => trim($_POST['thawani_environment'] ?? 'test'),
'wablas_domain' => trim($_POST['wablas_domain'] ?? ''),
'wablas_api_token' => trim($_POST['wablas_api_token'] ?? ''),
'wablas_secret_key' => trim($_POST['wablas_secret_key'] ?? ''),
'whatsapp_enabled' => isset($_POST['whatsapp_enabled']) ? '1' : '0',
'smtp_host' => trim($_POST['smtp_host'] ?? ''),
'smtp_port' => trim($_POST['smtp_port'] ?? ''),
'smtp_secure' => trim($_POST['smtp_secure'] ?? ''),
'smtp_user' => trim($_POST['smtp_user'] ?? ''),
'smtp_pass' => trim($_POST['smtp_pass'] ?? ''),
'mail_from' => trim($_POST['mail_from'] ?? ''),
'mail_from_name' => trim($_POST['mail_from_name'] ?? ''),
];
if (empty($errors)) {
$pdo = db();
foreach ($updates as $key => $val) {
$stmt = $pdo->prepare("INSERT INTO settings (setting_key, setting_value) VALUES (:k, :v) ON DUPLICATE KEY UPDATE setting_value = :v2");
$stmt->execute([':k' => $key, ':v' => $val, ':v2' => $val]);
}
$success = "Integrations settings updated successfully.";
}
$success = "Integrations settings updated successfully.";
}
}
@ -68,11 +96,17 @@ render_header('Integrations', 'admin', true);
<?php if ($success): ?>
<div class="alert alert-success"><?= e($success) ?></div>
<?php endif; ?>
<?php if ($testSuccess): ?>
<div class="alert alert-info"><?= e($testSuccess) ?></div>
<?php endif; ?>
<?php if ($testError): ?>
<div class="alert alert-danger"><?= e($testError) ?></div>
<?php endif; ?>
<?php if ($errors): ?>
<div class="alert alert-danger"><?= e(implode('<br>', $errors)) ?></div>
<?php endif; ?>
<form method="post">
<form method="post" id="settingsForm">
<ul class="nav nav-tabs mb-4" id="integrationsTab" role="tablist">
<li class="nav-item" role="presentation">
@ -166,6 +200,27 @@ render_header('Integrations', 'admin', true);
</div>
</div>
</div>
<!-- Test Section -->
<div class="panel p-4 border-top">
<h4 class="h6 fw-bold mb-3">Test Connection</h4>
<div class="row g-2 align-items-end">
<div class="col-md-4">
<label class="form-label small text-muted">Test Phone Number</label>
<input type="text" form="testForm" name="test_phone" class="form-control" placeholder="e.g. 12345678">
<div class="form-text x-small">Enter 8 digits (system adds 968) or full number.</div>
</div>
<div class="col-md-5">
<label class="form-label small text-muted">Test Message</label>
<input type="text" form="testForm" name="test_message" class="form-control" placeholder="Test message...">
</div>
<div class="col-md-3">
<button type="submit" form="testForm" class="btn btn-outline-success w-100">
<i class="bi bi-send me-1"></i> Send Test
</button>
</div>
</div>
</div>
</div>
<!-- SMTP Mail Gateway Panel -->
@ -228,6 +283,11 @@ render_header('Integrations', 'admin', true);
<button type="submit" class="btn btn-primary px-5">Save Integrations</button>
</div>
</form>
<!-- Hidden Test Form -->
<form method="post" id="testForm" style="display:none;">
<input type="hidden" name="action" value="test_whatsapp">
</form>
</div>
</div>

View File

@ -9,7 +9,7 @@ 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 'email' and 'full_name')
* @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.
*/
@ -69,9 +69,109 @@ class NotificationService
// Send WhatsApp if enabled
if (get_setting('whatsapp_enabled') === '1') {
// Log WhatsApp (Mock)
// In a real app, this would call Twilio/Meta API
error_log("WHATSAPP Notification to {$user['email']} (Phone N/A): $whatsapp");
$phone = self::getPhoneNumber($user);
if ($phone) {
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.
*/
public static function sendWhatsApp(string $phone, string $message)
{
// 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;
}
// Ensure domain has no trailing slash and correct scheme
$domain = rtrim($domain, '/');
if (!preg_match('/^https?:\\/', $domain)) {
$domain = 'https://' . $domain;
}
// 3. Send API Request
// Endpoint: /api/send-message (StandardWablas)
$url = $domain . "/api/send-message";
$data = [
'phone' => $phone,
'message' => $message,
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: $token",
"Content-Type: application/json" // Wablas often accepts JSON or form-data. Trying JSON first, or form-data if that fails.
// Actually, many Wablas instances use form-data or x-www-form-urlencoded.
// Let's try standard POST fields which curl sends as application/x-www-form-urlencoded by default if passing array.
]);
// Resetting headers to just Authorization for form-urlencoded default
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: $token"
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // For dev env
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
error_log("WHATSAPP cURL Error: $error");
return;
}
// Log result
error_log("WHATSAPP Sent to $phone. Status: $httpCode. Response: " . substr($response, 0, 100));
}
}