183 lines
6.0 KiB
PHP
183 lines
6.0 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../includes/app.php';
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
echo json_encode(['success' => false, 'error' => 'Invalid method']);
|
|
exit;
|
|
}
|
|
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
if (!$input || empty($input['items'])) {
|
|
echo json_encode(['success' => false, 'error' => 'Cart is empty']);
|
|
exit;
|
|
}
|
|
|
|
$name = trim($input['name'] ?? '');
|
|
$phoneInput = trim($input['phone'] ?? '');
|
|
$phone = normalize_oman_phone($phoneInput);
|
|
$address = trim($input['address'] ?? '');
|
|
$acceptPolicies = !empty($input['accept_policies']);
|
|
$paymentMethod = trim((string) ($input['payment_method'] ?? 'pay_later'));
|
|
if (!in_array($paymentMethod, ['pay_later', 'pay_online'], true)) {
|
|
echo json_encode(['success' => false, 'error' => 'Invalid payment method']);
|
|
exit;
|
|
}
|
|
if (!$acceptPolicies) {
|
|
echo json_encode(['success' => false, 'error' => 'You must accept the Privacy Policy and Terms & Conditions']);
|
|
exit;
|
|
}
|
|
if ($paymentMethod === 'pay_online' && !thawani_is_configured()) {
|
|
echo json_encode(['success' => false, 'error' => 'Thawani payment is not configured']);
|
|
exit;
|
|
}
|
|
|
|
if ($name === '' || $phoneInput === '' || $address === '') {
|
|
echo json_encode(['success' => false, 'error' => 'Missing customer details']);
|
|
exit;
|
|
}
|
|
|
|
if ($phone === '') {
|
|
echo json_encode(['success' => false, 'error' => 'Phone must be an 8-digit Oman number']);
|
|
exit;
|
|
}
|
|
|
|
$items = $input['items'];
|
|
$subtotal = 0;
|
|
$totalVat = 0;
|
|
|
|
// Recalculate total for security
|
|
$db = db();
|
|
$processedItems = [];
|
|
foreach ($items as $id => $item) {
|
|
$qty = (int)$item['qty'];
|
|
if ($qty <= 0) continue;
|
|
|
|
// get price and vat from DB
|
|
$stmt = $db->prepare("SELECT sku, name, price, vat FROM items WHERE id = ?");
|
|
$stmt->execute([$id]);
|
|
$dbItem = $stmt->fetch();
|
|
if ($dbItem) {
|
|
$price = (float)$dbItem['price'];
|
|
$vatPercent = (float)($dbItem['vat'] ?? 0);
|
|
$lineTotal = $price * $qty;
|
|
$itemVat = $lineTotal * ($vatPercent / 100);
|
|
|
|
$subtotal += $lineTotal;
|
|
$totalVat += $itemVat;
|
|
|
|
$processedItems[] = [
|
|
'id' => $id,
|
|
'sku' => $dbItem['sku'],
|
|
'name' => $dbItem['name'],
|
|
'price' => $price,
|
|
'vat' => $vatPercent,
|
|
'vat_amount' => $itemVat,
|
|
'qty' => $qty,
|
|
'line_total' => $lineTotal
|
|
];
|
|
}
|
|
}
|
|
|
|
if (empty($processedItems)) {
|
|
echo json_encode(['success' => false, 'error' => 'Invalid items']);
|
|
exit;
|
|
}
|
|
|
|
$totalAmount = $subtotal + $totalVat;
|
|
|
|
try {
|
|
$db->beginTransaction();
|
|
|
|
$paymentGateway = $paymentMethod === 'pay_online' ? 'thawani' : null;
|
|
$paymentStatus = $paymentMethod === 'pay_online' ? 'pending' : 'unpaid';
|
|
|
|
$stmt = $db->prepare("INSERT INTO online_orders (customer_name, customer_phone, customer_address, items_json, subtotal, vat_amount, total_amount, payment_method, payment_gateway, payment_status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
$stmt->execute([
|
|
$name,
|
|
$phone,
|
|
$address,
|
|
json_encode($processedItems, JSON_UNESCAPED_UNICODE),
|
|
$subtotal,
|
|
$totalVat,
|
|
$totalAmount,
|
|
$paymentMethod,
|
|
$paymentGateway,
|
|
$paymentStatus
|
|
]);
|
|
|
|
$orderId = (int) $db->lastInsertId();
|
|
sync_online_order_stock_reservation([], 'rejected', $processedItems, 'pending');
|
|
|
|
$checkoutUrl = null;
|
|
if ($paymentMethod === 'pay_online') {
|
|
$thawaniResult = thawani_create_checkout_session($orderId, [
|
|
'customer_name' => $name,
|
|
'customer_phone' => $phone,
|
|
'customer_address' => $address,
|
|
'items' => $processedItems,
|
|
]);
|
|
if (empty($thawaniResult['success'])) {
|
|
throw new RuntimeException((string) ($thawaniResult['error'] ?? 'Unable to create Thawani session'));
|
|
}
|
|
|
|
$checkoutUrl = (string) ($thawaniResult['checkout_url'] ?? '');
|
|
$sessionId = (string) ($thawaniResult['session_id'] ?? '');
|
|
$updateStmt = $db->prepare("UPDATE online_orders SET gateway_session_id = ? WHERE id = ?");
|
|
$updateStmt->execute([$sessionId, $orderId]);
|
|
}
|
|
|
|
$db->commit();
|
|
|
|
// Optional: send Telegram admin notice and customer WhatsApp notification.
|
|
try {
|
|
$msg = "🛒 *New Online Order #{$orderId}*
|
|
|
|
";
|
|
$msg .= "👤 {$name}
|
|
📞 " . phone_display($phone) . "
|
|
📍 {$address}
|
|
|
|
";
|
|
$msg .= "💰 Subtotal: " . currency($subtotal) . "
|
|
";
|
|
$msg .= "🧾 VAT: " . currency($totalVat) . "
|
|
";
|
|
$msg .= "💵 Total: " . currency($totalAmount) . "
|
|
";
|
|
|
|
$botToken = getenv('TELEGRAM_BOT_TOKEN') ?: get_setting('telegram_bot_token');
|
|
$chatId = getenv('TELEGRAM_CHAT_ID') ?: get_setting('telegram_chat_id');
|
|
if ($botToken && $chatId) {
|
|
$url = "https://api.telegram.org/bot{$botToken}/sendMessage";
|
|
$data = ['chat_id' => $chatId, 'text' => $msg, 'parse_mode' => 'Markdown'];
|
|
$options = [
|
|
'http' => [
|
|
'header' => "Content-type: application/x-www-form-urlencoded
|
|
",
|
|
'method' => 'POST',
|
|
'content' => http_build_query($data)
|
|
]
|
|
];
|
|
$context = stream_context_create($options);
|
|
@file_get_contents($url, false, $context);
|
|
}
|
|
} catch (Throwable $e) {
|
|
error_log('Telegram notify failed for online order #' . $orderId . ': ' . $e->getMessage());
|
|
}
|
|
|
|
if ($paymentMethod === 'pay_later' && wablas_is_configured()) {
|
|
try {
|
|
wablas_notify_online_order_by_id($orderId, 'created');
|
|
} catch (Throwable $e) {
|
|
error_log('Customer WhatsApp notify failed for online order #' . $orderId . ': ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
echo json_encode(['success' => true, 'redirect_url' => $checkoutUrl]);
|
|
} catch (Throwable $e) {
|
|
if ($db->inTransaction()) {
|
|
$db->rollBack();
|
|
}
|
|
echo json_encode(['success' => false, 'error' => 'Database error: ' . $e->getMessage()]);
|
|
} |