39038-vm/admin_integrations.php
2026-03-14 13:13:28 +00:00

294 lines
17 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php'; require_role('admin');
require_once __DIR__ . '/includes/NotificationService.php';
ensure_schema();
$errors = [];
$success = '';
$testSuccess = '';
$testError = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') { validate_csrf_token();
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 {
try {
// We use the new public method in NotificationService
// This method handles the 968 prefix logic internally.
$res = NotificationService::sendWhatsApp($testPhone, $testMessage ?: 'Test message from CargoLink');
if ($res['success']) {
$testSuccess = 'Message sent! ' . $res['message'];
} else {
$testError = 'Failed: ' . $res['message'];
}
} 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.";
}
}
}
$settings = get_settings();
$thawaniPub = $settings['thawani_publishable_key'] ?? '';
$thawaniSec = $settings['thawani_secret_key'] ?? '';
$thawaniEnv = $settings['thawani_environment'] ?? 'test';
$wablasDomain = $settings['wablas_domain'] ?? '';
$wablasToken = $settings['wablas_api_token'] ?? '';
$wablasSecret = $settings['wablas_secret_key'] ?? '';
$whatsappEnabled = $settings['whatsapp_enabled'] ?? '0';
$smtpHost = $settings['smtp_host'] ?? '';
$smtpPort = $settings['smtp_port'] ?? '587';
$smtpSecure = $settings['smtp_secure'] ?? 'tls';
$smtpUser = $settings['smtp_user'] ?? '';
$smtpPass = $settings['smtp_pass'] ?? '';
$mailFrom = $settings['mail_from'] ?? '';
$mailFromName = $settings['mail_from_name'] ?? '';
render_header('Integrations', 'admin', true);
?>
<div class="row g-0">
<div class="col-md-2 bg-white border-end min-vh-100">
<?php render_admin_sidebar('integrations'); ?>
</div>
<div class="col-md-10 p-4">
<div class="page-intro mb-4">
<h1 class="section-title mb-1"><?= e(t('integrations')) ?></h1>
<p class="muted mb-0">Manage your payment gateway and communication APIs.</p>
</div>
<?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" id="settingsForm"> <?= csrf_field() ?>
<ul class="nav nav-tabs mb-4" id="integrationsTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="thawani-tab" data-bs-toggle="tab" data-bs-target="#thawani" type="button" role="tab" aria-controls="thawani" aria-selected="true">
Thawani Gateway
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="whatsapp-tab" data-bs-toggle="tab" data-bs-target="#whatsapp" type="button" role="tab" aria-controls="whatsapp" aria-selected="false">
<?= e(t('whatsapp_settings')) ?>
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="smtp-tab" data-bs-toggle="tab" data-bs-target="#smtp" type="button" role="tab" aria-controls="smtp" aria-selected="false">
SMTP Mail
</button>
</li>
</ul>
<div class="tab-content" id="integrationsTabContent">
<!-- Thawani Payments Panel -->
<div class="tab-pane fade show active" id="thawani" role="tabpanel" aria-labelledby="thawani-tab">
<div class="panel p-4 mb-4">
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-credit-card me-2 text-primary" viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v1h14V4a1 1 0 0 0-1-1zm13 4H1v5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1z"/>
<path d="M2 10a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z"/>
</svg>
Thawani Payments Gateway
</h3>
<p class="text-muted small mb-4">Configure your Oman-based Thawani Pay integration to process shipment payments.</p>
<div class="row g-0">
<div class="col-md-6">
<label class="form-label fw-bold">Environment</label>
<select name="thawani_environment" class="form-select">
<option value="test" <?= $thawaniEnv === 'test' ? 'selected' : '' ?>>Test / Sandbox</option>
<option value="live" <?= $thawaniEnv === 'live' ? 'selected' : '' ?>>Live / Production</option>
</select>
</div>
<div class="col-md-6"></div>
<div class="col-md-6">
<label class="form-label fw-bold">Publishable Key</label>
<input type="text" name="thawani_publishable_key" class="form-control" value="<?= e($thawaniPub) ?>" placeholder="pk_test_...">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Secret Key</label>
<input type="password" name="thawani_secret_key" class="form-control" value="<?= e($thawaniSec) ?>" placeholder="sk_test_...">
</div>
</div>
</div>
</div>
<!-- Wablas WhatsApp Gateway Panel -->
<div class="tab-pane fade" id="whatsapp" role="tabpanel" aria-labelledby="whatsapp-tab">
<div class="panel p-4 mb-4">
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-whatsapp me-2 text-success" viewBox="0 0 16 16">
<path d="M13.601 2.326A7.85 7.85 0 0 0 7.994 0C3.627 0 .068 3.558.064 7.926c0 1.399.366 2.76 1.057 3.965L0 16l4.204-1.102a7.9 7.9 0 0 0 3.79.965h.004c4.368 0 7.926-3.558 7.93-7.93A7.9 7.9 0 0 0 13.6 2.326zM7.994 14.521a6.6 6.6 0 0 1-3.356-.92l-.24-.144-2.494.654.666-2.433-.156-.251a6.56 6.56 0 0 1-1.007-3.505c0-3.626 2.957-6.584 6.591-6.584a6.56 6.56 0 0 1 4.66 1.931 6.56 6.56 0 0 1 1.928 4.66c-.004 3.639-2.961 6.592-6.592 6.592m3.615-4.934c-.197-.099-1.17-.578-1.353-.646-.182-.065-.315-.099-.445.099-.133.197-.513.646-.627.775-.114.133-.232.148-.43.05-.197-.1-.836-.308-1.592-.985-.59-.525-.985-1.175-1.103-1.372-.114-.198-.011-.304.088-.403.087-.088.197-.232.296-.346.1-.114.133-.198.198-.33.065-.134.034-.248-.015-.347-.05-.099-.445-1.076-.612-1.47-.16-.389-.323-.335-.445-.34-.114-.007-.247-.007-.38-.007a.73.73 0 0 0-.529.247c-.182.198-.691.677-.691 1.654s.71 1.916.81 2.049c.098.133 1.394 2.132 3.383 2.992.47.205.84.326 1.129.418.475.152.904.129 1.246.08.38-.058 1.171-.48 1.338-.943.164-.464.164-.86.114-.943-.049-.084-.182-.133-.38-.232"/>
</svg>
<?= e(t('whatsapp_settings')) ?>
</h3>
<p class="text-muted small mb-4">Connect Wablas to automatically send WhatsApp notifications to Shippers and Truck Owners.</p>
<div class="row g-0">
<div class="col-12 mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="whatsapp_enabled" id="whatsapp_enabled" value="1" <?= $whatsappEnabled === '1' ? 'checked' : '' ?>>
<label class="form-check-label fw-bold" for="whatsapp_enabled"><?= e(t('enable_whatsapp')) ?></label>
</div>
</div>
<div class="col-md-6">
<label class="form-label fw-bold"><?= e(t('wablas_domain')) ?></label>
<input type="text" name="wablas_domain" class="form-control" value="<?= e($wablasDomain) ?>" placeholder="e.g. https://solo.wablas.com">
<div class="form-text">Your assigned server node from the Wablas dashboard.</div>
</div>
<div class="col-md-6">
<label class="form-label fw-bold"><?= e(t('wablas_api_token')) ?></label>
<input type="password" name="wablas_api_token" class="form-control" value="<?= e($wablasToken) ?>" placeholder="API Token">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Secret Key</label>
<input type="password" name="wablas_secret_key" class="form-control" value="<?= e($wablasSecret) ?>" placeholder="Secret Key">
<div class="form-text">Optional. Provide if your Wablas webhooks require signature verification.</div>
</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 -->
<div class="tab-pane fade" id="smtp" role="tabpanel" aria-labelledby="smtp-tab">
<div class="panel p-4 mb-4">
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-envelope me-2 text-danger" viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"/>
</svg>
SMTP Mail Settings
</h3>
<p class="text-muted small mb-4">Configure your SMTP server to send emails and system notifications.</p>
<div class="row g-0">
<div class="col-md-6">
<label class="form-label fw-bold">SMTP Host</label>
<input type="text" name="smtp_host" class="form-control" value="<?= e($smtpHost) ?>" placeholder="smtp.example.com">
</div>
<div class="col-md-3">
<label class="form-label fw-bold">SMTP Port</label>
<input type="number" name="smtp_port" class="form-control" value="<?= e($smtpPort) ?>" placeholder="587">
</div>
<div class="col-md-3">
<label class="form-label fw-bold">Security</label>
<select name="smtp_secure" class="form-select">
<option value="tls" <?= $smtpSecure === 'tls' ? 'selected' : '' ?>>TLS</option>
<option value="ssl" <?= $smtpSecure === 'ssl' ? 'selected' : '' ?>>SSL</option>
<option value="none" <?= $smtpSecure === 'none' || $smtpSecure === '' ? 'selected' : '' ?>>None</option>
</select>
</div>
<div class="col-md-6">
<label class="form-label fw-bold">SMTP Username</label>
<input type="text" name="smtp_user" class="form-control" value="<?= e($smtpUser) ?>" placeholder="user@example.com">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">SMTP Password</label>
<input type="password" name="smtp_pass" class="form-control" value="<?= e($smtpPass) ?>" placeholder="••••••••">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Mail From Address</label>
<input type="email" name="mail_from" class="form-control" value="<?= e($mailFrom) ?>" placeholder="noreply@example.com">
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Mail From Name</label>
<input type="text" name="mail_from_name" class="form-control" value="<?= e($mailFromName) ?>" placeholder="CargoLink System">
</div>
</div>
</div>
</div>
</div>
<div class="d-flex justify-content-end mt-4">
<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;"> <?= csrf_field() ?>
<input type="hidden" name="action" value="test_whatsapp">
</form>
</div>
</div>
<?php render_footer(); ?>