Update: 2026-06-11 19:26:42

This commit is contained in:
Hamza-Ayed
2026-06-11 19:26:42 +03:00
parent 727068b668
commit b87477bec4
371 changed files with 67 additions and 14257 deletions

View File

@@ -1,237 +0,0 @@
<?php
// /v1/main/ride/syriatel/driver/confirm_payment.php
// يعتمد على connect.php و syriatel_token_handler.php فقط
include_once "../../../connect.php";
include_once "./syriatel_token_handler.php";
header('Content-Type: application/json; charset=utf-8');
// ================== Helpers (طباعة/لوج) ==================
if (!function_exists('printSuccess')) {
function printSuccess($data = null, $message = "success") {
echo json_encode(["status" => "success", "message" => $message, "data" => $data], JSON_UNESCAPED_UNICODE);
exit;
}
}
if (!function_exists('printFailure')) {
function printFailure($message = "failure", $code = null) {
$resp = ["status" => "failure", "message" => $message];
if ($code !== null) $resp["code"] = $code;
echo json_encode($resp, JSON_UNESCAPED_UNICODE);
exit;
}
}
define("WALLET_LOG", __DIR__ . "/../logs/payment_verification.log");
function wlog($step, $msg, $data = null) {
$dir = dirname(WALLET_LOG);
if (!is_dir($dir)) { @mkdir($dir, 0755, true); }
$line = "[".date('Y-m-d H:i:s')."] STEP {$step}: {$msg}";
if ($data !== null) $line .= " | Data: ".json_encode($data, JSON_UNESCAPED_UNICODE);
file_put_contents(WALLET_LOG, $line.PHP_EOL, FILE_APPEND);
}
// ================== منطق التوكن/المعرف ==================
function generateToken(PDO $con, string $driverId, float $amount): ?string {
// secretKey يُفترض قادم من connect/env
global $secretKey;
$data = $driverId.$amount.time().($secretKey ?? 'default_secret');
$hash = hash('sha256', $data);
$rand = bin2hex(random_bytes(16));
$token = substr($hash.$rand, 0, 64);
$stmt = $con->prepare("INSERT INTO payment_tokens (token, driverID, dateCreated, amount)
VALUES (:t, :d, NOW(), :a)");
$stmt->execute([':t'=>$token, ':d'=>$driverId, ':a'=>$amount]);
return $stmt->rowCount() ? $token : null;
}
function generatePaymentID(PDO $con, string $driverId, float $amount, string $method): ?string {
$stmt = $con->prepare("INSERT INTO paymentsDriverPoints (amount, payment_method, driverID)
VALUES (:a, :m, :d)");
$stmt->execute([':a'=>$amount, ':m'=>$method, ':d'=>$driverId]);
return $stmt->rowCount() ? $con->lastInsertId() : null;
}
// ================== منطق إنهاء الدفع (مضمَّن) ==================
function finalizeWalletPaymentInline(PDO $con, string $orderRef): void {
// نقفل الصف لمنع السباقات
$stmt = $con->prepare("SELECT * FROM paymentsLogSyriaDriver
WHERE order_ref = :r LIMIT 1 FOR UPDATE");
$stmt->execute([':r'=>$orderRef]);
$payment = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$payment) {
wlog("FINALIZE", "Payment row not found", ['orderRef'=>$orderRef]);
throw new RuntimeException("Payment not found.");
}
// نتأكد من نجاح مزود الدفع
if ((int)$payment['status'] !== 1) {
wlog("FINALIZE", "Payment not completed yet", ['orderRef'=>$orderRef, 'status'=>$payment['status']]);
throw new RuntimeException("Payment not completed.");
}
// حارس التكرار: إذا تمّت معالجة المحفظة سابقاً لا نكرر
if (!empty($payment['processed_wallet']) && (int)$payment['processed_wallet'] === 1) {
wlog("FINALIZE", "Already processed_wallet=1, skip.", ['orderRef'=>$orderRef]);
return; // لا نرمي استثناء؛ العملية سبق احتسابها
}
$driverId = $payment['user_id']; // This is now correctly handled as a string
$originalAmount = (float)$payment['amount'];
$paymentMethod = $payment['payment_method'] ?: 'ecash';
// البونص
$bonusAmount = match ((int)$originalAmount) {
100 => 100.0,
200 => 210.0,
400 => 450.0,
1000 => 1100.0,
default => $originalAmount,
};
// تنفيذ ككل داخل معاملة
$con->beginTransaction();
try {
// توليد التوكنات/المعرف
$tokenDriver = generateToken($con, $driverId, $bonusAmount);
if (!$tokenDriver) throw new RuntimeException("Failed to generate driver token");
$tokenSefer = generateToken($con, $driverId, $originalAmount);
if (!$tokenSefer) throw new RuntimeException("Failed to generate sefer token");
$paymentID = generatePaymentID($con, $driverId, $bonusAmount, $paymentMethod);
if (!$paymentID) throw new RuntimeException("Failed to create payment ID");
// driverWallet
$q = $con->prepare("INSERT INTO driverWallet (driverID, paymentID, amount, paymentMethod)
VALUES (:d, :r, :a, :m)");
$q->execute([
':d'=>$driverId, ':a'=>$bonusAmount,
':m'=>$paymentMethod, ':r'=>$orderRef
]);
if ($q->rowCount() === 0) throw new RuntimeException("Insert driverWallet failed");
// وسم التوكن كمستخدم
$con->prepare("UPDATE payment_tokens SET isUsed = 1 WHERE token = :t")->execute([':t'=>$tokenDriver]);
// seferWallet
$q2 = $con->prepare("INSERT INTO seferWallet (driverId, passengerId, amount, paymentMethod, token, createdAt)
VALUES (:d, :p, :a, :m, :t, CURRENT_TIMESTAMP)");
$q2->execute([
':d'=>$driverId, ':p'=>'driver', ':a'=>$originalAmount,
':m'=>$paymentMethod, ':t'=>$tokenSefer
]);
if ($q2->rowCount() === 0) throw new RuntimeException("Insert seferWallet failed");
$con->prepare("UPDATE payment_tokens SET isUsed = 1 WHERE token = :t")->execute([':t'=>$tokenSefer]);
// تأشير السجل كمنتهٍ للمحفظة
$con->prepare("UPDATE paymentsLogSyriaDriver
SET processed_wallet = 1, updated_at = NOW()
WHERE order_ref = :r")->execute([':r'=>$orderRef]);
$con->commit();
wlog("FINALIZE", "Wallets updated successfully", ['orderRef'=>$orderRef, 'driverId'=>$driverId]);
} catch (Throwable $e) {
$con->rollBack();
wlog("FINALIZE", "Exception: ".$e->getMessage(), ['orderRef'=>$orderRef]);
throw $e;
}
}
// ================== مدخل تأكيد الدفع ==================
$transactionID = filterRequest('transactionID');
$otp = filterRequest('otp');
error_log("Syriatel Confirm: Request for transaction {$transactionID}");
if (!$transactionID || !$otp) {
printFailure("Missing transaction ID or OTP.");
}
// بيئة
$baseUrl = rtrim((string)getenv('SYRIATEL_API_BASE_URL'), '/');
$merchantMSISDN = (string)getenv('SYRIATEL_MERCHANT_MSISDN');
if ($baseUrl === '' || $merchantMSISDN === '') {
error_log("Syriatel Confirm: Missing SYRIATEL envs");
printFailure("Server configuration error.");
}
try {
// 1) Auth token
$token = function_exists('GetSerialToken') ? GetSerialToken() : getSyriatelToken();
if (!$token) { printFailure("Could not authenticate with the payment provider."); }
// 2) Call provider
$body = [
"OTP" => $otp,
"merchantMSISDN" => $merchantMSISDN,
"transactionID" => $transactionID,
"token" => $token
];
$url = "{$baseUrl}/ePaymentExternalModule/paymentConfirmation";
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($body, JSON_UNESCAPED_UNICODE),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Accept: application/json",
"User-Agent: Mozilla/5.0",
],
CURLOPT_CONNECTTIMEOUT => 8,
CURLOPT_TIMEOUT => 40,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
]);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
error_log("Syriatel Confirm: HTTP {$httpCode} - ".substr((string)$response, 0, 300));
if ($errno) { printFailure("Payment gateway communication error.", $errno); }
if ($httpCode !== 200 || !$response) { printFailure("Payment gateway communication error (HTTP {$httpCode})."); }
$responseData = json_decode($response, true);
if (!is_array($responseData)) { printFailure("Invalid provider response."); }
$ok = (isset($responseData['errorDesc']) && $responseData['errorDesc'] === "Success");
if ($ok) {
// نحدّث حالة الدفع، ونُتم المحفظة بشكل آمن داخل نفس الطلب
$con->prepare("UPDATE paymentsLogSyriaDriver
SET status = 1, updated_at = NOW()
WHERE order_ref = :r")->execute([':r'=>$transactionID]);
// إنهاء المحفظة (داخلية)
$walletOk = true; $walletMsg = null;
try {
finalizeWalletPaymentInline($con, $transactionID);
} catch (Throwable $ex) {
$walletOk = false; $walletMsg = $ex->getMessage();
}
$payload = [
'message' => 'Payment confirmed.',
'transactionID' => $transactionID,
'provider' => $responseData
];
if (!$walletOk && $walletMsg) {
$payload['walletNotice'] = "Payment successful, but wallet update failed: ".$walletMsg;
}
printSuccess($payload);
}
$errorMessage = $responseData['errorDesc'] ?? 'Unknown provider error';
printFailure($errorMessage);
} catch (Throwable $e) {
error_log("Syriatel Confirm: Exception - ".$e->getMessage());
printFailure("An unexpected server error occurred.");
}

View File

@@ -1,127 +0,0 @@
<?php
// wallet/finalize_wallet_payment.php
// تم حذف include_once من هنا لأنه يُفترض أن ملف الاتصال قد تم تحميله بالفعل
// بواسطة الملف الذي يستدعي هذه الدالة (confirm_payment.php).
// include_once "../../../jwtconnect.php";
define("LOG_FILE", __DIR__ . "/../logs/payment_verification.log");
if (!function_exists('logError')) {
function logError($step, $message, $data = null) {
$logDir = dirname(LOG_FILE);
if (!is_dir($logDir)) { mkdir($logDir, 0755, true); }
$logEntry = "[" . date('Y-m-d H:i:s') . "] STEP {$step}: {$message}";
if ($data !== null) { $logEntry .= " | Data: " . json_encode($data, JSON_UNESCAPED_UNICODE); }
file_put_contents(LOG_FILE, $logEntry . PHP_EOL, FILE_APPEND);
}
}
if (!function_exists('generateToken')) {
function generateToken($con, $driverId, $amount): ?string {
global $secretKey;
$data = $driverId . $amount . time() . ($secretKey ?? 'default_secret');
$hash = hash('sha256', $data);
$randomBytes = bin2hex(random_bytes(16));
$token = substr($hash . $randomBytes, 0, 64);
$stmt = $con->prepare("INSERT INTO payment_tokens (token, driverID, dateCreated, amount) VALUES (:token, :driverID, NOW(), :amount)");
$stmt->execute([':token' => $token, ':driverID' => $driverId, ':amount' => $amount]);
return $stmt->rowCount() > 0 ? $token : null;
}
}
if (!function_exists('generatePaymentID')) {
function generatePaymentID($con, $driverId, $amount, $method): ?string {
$stmt = $con->prepare("INSERT INTO paymentsDriverPoints (`amount`, `payment_method`, `driverID`) VALUES (:amount, :method, :driverID)");
$stmt->execute([':driverID' => $driverId, ':amount' => $amount, ':method' => $method]);
return $stmt->rowCount() > 0 ? $con->lastInsertId() : null;
}
}
if (!function_exists('finalizeWalletPayment')) {
function finalizeWalletPayment($con) {
$orderRef = $_GET['orderRef'] ?? null;
if (empty($orderRef)) {
logError("FINALIZE", "Missing orderRef");
return; // لا نستخدم throw هنا لأن الخطأ داخلي
}
// 1. تحقق من الدفع
$stmt = $con->prepare("SELECT * FROM `paymentsLogSyriaDriver` WHERE order_ref = :order_ref AND status = 1 LIMIT 1");
$stmt->execute([':order_ref' => $orderRef]);
$payment = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$payment) {
logError("FINALIZE", "Payment not found or not completed", ['orderRef' => $orderRef]);
return;
}
// [تحسين] استخدام معاملات لضمان سلامة البيانات
$con->beginTransaction();
try {
$driverId = $payment['user_id'];
$originalAmount = floatval($payment['amount']);
$paymentMethod = $payment['payment_method'] ?? 'ecash';
// حساب المكافأة
$bonusAmount = match ((int)$originalAmount) {
100 => 100.0,
200 => 210.0,
400 => 450.0,
1000 => 1100.0,
default => $originalAmount,
};
// إنشاء التوكنات
$tokenDriver = generateToken($con, $driverId, $bonusAmount);
if (!$tokenDriver) throw new Exception('Failed to generate driver token');
$tokenSefer = generateToken($con, $driverId, $originalAmount);
if (!$tokenSefer) throw new Exception('Failed to generate sefer token');
$paymentID = generatePaymentID($con, $driverId, $bonusAmount, $paymentMethod);
if (!$paymentID) throw new Exception('Failed to generate payment ID');
// driverWallet
$insertDriver = $con->prepare("INSERT INTO driverWallet (driverID, paymentID, amount, paymentMethod) VALUES (:driverID, :paymentID, :amount, :paymentMethod)");
$insertDriver->execute([
':driverID' => $driverId,
':paymentID' => $paymentID,
':amount' => $bonusAmount,
':paymentMethod' => $paymentMethod
]);
if ($insertDriver->rowCount() === 0) throw new Exception('Insert to driverWallet failed');
$con->prepare("UPDATE payment_tokens SET isUsed = TRUE WHERE token = :token")->execute([':token' => $tokenDriver]);
// seferWallet
$insertSefer = $con->prepare("INSERT INTO seferWallet (driverId, passengerId, amount, paymentMethod, token, createdAt)
VALUES (:driverId, :passengerId, :amount, :paymentMethod, :token, CURRENT_TIMESTAMP)");
$insertSefer->execute([
':driverId' => $driverId,
':passengerId' => 'driver',
':amount' => $originalAmount,
':paymentMethod' => $paymentMethod,
':token' => $tokenSefer
]);
if ($insertSefer->rowCount() === 0) throw new Exception('Insert to seferWallet failed');
$con->prepare("UPDATE payment_tokens SET isUsed = TRUE WHERE token = :token")->execute([':token' => $tokenSefer]);
// إذا نجحت كل العمليات، قم بتثبيتها في قاعدة البيانات
$con->commit();
logError("FINALIZE", "Wallets updated successfully", ['orderRef' => $orderRef]);
// لا نطبع نجاح هنا، الملف المستدعي هو المسؤول عن إرسال الرد النهائي
} catch (Throwable $e) {
// في حالة حدوث أي خطأ، تراجع عن كل التغييرات
$con->rollBack();
logError("FINALIZE", "Exception during finalization: " . $e->getMessage(), ['orderRef' => $orderRef]);
// نمرر الخطأ للملف الأعلى ليعالجه
throw $e;
}
}
}

View File

@@ -1,141 +0,0 @@
<?php
// /v1/main/ride/syriatel/driver/start_payment.php
include "../../../connect.php";
include_once "./syriatel_token_handler.php";
header('Content-Type: application/json; charset=utf-8');
/** دوال الطباعة (لو موجودة أصلاً في connect.php تجاهل هذه) */
if (!function_exists('printSuccess')) {
function printSuccess($data = null, $message = "success") {
echo json_encode(["status"=>"success","message"=>$message,"data"=>$data], JSON_UNESCAPED_UNICODE); exit;
}
}
if (!function_exists('printFailure')) {
function printFailure($message = "failure", $code = null) {
$resp = ["status"=>"failure","message"=>$message]; if ($code!==null) $resp["code"]=$code;
echo json_encode($resp, JSON_UNESCAPED_UNICODE); exit;
}
}
/** مولّد مرجع الطلب (TransactionID) */
function generate_order_ref(): string {
// مرجع مقروء + فريد: INT-YYYYMMDDHHMMSS-6digits
$ts = date('YmdHis');
$rand = str_pad((string)random_int(0, 999999), 6, '0', STR_PAD_LEFT);
return "INT-$ts-$rand";
}
// --- Input Parameters ---
$amount = filterRequest('amount');
$driverId = filterRequest('driverId');
$phone = filterRequest('phone'); // customerMSISDN
$lang = filterRequest('lang') ?? 'ar';
error_log("Syriatel Start: Request received for driver {$driverId} with amount {$amount}");
if (!$amount || !$driverId || !$phone) {
printFailure("Missing required parameters.");
}
// --- Environment Variables ---
$baseUrl = rtrim((string)getenv('SYRIATEL_API_BASE_URL'), '/');
$merchantMSISDN = (string)getenv('SYRIATEL_MERCHANT_MSISDN');
if ($baseUrl === '' || $merchantMSISDN === '') {
error_log("Syriatel Start: Missing SYRIATEL_API_BASE_URL or SYRIATEL_MERCHANT_MSISDN");
printFailure("Server configuration error.");
}
// --- Logic ---
try {
// 1) Token
$token = getSyriatelToken();
error_log("Syriatel Start: token=" . ($token ? substr($token,0,8).'...' : 'NULL'));
if (!$token) {
printFailure("Could not authenticate with the payment provider.");
}
// 2) Transaction ID + log DB
$transactionID = generate_order_ref();
$stmt = $con->prepare(
"INSERT INTO `paymentsLogSyriaDriver` (user_id, amount, status, order_ref, payment_method, created_at)
VALUES (:user_id, :amount, 0, :order_ref, 'syriatel', NOW())"
);
$stmt->execute([
':user_id' => $driverId,
':amount' => $amount,
':order_ref' => $transactionID
]);
error_log("Syriatel Start: Logged transaction {$transactionID} for driver {$driverId}");
// 3) Payment Request → Syriatel
$body = [
"customerMSISDN" => $phone, // مثال: 09xxxxxxxx (حسب وثيقتهم)
"merchantMSISDN" => $merchantMSISDN, // من env
"amount" => $amount,
"transactionID" => $transactionID,
"token" => $token
];
error_log("Syriatel Start: customerMSISDN {$phone} merchantMSISDN {$merchantMSISDN}");
$url = "{$baseUrl}/ePaymentExternalModule/paymentRequest";
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($body, JSON_UNESCAPED_UNICODE),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"User-Agent: Mozilla/5.0",
"Accept: application/json"
],
CURLOPT_CONNECTTIMEOUT => 8,
CURLOPT_TIMEOUT => 40,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
]);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$errstr = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
error_log("Syriatel Start: paymentRequest HTTP {$httpCode} errno={$errno} resp=" . substr((string)$response,0,300));
if ($errno) {
printFailure("Payment gateway communication error.", $errno);
}
if ($httpCode !== 200) {
printFailure("Payment gateway communication error (HTTP {$httpCode}).");
}
$responseData = json_decode($response, true);
// حسب الدوكيومنت: resultCode = 1 يعني OTP انرسل بنجاح
//errorCode = 0 => Success
if (isset($responseData['errorCode']) && (string)$responseData['errorCode'] === "0") {
printSuccess([
'message' => 'OTP sent successfully.',
'transactionID' => $transactionID,
]);
}
// 2) إذا resultCode = 1 => OTP sent
elseif (isset($responseData['resultCode']) && (int)$responseData['resultCode'] === 1) {
printSuccess([
'message' => 'OTP sent successfully.',
'transactionID' => $transactionID,
]);
}
// 3) أي شيء آخر => فشل
else {
$errorMessage = $responseData['resultDescription']
?? $responseData['errorDesc']
?? 'Failed to initiate payment.';
printFailure($errorMessage);
}
} catch (Throwable $e) {
error_log("Syriatel Start: Exception - " . $e->getMessage());
printFailure("An unexpected server error occurred.");
}

View File

@@ -1,74 +0,0 @@
<?php // syriatel_token_handler
function getSyriatelToken(): ?string {
// اضبط البيئة: prod أو stage (افتراضي prod)
$env = getenv("SYRIATEL_ENV") ?: "prod";
// Base URLs من Postman
$baseStage = "https://merchants.syriatel.sy:1443/ePayment_external_Json_test/rs/ePaymentExternalModule";
$baseProd = "https://merchants.syriatel.sy:1443/ePayment_external_Json/rs/ePaymentExternalModule";
$baseUrl = ($env === "stage") ? $baseStage : $baseProd;
$url = $baseUrl . "/getToken";
// ⚠️ لا تضع قيم افتراضية حساسة Hardcoded
$username = getenv("SYRIATEL_USERNAME");
$password = getenv("SYRIATEL_PASSWORD");
if (!$username || !$password) {
error_log("[GetSyriatelToken] Missing credentials in ENV");
printFailure("Payment provider credentials are missing.");
return null;
}
error_log("[GetSyriatelToken] Env={$env} | URL={$url} | user={$username}");
$payload = [
"username" => $username,
"password" => $password
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"User-Agent: Mozilla/5.0",
],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
CURLOPT_CONNECTTIMEOUT => 8,
CURLOPT_TIMEOUT => 40,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
]);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$errstr = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($errno) {
error_log("[GetSyriatelToken] cURL error {$errno}: {$errstr}");
printFailure("Could not connect to the payment provider.", $errno);
return null;
}
if ($httpCode !== 200 || !$response) {
error_log("[GetSyriatelToken] HTTP {$httpCode} | Empty/invalid response");
printFailure("Could not authenticate with the payment provider.");
return null;
}
$data = json_decode($response, true);
$token = $data["token"] ?? null;
if (!$token) {
error_log("[GetSyriatelToken] Token not found in response: " . substr($response, 0, 300));
printFailure("Could not authenticate with the payment provider.");
return null;
}
error_log("[GetSyriatelToken] Token received successfully");
return $token;
}