255 lines
8.9 KiB
PHP
Executable File
255 lines
8.9 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* process_passenger_sms_payment.php
|
|
* - يستخدم BASE_URL الموجودة مسبقًا (لا يُعرّف بديل).
|
|
* - يستخدم Gemini 2.5 Flash Lite.
|
|
* - لا يحدّث raw_sms_log الآن (لا mark processed/failed).
|
|
* - الدفع للراكب فقط: invoices_sms_passenger → bonus → generate token → add to wallets.
|
|
*/
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
include_once __DIR__ . '/../../jwtconnect.php';
|
|
|
|
if (!defined('BASE_URL')) {
|
|
$APP_BASE_URL = rtrim(getenv('APP_BASE_URL') ?: '', '/');
|
|
if ($APP_BASE_URL === '') {
|
|
$scheme = isset($_SERVER['REQUEST_SCHEME']) ? $_SERVER['REQUEST_SCHEME'] : 'https';
|
|
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
|
|
define('BASE_URL', $scheme . '://' . $host);
|
|
} else {
|
|
define('BASE_URL', $APP_BASE_URL);
|
|
}
|
|
}
|
|
|
|
/* ===== Gemini: Flash Lite ===== */
|
|
$geminiModel = 'gemini-2.5-flash-lite';
|
|
$geminiApiKey = getenv('GEMINI_API_KEY');
|
|
if (!$geminiApiKey) {
|
|
printFailure("Missing GEMINI_API_KEY");
|
|
exit;
|
|
}
|
|
$geminiApiUrl = "https://generativelanguage.googleapis.com/v1beta/models/{$geminiModel}:generateContent?key={$geminiApiKey}";
|
|
|
|
/* ===== اجلب رسالة واحدة pending (مع sender) ===== */
|
|
try {
|
|
$stmt = $con->prepare("
|
|
SELECT id, message_body, sender
|
|
FROM raw_sms_log
|
|
WHERE status = 'pending'
|
|
ORDER BY created_at ASC
|
|
LIMIT 1
|
|
");
|
|
$stmt->execute();
|
|
$sms = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
if (!$sms) {
|
|
echo json_encode(["status" => "idle", "message" => "No pending messages"]);
|
|
exit;
|
|
}
|
|
} catch (PDOException $e) {
|
|
printFailure("DB fetch error: " . $e->getMessage());
|
|
exit;
|
|
}
|
|
|
|
$smsId = (int)$sms['id'];
|
|
$body = (string)$sms['message_body'];
|
|
$sender = (string)$sms['sender']; // نستخدمه لاشتقاق طريقة الدفع
|
|
|
|
/* ===== Prompt لِـ Gemini ===== */
|
|
$prompt = "Analyze the following financial SMS and return ONLY a valid JSON object:
|
|
{
|
|
\"transaction_type\": \"income\" | \"payout\",
|
|
\"amount\": number,
|
|
\"currency\": \"SYP\" | string (3 letters),
|
|
\"phone_number\": string | null
|
|
}
|
|
SMS Text: \"$body\"";
|
|
|
|
$payload = ['contents' => [['parts' => [['text' => $prompt]]]]];
|
|
|
|
$ch = curl_init($geminiApiUrl);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_UNESCAPED_UNICODE));
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$curlErr = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if ($response === false) {
|
|
printFailure("Gemini curl error: " . $curlErr);
|
|
exit;
|
|
}
|
|
|
|
$gem = json_decode($response, true);
|
|
$gemText = $gem['candidates'][0]['content']['parts'][0]['text'] ?? null;
|
|
if ($httpCode !== 200 || !$gemText) {
|
|
printFailure("Gemini HTTP $httpCode / empty response");
|
|
exit;
|
|
}
|
|
|
|
/* Gemini أحيانًا يحيط الـ JSON بعلامات Markdown */
|
|
$clean = trim(str_replace(['```json','```JSON','```'], '', $gemText));
|
|
$data = json_decode($clean, true);
|
|
if (!is_array($data) || empty($data['transaction_type'])) {
|
|
printFailure("Failed to parse Gemini JSON");
|
|
exit;
|
|
}
|
|
|
|
/* ===== القيم المستخرجة ===== */
|
|
$trxType = strtolower((string)$data['transaction_type']);
|
|
$amount = isset($data['amount']) ? floatval($data['amount']) : 0.0;
|
|
$currency = isset($data['currency']) ? strtoupper((string)$data['currency']) : '';
|
|
$phone = isset($data['phone_number']) ? (string)$data['phone_number'] : '';
|
|
|
|
/* ===== طريقة الدفع من الـ sender (الآن ثابتة shamcash كما طلبت) ===== */
|
|
$paymentMethod = 'shamcash'; // أو اشتقاق ذكي: strpos(strtolower($sender),'sham') !== false ? 'shamcash' : 'unknown';
|
|
|
|
/* ===== فقط INCOME: نفّذ تدفّق الراكب ===== */
|
|
if ($trxType === 'income' && $amount > 0 && $phone !== '') {
|
|
try {
|
|
// ابحث عن فاتورة راكب حديثة متطابقة خلال 60 دقيقة
|
|
$q = $con->prepare("
|
|
SELECT id
|
|
FROM invoices_sms_passenger
|
|
WHERE status='pending'
|
|
AND user_phone = :p
|
|
AND amount = :a
|
|
AND created_at >= (NOW() - INTERVAL 60 MINUTE)
|
|
ORDER BY created_at DESC
|
|
LIMIT 1
|
|
");
|
|
$q->execute([':p' => $phone, ':a' => $amount]);
|
|
$inv = $q->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$inv) {
|
|
printFailure( "No matching passenger invoice");
|
|
exit;
|
|
}
|
|
|
|
$invoiceId = $inv['id'];
|
|
|
|
// حدّث حالة الفاتورة
|
|
$con->prepare("UPDATE invoices_sms_passenger SET status='completed', updated_at=NOW() WHERE id=:id")
|
|
->execute([':id' => $invoiceId]);
|
|
|
|
// احضر بيانات الفاتورة لمعرفة passengerID والمبلغ المؤكد
|
|
$st = $con->prepare("SELECT passengerID, amount FROM invoices_sms_passenger WHERE id=:id LIMIT 1");
|
|
$st->execute([':id' => $invoiceId]);
|
|
$row = $st->fetch(PDO::FETCH_ASSOC);
|
|
if (!$row) {
|
|
printFailure("Invoice row not found after update");
|
|
exit;
|
|
}
|
|
|
|
$passengerId = $row['passengerID'];
|
|
$amt = floatval($row['amount']);
|
|
|
|
// 1) Bonus
|
|
$finalAmount = calculateBonus($amt);
|
|
|
|
// 2) Generate payment token (للراكب)
|
|
$token = generatePaymentToken($passengerId, $finalAmount);
|
|
|
|
// 3) Add to Passenger Wallet
|
|
$walletResult = addToPassengerWallet($passengerId, $finalAmount, $token);
|
|
|
|
// 4) Add to Siro Wallet (محاسبي) بطريقة الدفع المستخلصة من sender
|
|
$token2 = generatePaymentToken($passengerId, $amt);
|
|
$siroWalletResult = addToSiroWallet($passengerId, $amt, $paymentMethod, $token2);
|
|
|
|
printSuccess([
|
|
"message" => "Passenger income processed",
|
|
"invoice_id" => $invoiceId,
|
|
"passenger_id" => $passengerId,
|
|
"amount" => $amt,
|
|
"final_amount" => $finalAmount,
|
|
"payment_method" => $paymentMethod,
|
|
"wallet" => $walletResult,
|
|
"siroWallet" => $siroWalletResult,
|
|
"sender" => $sender
|
|
]);
|
|
exit;
|
|
|
|
} catch (PDOException $e) {
|
|
printFailure("DB income error: " . $e->getMessage());
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/* غير مدعوم الآن (payout أو مدخلات ناقصة) */
|
|
printFailure([
|
|
"status" => "ignored",
|
|
"message" => "Unsupported or incomplete transaction",
|
|
"type" => $trxType,
|
|
"sender" => $sender
|
|
]);
|
|
exit;
|
|
|
|
/* ===== Helpers — تعتمد على BASE_URL الموجودة عندك ===== */
|
|
|
|
function calculateBonus($amount) {
|
|
if ($amount == 20000) return 20500;
|
|
if ($amount == 40000) return 42500;
|
|
if ($amount == 100000) return 104000;
|
|
return $amount;
|
|
}
|
|
|
|
function generatePaymentToken($passengerId, $amount) {
|
|
if (!defined('BASE_URL')) return null; // نعتمد وجودها لديك
|
|
$url = rtrim(BASE_URL, '/') . "/passengerWallet/addPaymentTokenPassenger.php";
|
|
$post = ['passengerId' => $passengerId, 'amount' => $amount];
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
|
|
$resp = curl_exec($ch);
|
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($code != 200 || !$resp) return null;
|
|
$j = json_decode($resp, true);
|
|
return $j['message'] ?? null;
|
|
}
|
|
|
|
function addToPassengerWallet($passengerId, $amount, $token) {
|
|
if (!defined('BASE_URL')) return null;
|
|
$url = rtrim(BASE_URL, '/') . "/passengerWallet/add.php";
|
|
$post = ['passenger_id' => $passengerId, 'balance' => $amount, 'token' => $token];
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
|
|
$resp = curl_exec($ch);
|
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($code != 200 || !$resp) return null;
|
|
return json_decode($resp, true);
|
|
}
|
|
|
|
function addToSiroWallet($passengerId, $amount, $paymentMethod, $token) {
|
|
if (!defined('BASE_URL')) return null;
|
|
$url = rtrim(BASE_URL, '/') . "/siroWallet/add.php";
|
|
$post = [
|
|
'amount' => $amount,
|
|
'paymentMethod' => $paymentMethod, // من sender
|
|
'passengerId' => $passengerId,
|
|
'token' => $token,
|
|
'driverId' => 'passenger'
|
|
];
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
|
|
$resp = curl_exec($ch);
|
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($code != 200 || !$resp) return null;
|
|
return json_decode($resp, true);
|
|
}
|