Files
Siro/walletintaleq.intaleq.xyz/v2/main/sms_webhook/process_passenger_sms_payment.php
2026-06-16 22:44:11 +03:00

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);
}