adding whatapp
This commit is contained in:
parent
d2a2461bda
commit
2a16f1f83e
64
admin.php
64
admin.php
@ -2,6 +2,17 @@
|
||||
$title = 'dashboard';
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
|
||||
// Handle WhatsApp Settings Save
|
||||
if ($is_super && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_whatsapp_settings'])) {
|
||||
set_setting('whatsapp_enabled', $_POST['whatsapp_enabled'] ?? '0');
|
||||
set_setting('wablas_token', $_POST['wablas_token'] ?? '');
|
||||
set_setting('wablas_server', $_POST['wablas_server'] ?? '');
|
||||
set_setting('msg_order_created_ar', $_POST['msg_order_created_ar'] ?? '');
|
||||
set_setting('msg_order_ready_ar', $_POST['msg_order_ready_ar'] ?? '');
|
||||
set_setting('msg_payment_ar', $_POST['msg_payment_ar'] ?? '');
|
||||
$success_msg = is_arabic() ? 'تم حفظ الإعدادات بنجاح' : 'Settings saved successfully';
|
||||
}
|
||||
|
||||
// Helper functions for status colors
|
||||
if (!function_exists('getStatusColor')) {
|
||||
function getStatusColor($status) {
|
||||
@ -281,8 +292,59 @@ if (!$is_limited) {
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php if ($is_super): ?>
|
||||
<div class="mt-4">
|
||||
<div class="card p-4 shadow-sm" style="border-radius: 20px;">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h5 class="fw-bold mb-0"><i class="bi bi-whatsapp text-success me-2"></i> <?= __('whatsapp_settings') ?></h5>
|
||||
<?php if (isset($success_msg)): ?>
|
||||
<div class="alert alert-success py-2 px-3 mb-0" style="border-radius: 10px;"><?= $success_msg ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<form method="POST">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12">
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="whatsapp_enabled" name="whatsapp_enabled" value="1" <?= get_setting('whatsapp_enabled') == '1' ? 'checked' : '' ?>>
|
||||
<label class="form-check-label" for="whatsapp_enabled"><?= __('whatsapp_enabled') ?></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold"><?= __('wablas_token') ?></label>
|
||||
<input type="text" class="form-control" name="wablas_token" value="<?= htmlspecialchars(get_setting('wablas_token', '')) ?>" placeholder="Wablas API Token">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold"><?= __('wablas_server') ?></label>
|
||||
<input type="text" class="form-control" name="wablas_server" value="<?= htmlspecialchars(get_setting('wablas_server', 'https://console.wablas.com')) ?>" placeholder="https://console.wablas.com">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-semibold"><?= __('msg_order_created_ar') ?></label>
|
||||
<textarea class="form-control mb-2" name="msg_order_created_ar" rows="2"><?= htmlspecialchars(get_setting('msg_order_created_ar', '')) ?></textarea>
|
||||
<small class="text-muted">Tags: {customer_name}, {order_number}, {order_details}, {total_price}</small>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-semibold"><?= __('msg_order_ready_ar') ?></label>
|
||||
<textarea class="form-control mb-2" name="msg_order_ready_ar" rows="2"><?= htmlspecialchars(get_setting('msg_order_ready_ar', '')) ?></textarea>
|
||||
<small class="text-muted">Tags: {customer_name}, {order_number}</small>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-semibold"><?= __('msg_payment_ar') ?></label>
|
||||
<textarea class="form-control mb-2" name="msg_payment_ar" rows="2"><?= htmlspecialchars(get_setting('msg_payment_ar', '')) ?></textarea>
|
||||
<small class="text-muted">Tags: {customer_name}, {order_number}, {amount}, {remaining_balance}</small>
|
||||
</div>
|
||||
<div class="col-12 mt-4">
|
||||
<button type="submit" name="save_whatsapp_settings" class="btn btn-primary px-4 py-2" style="border-radius: 12px;">
|
||||
<i class="bi bi-save me-2"></i> <?= is_arabic() ? 'حفظ' : 'Save' ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/footer.php';
|
||||
?>
|
||||
?>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../includes/whatsapp.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
@ -95,9 +96,65 @@ try {
|
||||
$stmt_payment->execute([$order_id, $total_price, $payment_method]);
|
||||
}
|
||||
|
||||
// Fetch customer details for notifications
|
||||
$customer = null;
|
||||
if ($customer_id) {
|
||||
$stmt_cust = $pdo->prepare('SELECT name_ar, phone FROM customers WHERE id = ?');
|
||||
$stmt_cust->execute([$customer_id]);
|
||||
$customer = $stmt_cust->fetch();
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
// WhatsApp Notifications
|
||||
try {
|
||||
if (get_setting('whatsapp_enabled') === '1' && $customer && !empty($customer['phone'])) {
|
||||
// 1. Order Created Notification
|
||||
$template = get_setting('msg_order_created_ar');
|
||||
if (!empty($template)) {
|
||||
$details_parts = [];
|
||||
foreach ($items as $item) {
|
||||
$stmt_names = $pdo->prepare('SELECT i.name_ar as item_name, s.name_ar as service_name FROM items i, services s WHERE i.id = ? AND s.id = ?');
|
||||
$stmt_names->execute([$item['itemId'], $item['serviceId']]);
|
||||
$names = $stmt_names->fetch();
|
||||
$details_parts[] = ($names['item_name'] ?? 'صنف') . ' (' . ($names['service_name'] ?? 'خدمة') . ') x' . $item['quantity'];
|
||||
}
|
||||
$order_details = implode(', ', $details_parts);
|
||||
|
||||
// Get order number if not already available
|
||||
if (!isset($order_number)) {
|
||||
$stmt_onum = $pdo->prepare('SELECT order_number FROM orders WHERE id = ?');
|
||||
$stmt_onum->execute([$order_id]);
|
||||
$order_number = $stmt_onum->fetchColumn();
|
||||
}
|
||||
|
||||
$message = str_replace(
|
||||
['{customer_name}', '{order_number}', '{order_details}', '{total_price}'],
|
||||
[$customer['name_ar'], $order_number, $order_details, $total_price],
|
||||
$template
|
||||
);
|
||||
send_whatsapp_message($customer['phone'], $message);
|
||||
}
|
||||
|
||||
// 2. Payment Received Notification (if paid during checkout)
|
||||
if ($payment_method && $payment_method !== 'pay_later') {
|
||||
$template_pay = get_setting('msg_payment_ar');
|
||||
if (!empty($template_pay)) {
|
||||
$message_pay = str_replace(
|
||||
['{customer_name}', '{order_number}', '{amount}', '{remaining_balance}'],
|
||||
[$customer['name_ar'], $order_number, $total_price, 0],
|
||||
$template_pay
|
||||
);
|
||||
send_whatsapp_message($customer['phone'], $message_pay);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Silently fail for notifications
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'order_id' => $order_id]);
|
||||
} catch (Exception $e) {
|
||||
if (isset($pdo)) $pdo->rollBack();
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../includes/whatsapp.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
@ -29,10 +30,35 @@ try {
|
||||
$stmt->execute([$status, $id]);
|
||||
|
||||
if ($stmt->rowCount() > 0) {
|
||||
// WhatsApp Notification for Order Ready
|
||||
try {
|
||||
if ($status === 'ready') {
|
||||
if (get_setting('whatsapp_enabled') === '1') {
|
||||
$stmt_details = $pdo->prepare('SELECT o.order_number, c.name_ar, c.phone FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.id = ?');
|
||||
$stmt_details->execute([$id]);
|
||||
$order = $stmt_details->fetch();
|
||||
|
||||
if ($order && !empty($order['phone'])) {
|
||||
$template = get_setting('msg_order_ready_ar');
|
||||
if (!empty($template)) {
|
||||
$message = str_replace(
|
||||
['{customer_name}', '{order_number}'],
|
||||
[$order['name_ar'], $order['order_number']],
|
||||
$template
|
||||
);
|
||||
send_whatsapp_message($order['phone'], $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// Silently fail for notification
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Order not found or status already same']);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
@ -43,7 +43,23 @@ function check_permission($page = null, $user_id = null) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
function get_setting($key, $default = null) {
|
||||
try {
|
||||
$stmt = db()->prepare('SELECT setting_value FROM settings WHERE setting_key = ?');
|
||||
$stmt->execute([$key]);
|
||||
$val = $stmt->fetchColumn();
|
||||
return ($val !== false) ? $val : $default;
|
||||
} catch (Exception $e) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
function set_setting($key, $value) {
|
||||
$stmt = db()->prepare('INSERT INTO settings (setting_key, setting_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE setting_value = ?, updated_at = CURRENT_TIMESTAMP');
|
||||
$stmt->execute([$key, $value, $value]);
|
||||
}
|
||||
|
||||
function has_permission($action, $page = null, $user_id = null) {
|
||||
$perms = check_permission($page, $user_id);
|
||||
return !empty($perms[$action]);
|
||||
}
|
||||
}
|
||||
|
||||
14
db/migrations/14_add_whatsapp_settings.sql
Normal file
14
db/migrations/14_add_whatsapp_settings.sql
Normal file
@ -0,0 +1,14 @@
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
setting_key VARCHAR(100) PRIMARY KEY,
|
||||
setting_value TEXT,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Initial WhatsApp settings
|
||||
INSERT INTO settings (setting_key, setting_value) VALUES
|
||||
('whatsapp_enabled', '0'),
|
||||
('wablas_token', ''),
|
||||
('wablas_server', 'https://console.wablas.com'),
|
||||
('msg_order_created_ar', 'عزيزي {customer_name}، تم استلام طلبك رقم {order_number}. التفاصيل: {order_details}. الإجمالي: {total_price}. شكراً لتعاملك معنا.'),
|
||||
('msg_order_ready_ar', 'عزيزي {customer_name}، طلبك رقم {order_number} جاهز للاستلام. شكراً لتعاملك معنا.'),
|
||||
('msg_payment_ar', 'عزيزي {customer_name}، تم استلام دفعة بمبلغ {amount} لطلبك رقم {order_number}. الرصيد المتبقي: {remaining_balance}. شكراً لتعاملك معنا.');
|
||||
@ -18,6 +18,7 @@ $translations = [
|
||||
'branches' => 'Branches',
|
||||
'users' => 'Users',
|
||||
'settings' => 'Settings',
|
||||
'whatsapp_settings' => 'WhatsApp Settings', 'whatsapp_enabled' => 'WhatsApp Enabled', 'wablas_token' => 'Wablas API Token', 'wablas_server' => 'Wablas Server URL', 'msg_order_created_ar' => 'Order Created Message (Arabic)', 'msg_order_ready_ar' => 'Order Ready Message (Arabic)', 'msg_payment_ar' => 'Payment Received Message (Arabic)',
|
||||
'logout' => 'Logout',
|
||||
'login' => 'Login',
|
||||
'username' => 'Username',
|
||||
@ -206,6 +207,7 @@ $translations = [
|
||||
'branches' => 'الفروع',
|
||||
'users' => 'المستخدمين',
|
||||
'settings' => 'الإعدادات',
|
||||
'whatsapp_settings' => 'إعدادات الواتساب', 'whatsapp_enabled' => 'تفعيل الواتساب', 'wablas_token' => 'رمز API Wablas', 'wablas_server' => 'رابط خادم Wablas', 'msg_order_created_ar' => 'رسالة إنشاء الطلب (بالعربية)', 'msg_order_ready_ar' => 'رسالة الطلب جاهز (بالعربية)', 'msg_payment_ar' => 'رسالة استلام الدفعة (بالعربية)',
|
||||
'logout' => 'تسجيل الخروج',
|
||||
'login' => 'تسجيل الدخول',
|
||||
'username' => 'اسم المستخدم',
|
||||
|
||||
51
includes/whatsapp.php
Normal file
51
includes/whatsapp.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
function send_whatsapp_message($phone, $message) {
|
||||
if (get_setting('whatsapp_enabled') !== '1') {
|
||||
return ['success' => false, 'error' => 'WhatsApp is disabled'];
|
||||
}
|
||||
|
||||
$token = get_setting('wablas_token');
|
||||
$server = get_setting('wablas_server', 'https://console.wablas.com');
|
||||
|
||||
if (empty($token) || empty($server)) {
|
||||
return ['success' => false, 'error' => 'Wablas configuration is incomplete'];
|
||||
}
|
||||
|
||||
// Clean phone number (ensure it has country code, e.g., 966 for Saudi Arabia if not provided)
|
||||
// For now, assume user provides it or we just use it as is if it looks correct.
|
||||
$phone = preg_replace('/[^0-9]/', '', $phone);
|
||||
|
||||
// Wablas API expects phone number.
|
||||
$curl = curl_init();
|
||||
$data = [
|
||||
'phone' => $phone,
|
||||
'message' => $message,
|
||||
];
|
||||
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, [
|
||||
"Authorization: $token",
|
||||
]);
|
||||
curl_setopt($curl, CURLOPT_URL, rtrim($server, '/') . "/api/send-message");
|
||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
|
||||
|
||||
$result = curl_exec($curl);
|
||||
$error = curl_error($curl);
|
||||
curl_close($curl);
|
||||
|
||||
if ($error) {
|
||||
return ['success' => false, 'error' => $error];
|
||||
}
|
||||
|
||||
$response = json_decode($result, true);
|
||||
if (isset($response['status']) && $response['status'] == true) {
|
||||
return ['success' => true, 'response' => $response];
|
||||
}
|
||||
|
||||
return ['success' => false, 'error' => $response['message'] ?? 'Unknown error from Wablas'];
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
// ACTION HANDLING FIRST
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/includes/lang.php';
|
||||
require_once __DIR__ . '/includes/whatsapp.php';
|
||||
|
||||
$order_id = $_GET['id'] ?? null;
|
||||
if (!$order_id) {
|
||||
@ -27,10 +28,26 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||
$new_status = $_POST['status'];
|
||||
$stmt = db()->prepare("UPDATE orders SET status = ? WHERE id = ?");
|
||||
$stmt->execute([$new_status, $order_id]);
|
||||
|
||||
// WhatsApp Notification for Order Ready
|
||||
try {
|
||||
if ($new_status === 'ready' && get_setting('whatsapp_enabled') === '1' && !empty($order['customer_phone'])) {
|
||||
$template = get_setting('msg_order_ready_ar');
|
||||
if (!empty($template)) {
|
||||
$message = str_replace(
|
||||
['{customer_name}', '{order_number}'],
|
||||
[$order['customer_name_ar'], $order['order_number']],
|
||||
$template
|
||||
);
|
||||
send_whatsapp_message($order['customer_phone'], $message);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {}
|
||||
|
||||
header("Location: order_details.php?id=$order_id");
|
||||
exit;
|
||||
} elseif ($_POST['action'] === 'add_payment') {
|
||||
$amount = $_POST['amount'];
|
||||
$amount = (float)$_POST['amount'];
|
||||
$method = $_POST['payment_method'];
|
||||
$stmt = db()->prepare("INSERT INTO payments (order_id, amount, payment_method) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$order_id, $amount, $method]);
|
||||
@ -43,6 +60,22 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||
$stmt = db()->prepare("UPDATE orders SET payment_status = ? WHERE id = ?");
|
||||
$stmt->execute([$payment_status, $order_id]);
|
||||
|
||||
// WhatsApp Notification for Payment Received
|
||||
try {
|
||||
if (get_setting('whatsapp_enabled') === '1' && !empty($order['customer_phone'])) {
|
||||
$remaining_now = (float)$order['total_price'] - (float)$total_paid;
|
||||
$template = get_setting('msg_payment_ar');
|
||||
if (!empty($template)) {
|
||||
$message = str_replace(
|
||||
['{customer_name}', '{order_number}', '{amount}', '{remaining_balance}'],
|
||||
[$order['customer_name_ar'], $order['order_number'], $amount, max(0, $remaining_now)],
|
||||
$template
|
||||
);
|
||||
send_whatsapp_message($order['customer_phone'], $message);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {}
|
||||
|
||||
header("Location: order_details.php?id=$order_id");
|
||||
exit;
|
||||
}
|
||||
@ -193,7 +226,7 @@ $payments = $stmt->fetchAll();
|
||||
$stmt = db()->prepare("SELECT SUM(amount) as total_paid FROM payments WHERE order_id = ?");
|
||||
$stmt->execute([$order_id]);
|
||||
$total_paid = $stmt->fetch()['total_paid'] ?? 0;
|
||||
$remaining = $order['total_price'] - $total_paid;
|
||||
$remaining = (float)$order['total_price'] - (float)$total_paid;
|
||||
?>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<span class="text-muted fw-bold small"><?= __('remaining_amount') ?></span>
|
||||
@ -255,4 +288,4 @@ function getPaymentStatusColor($status) {
|
||||
][$status] ?? 'info';
|
||||
}
|
||||
require_once __DIR__ . '/includes/footer.php';
|
||||
?>
|
||||
?>
|
||||
Loading…
x
Reference in New Issue
Block a user