Update: 2026-06-11 19:26:42
This commit is contained in:
@@ -1,125 +0,0 @@
|
||||
<?php
|
||||
// /v1/main/ride/mtn/driver/confirm_payment.php
|
||||
include "../../../connect.php";
|
||||
|
||||
// It's better to use __DIR__ for reliable file path resolution.
|
||||
// Assuming your private_key.pem is in the same directory as this script.
|
||||
$privateKeyPath = __DIR__ . "/private_key.pem";
|
||||
|
||||
$baseUrl = rtrim(getenv('MTN_API_BASE_URL'), '/');
|
||||
$terminalId = getenv('MTN_TERMINAL_ID');
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents($privateKeyPath));
|
||||
|
||||
$invoice = filterRequest('invoiceNumber');
|
||||
$phone = filterRequest('phone');
|
||||
$guid = filterRequest('guid');
|
||||
$operationNumber = filterRequest('operationNumber');
|
||||
$code = filterRequest('otp'); // The OTP
|
||||
|
||||
error_log("MTN Confirm (Driver): Start request for invoice={$invoice}, phone={$phone}, guid={$guid}, opNum={$operationNumber}");
|
||||
|
||||
if (!$invoice || !$phone || !$guid || !$operationNumber || !$code) {
|
||||
error_log("MTN Confirm (Driver): Missing parameters");
|
||||
printFailure("Missing parameters.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Encrypt the code
|
||||
$hashBin = hash('sha256', $code, true);
|
||||
$codeB64 = base64_encode($hashBin);
|
||||
|
||||
$body = [
|
||||
'Invoice' => intval($invoice),
|
||||
'Phone' => $phone,
|
||||
'Guid' => $guid,
|
||||
'OperationNumber' => intval($operationNumber),
|
||||
'Code' => $codeB64
|
||||
];
|
||||
$bodyJson = json_encode($body, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
error_log("MTN Confirm (Driver): Prepared body JSON: " . $bodyJson);
|
||||
|
||||
// Generate signature
|
||||
$signResult = openssl_sign($bodyJson, $sig, $privateKey, OPENSSL_ALGO_SHA256);
|
||||
if (!$signResult) {
|
||||
error_log("MTN Confirm (Driver): Failed to generate signature");
|
||||
printFailure("Signature error.");
|
||||
exit;
|
||||
}
|
||||
$xSignature = base64_encode($sig);
|
||||
error_log("MTN Confirm (Driver): Generated signature");
|
||||
|
||||
// Send the request
|
||||
$ch = curl_init("{$baseUrl}/pos_web/payment_phone/confirm");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $bodyJson,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Content-Type: application/json",
|
||||
"Request-Name: pos_web/payment_phone/confirm",
|
||||
"Subject: {$terminalId}",
|
||||
"X-Signature: {$xSignature}"
|
||||
]
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
error_log("MTN Confirm (Driver): HTTP $httpCode - Response: $response");
|
||||
if ($curlError) {
|
||||
error_log("MTN Confirm (Driver): cURL error - $curlError");
|
||||
}
|
||||
|
||||
// --- SOLUTION IMPLEMENTED HERE ---
|
||||
// 1. Decode the response from MTN to check its contents.
|
||||
$responseData = json_decode($response, true) ?: [];
|
||||
|
||||
// 2. First, check for network/gateway level failure.
|
||||
if ($httpCode !== 200) {
|
||||
error_log("MTN Confirm (Driver): HTTP failure for invoice {$invoice}. Code: {$httpCode}");
|
||||
// Use printFailure to send a structured error to Flutter
|
||||
printFailure(['message' => 'MTN Gateway Error', 'http' => $httpCode, 'details' => $responseData]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 3. Now, check for business-logic failure (like "Balance not enough").
|
||||
$errno = $responseData['Errno'] ?? -1; // Default to an error state if Errno is missing
|
||||
if ($errno !== 0) {
|
||||
$apiError = $responseData['Error'] ?? 'Unknown MTN API Error';
|
||||
error_log("MTN Confirm (Driver): Business failure for invoice {$invoice}. Errno: {$errno}, Reason: {$apiError}");
|
||||
// This now sends the specific error message in the format Flutter expects!
|
||||
printFailure(['message' => $apiError, 'errno' => $errno, 'details' => $responseData]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- ONLY PROCEED TO DATABASE ON FULL SUCCESS (HTTP 200 AND Errno 0) ---
|
||||
try {
|
||||
$stmt = $con->prepare(
|
||||
"UPDATE `paymentsLogSyriaDriver` SET status = 1, updated_at = NOW()
|
||||
WHERE order_ref = :inv"
|
||||
);
|
||||
$stmt->execute([':inv' => $invoice]);
|
||||
error_log("MTN Confirm (Driver): Payment updated successfully in DB for invoice={$invoice}");
|
||||
|
||||
// The file path correction from before remains important.
|
||||
include_once __DIR__ . '/finalize_wallet_payment.php';
|
||||
|
||||
// Call the wallet finalization logic
|
||||
if (function_exists('finalizeWalletPayment')) {
|
||||
$_GET['orderRef'] = $invoice;
|
||||
finalizeWalletPayment($con);
|
||||
} else {
|
||||
error_log("MTN Confirm (Driver): FATAL - finalizeWalletPayment() function does not exist after include.");
|
||||
}
|
||||
|
||||
// On success, send a success response to Flutter
|
||||
printSuccess(['message' => 'Payment confirmed successfully', 'details' => $responseData]);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_log("MTN Confirm (Driver): DB update error - " . $e->getMessage());
|
||||
printFailure("Database processing error.");
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
// wallet/finalize_wallet_payment.php
|
||||
include_once "../../../jwtconnect.php";
|
||||
|
||||
define("LOG_FILE", "../logs/payment_verification.log");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function finalizeWalletPayment($con) {
|
||||
$orderRef = $_GET['orderRef'] ?? null;
|
||||
if (empty($orderRef)) {
|
||||
logError("FINALIZE", "Missing orderRef");
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
try {
|
||||
$driverId = $payment['user_id'];
|
||||
$originalAmount = floatval($payment['amount']);
|
||||
$paymentMethod = $payment['payment_method'] ?? 'ecash';
|
||||
|
||||
// حساب المكافأة
|
||||
$bonusAmount = match ((int)$originalAmount) {
|
||||
10000 => 10000.0,
|
||||
20000 => 21000.0,
|
||||
40000 => 45000.0,
|
||||
100000 => 110000.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
|
||||
]);
|
||||
$con->prepare("UPDATE payment_tokens SET isUsed = TRUE WHERE token = :token")->execute([':token' => $tokenSefer]);
|
||||
|
||||
logError("FINALIZE", "Wallets updated successfully", ['orderRef' => $orderRef]);
|
||||
printSuccess("FINALIZE", "Wallets updated successfully");
|
||||
} catch (Throwable $e) {
|
||||
logError("FINALIZE", "Exception during finalization: " . $e->getMessage(), ['orderRef' => $orderRef]);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
// File: generate_keys.php
|
||||
// الوظيفة: إنشاء زوج المفاتيح (العام والخاص) لمرة واحدة فقط
|
||||
|
||||
// إعدادات لتوليد المفتاح
|
||||
$config = [
|
||||
"digest_alg" => "sha256",
|
||||
"private_key_bits" => 1024,
|
||||
"private_key_type" => OPENSSL_KEYTYPE_RSA,
|
||||
];
|
||||
|
||||
// إنشاء زوج المفاتيح
|
||||
$res = openssl_pkey_new($config);
|
||||
|
||||
if (!$res) {
|
||||
die('Failed to generate new private key. Error: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
// استخراج المفتاح الخاص
|
||||
openssl_pkey_export($res, $private_key);
|
||||
|
||||
// استخراج المفتاح العام
|
||||
$public_key_details = openssl_pkey_get_details($res);
|
||||
$public_key = $public_key_details["key"];
|
||||
|
||||
// حفظ المفاتيح في ملفات
|
||||
file_put_contents('private_key.pem', $private_key);
|
||||
file_put_contents('public_key.pem', $public_key);
|
||||
|
||||
echo "<h1>Keys Generated Successfully!</h1>";
|
||||
echo "<h2>Private Key (saved to private_key.pem):</h2>";
|
||||
echo "<pre>" . htmlspecialchars($private_key) . "</pre>";
|
||||
echo "<h2>Public Key (saved to public_key.pem):</h2>";
|
||||
echo "<pre>" . htmlspecialchars($public_key) . "</pre>";
|
||||
|
||||
// --- تحضير المفتاح العام لعملية التفعيل ---
|
||||
// إزالة الهيدر والفوتر والأسطر الجديدة كما هو مطلوب
|
||||
$formatted_public_key = str_replace("-----BEGIN PUBLIC KEY-----", "", $public_key);
|
||||
$formatted_public_key = str_replace("-----END PUBLIC KEY-----", "", $formatted_public_key);
|
||||
$formatted_public_key = preg_replace("/\s+/", "", $formatted_public_key);
|
||||
|
||||
|
||||
echo "<h2>Formatted Public Key (for Terminal Activation):</h2>";
|
||||
echo "<p><strong>انسخ هذا المفتاح لاستخدامه في خطوة تفعيل الجهاز (activate_terminal.php)</strong></p>";
|
||||
echo "<textarea rows='5' cols='80' readonly>" . htmlspecialchars($formatted_public_key) . "</textarea>";
|
||||
|
||||
?>
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
// /v1/main/ride/mtn/passenger/initiate_payment.php
|
||||
include "../../../connect.php";
|
||||
|
||||
$baseUrl = rtrim(getenv('MTN_API_BASE_URL'), '/');
|
||||
$terminalId = getenv('MTN_TERMINAL_ID');
|
||||
$privateKeyPem = getenv('MTN_PRIVATE_KEY');
|
||||
|
||||
$invoice = filterRequest('invoice'); // رقم الفاتورة
|
||||
$phone = filterRequest('phone'); // رقم الزبون
|
||||
$guid = uniqid('mtn_');
|
||||
|
||||
if (!$invoice || !$phone) {
|
||||
printFailure("Missing invoice or phone.");
|
||||
exit;
|
||||
}
|
||||
|
||||
$body = json_encode([
|
||||
'Invoice' => intval($invoice),
|
||||
'Phone' => $phone,
|
||||
'Guid' => $guid
|
||||
], JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$hash = hash('sha256', $body, true);
|
||||
openssl_sign($hash, $sig, $privateKeyPem, OPENSSL_ALGO_SHA256);
|
||||
$xSignature = base64_encode($sig);
|
||||
|
||||
$ch = curl_init("{$baseUrl}/pos_web/payment_phone/initiate");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $body,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Content-Type: application/json",
|
||||
"Request-Name: pos_web/payment_phone/initiate",
|
||||
"Subject: {$terminalId}",
|
||||
"X-Signature: {$xSignature}"
|
||||
]
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
// سجل المحاولة مع Guid
|
||||
$stmt = $con->prepare(
|
||||
"UPDATE `mtn_payments`
|
||||
SET guid = :guid, status = 3, updated_at = NOW()
|
||||
WHERE invoice = :inv"
|
||||
);
|
||||
$stmt->execute([':guid'=>$guid, ':inv'=>$invoice]);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
http_response_code($httpCode);
|
||||
echo $response;
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
// بيانات التفعيل
|
||||
$terminalId = "9001000000060863";
|
||||
$activationCode = "26164711";
|
||||
$serialNumber = "INTALEQ-001"; // يمكنك تغييره
|
||||
|
||||
// المفتاح العام على سطر واحد — بدون BEGIN/END وبدون أسطر جديدة
|
||||
//$publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNxFbepx2OrpyrNG4+/aAaH3Rjc8dGw6B6vMAfsZzzm4wzoSkrtsr6jfuaMTZRLwxS5h8k1ztLG1HrOmL/NDsiE/7yxaKLAIZyWB/rR9byvPeOCC8QnCd/08kmxNl/l7Akn6qlPwsVpKUUNsr0SkU9lShMAw4OBgQq399jsbkFSwIDAQAB";
|
||||
$publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOhVAdUyxFpVNSyjRndMWEPAN9vJEetMzLbjF9DTn2lPVuRj/Mkwq9wCNhy+tdeX2lIn4K3EkONBvYJubBhxnYOoQuMchPW5vG7VnmpLjZ7TkpM2n9fcMu8u1GkLatLblDI4LTfvn3851+nhpnYlUVkjw5GAhH4XnEpveIjqDhzQIDAQAB";
|
||||
// جسم الطلب
|
||||
$body = [
|
||||
"Key" => $publicKey,
|
||||
"Secret" => $activationCode,
|
||||
"Serial" => $serialNumber
|
||||
];
|
||||
//$bodyJson = json_encode($body, JSON_UNESCAPED_SLASHES);
|
||||
$bodyJson = trim(stripslashes(json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS)),'"');
|
||||
//$bodyJson = json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
// 1. توليد هاش SHA256 للـ JSON
|
||||
//$bodyHash = hash('sha256', $bodyJson, true);
|
||||
|
||||
// 2. تحميل المفتاح الخاص للتوقيع
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents("private_key.pem")); // تأكد من وجود هذا الملف بجانب السكربت
|
||||
|
||||
// 3. توقيع الهاش
|
||||
openssl_sign($bodyJson, $signature, $privateKey, OPENSSL_ALGO_SHA256);
|
||||
|
||||
// 4. تحويل التوقيع إلى Base64
|
||||
$xSignature = base64_encode($signature);
|
||||
|
||||
// 5. إرسال الطلب
|
||||
$headers = [
|
||||
"Content-Type: application/json",
|
||||
"Accept-Language: en",
|
||||
"Request-Name: pos_web/pos/activate",
|
||||
"Subject: $terminalId",
|
||||
"X-Signature: $xSignature"
|
||||
];
|
||||
|
||||
$ch = curl_init("https://cashmobile.mtnsyr.com:9000");
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyJson);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
// ✅ النتيجة
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
"httpCode" => $httpCode,
|
||||
"response" => json_decode($response, true),
|
||||
"sentBody" => $body,
|
||||
]);
|
||||
@@ -1,129 +0,0 @@
|
||||
<?php
|
||||
include "../../../connect.php";
|
||||
date_default_timezone_set("Asia/Damascus");
|
||||
|
||||
// ========== إعدادات MTN ==========
|
||||
$terminalId = "9001000000060863";
|
||||
$currencyCode = 760;
|
||||
$sessionNumber = 0;
|
||||
$ttl = 15;
|
||||
|
||||
// ====== استقبال البيانات من فلاتر ======
|
||||
$amount = filterRequest("amount");
|
||||
$passengerId = filterRequest("passengerId");
|
||||
$phone = filterRequest("phone");
|
||||
|
||||
// ✅ Log مبدئي
|
||||
error_log("🚦 START | passengerId: $passengerId | phone: $phone | amount: $amount");
|
||||
|
||||
// تحقق من المدخلات
|
||||
if (empty($amount) || empty($passengerId) || empty($phone) || $amount <= 0) {
|
||||
error_log("❌ Invalid input: amount=$amount, passengerId=$passengerId, phone=$phone");
|
||||
printFailure("بيانات الدفع غير كاملة أو غير صالحة.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// ====== توليد invoiceNumber و GUID ======
|
||||
$invoiceNumber = mt_rand(10000000000, 99999999999);
|
||||
//$invoiceNumber = "MTN_" . $passengerId . "_" . time();
|
||||
$guid = uniqid("mtn_");
|
||||
error_log("🧾 Generated Invoice: $invoiceNumber");
|
||||
error_log("🧭 Generated GUID: $guid");
|
||||
|
||||
// ====== 1. إنشاء الفاتورة ======
|
||||
$createInvoiceBody = [
|
||||
"Amount" => intval($amount * 100),
|
||||
"Invoice" => $invoiceNumber,
|
||||
"Session" => $sessionNumber,
|
||||
"TTL" => $ttl
|
||||
];
|
||||
error_log("📦 Create Invoice Body: " . json_encode($createInvoiceBody, JSON_UNESCAPED_UNICODE));
|
||||
$invoiceResponse = sendMtnApiRequest("pos_web/invoice/create", $terminalId, $createInvoiceBody);
|
||||
error_log("📥 Create Invoice Response: " . json_encode($invoiceResponse, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
if (!$invoiceResponse || isset($invoiceResponse['Errno']) && $invoiceResponse['Errno'] != 0) {
|
||||
error_log("❌ Failed to create invoice. Error: " . json_encode($invoiceResponse));
|
||||
printFailure("فشل إنشاء الفاتورة عبر MTN.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// ====== 2. بدء الدفع ======
|
||||
$initiateBody = [
|
||||
"Invoice" => $invoiceNumber,
|
||||
"Phone" => $phone,
|
||||
"Guid" => $guid
|
||||
];
|
||||
error_log("📤 body initiateBody: $initiateBody");
|
||||
error_log("📦 Initiate Payment Body: " . json_encode($initiateBody, JSON_UNESCAPED_UNICODE));
|
||||
$initiateResponse = sendMtnApiRequest("pos_web/payment_phone/initiate", $terminalId, $initiateBody);
|
||||
error_log("📥 Initiate Response: " . json_encode($initiateResponse, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
if (!$initiateResponse || !isset($initiateResponse['OperationNumber'])) {
|
||||
error_log("❌ Failed to initiate payment.");
|
||||
printFailure($initiateResponse);
|
||||
exit;
|
||||
}
|
||||
|
||||
$operationNumber = $initiateResponse['OperationNumber'];
|
||||
|
||||
// ====== 3. تسجيل العملية ======
|
||||
try {
|
||||
$stmt = $con->prepare("INSERT INTO `paymentsLogSyriaDriver`
|
||||
(`user_id`, `amount`, `status`, `order_ref`, `payment_method`, `created_at`)
|
||||
VALUES (?, ?, 2, ?, 'mtn', NOW())");
|
||||
$stmt->execute([$passengerId, $amount, $invoiceNumber]);
|
||||
error_log("✅ DB Log Inserted.");
|
||||
} catch (PDOException $e) {
|
||||
error_log("❌ DB ERROR: " . $e->getMessage());
|
||||
printFailure("فشل في تسجيل العملية.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// ====== 4. نجاح
|
||||
error_log("✅ Payment initiation successful.");
|
||||
printSuccess([
|
||||
"invoiceNumber" => $invoiceNumber,
|
||||
"operationNumber" => $operationNumber,
|
||||
"guid" => $guid
|
||||
]);
|
||||
|
||||
|
||||
// ====== دالة إرسال الطلب =====================
|
||||
function sendMtnApiRequest($requestName, $terminalId, $body)
|
||||
{
|
||||
$apiUrl = "https://cashmobile.mtnsyr.com:9000";
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents("private_key.pem"));
|
||||
|
||||
// ✅ تحويل الـ body إلى JSON بدون فراغات أو أسطر
|
||||
$bodyJson = trim(stripslashes(json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS)), '"');
|
||||
//$bodyJson = json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
// ✅ توليد التوقيع
|
||||
// $bodyHash = hash('sha256', $bodyJson, true);
|
||||
error_log("📤 body before JSON: $bodyJson");
|
||||
openssl_sign($bodyJson, $signature, $privateKey, OPENSSL_ALGO_SHA256);
|
||||
$xSignature = base64_encode($signature);
|
||||
error_log("📤 body xSignature: $xSignature");
|
||||
// ✅ رؤوس الطلب
|
||||
$headers = [
|
||||
"Content-Type: application/json",
|
||||
"Accept-Language: en",
|
||||
"Request-Name: $requestName",
|
||||
"Subject: $terminalId",
|
||||
"X-Signature: $xSignature"
|
||||
];
|
||||
|
||||
$ch = curl_init($apiUrl);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyJson);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
// ✅ لوق داخلي
|
||||
error_log("🔐 Signature for $requestName: $xSignature");
|
||||
error_log("📤 Sent JSON: $bodyJson");
|
||||
|
||||
curl_close($ch);
|
||||
return json_decode($response, true);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXwIBAAKBgQDOhVAdUyxFpVNSyjRndMWEPAN9vJEetMzLbjF9DTn2lPVuRj/M
|
||||
kwq9wCNhy+tdeX2lIn4K3EkONBvYJubBhxnYOoQuMchPW5vG7VnmpLjZ7TkpM2n9
|
||||
fcMu8u1GkLatLblDI4LTfvn3851+nhpnYlUVkjw5GAhH4XnEpveIjqDhzQIDAQAB
|
||||
AoGBALRcAvqJT8nHN7y+8QNFHNZ+XwIpc4egmJY1Ny0iJvPtZWaYHVG5PRE4Qu4+
|
||||
29+3oX5dYDx146tu4L5mQvLS3ULBsvxaUZt2lT/vxkQzI9pNfXw584WvIrbtxQod
|
||||
ILvBcnamwQa9hEOIFZVyZ/hzkzUcMO6cAXqvsfqqPgJhm7PBAkEA+xgE9CUOLDFl
|
||||
vLePQKGcHIUOsPLr16qNEgGhTW7Km3OMMqoB2f7t67xOHGqK6tnANRM4Sk6IModI
|
||||
wbZuVh4jMQJBANKOVmIdDLNffZVHp90SDRG7/YdK2R5ob361CIkcUzjh927Wfs5W
|
||||
A/WroB7eJ7pWiq2BMaj/xq65nYaCOldvaV0CQQDm12c+eY61DFjnDa6ykaEvCxi9
|
||||
jydJp+93vW3o/VFhZvJeZbO8EcX0MrNxJnY+gSBW6yuWDOrj4UH/bVO08pIRAkEA
|
||||
lH3TiBAqo9nlTEEjrnILi4VD0IVFx/8pGnf71A6I1qXuBVn6RfQ9iKWIIBzWccCU
|
||||
vrZNWn1AFntLD9CJ6p3k9QJBAMbSQ9CoXWlOLJRduV15ER1ZyE/inVd4jIvtjAgz
|
||||
b7QaM62Ecxl3D8EI/LTSZV9Oa8D/62cJeMsflVa7gpavL70=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,6 +0,0 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqBQZEJXWCQwPsPzBM70M3TjyU
|
||||
5vwCZWoEtUomR9Qu+dEQaa0Hniz6JY8+goCxfMYuZQw6+kimctA2KqzT2pCsJufN
|
||||
b92pSAMZgb0RSTl2y62oJkJd2WY7dj36AvPEyw6DxCFItvFOu7HGl3LlHQBriiw3
|
||||
jwtuS6DO7gbmAJPU8wIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -1,115 +0,0 @@
|
||||
<?php
|
||||
|
||||
include "../../connect.php";
|
||||
|
||||
// --- 2. استقبال البيانات من الطلب ---
|
||||
$driver_id = filterRequest("driver_id");
|
||||
$driver_name = filterRequest("driver_name");
|
||||
$amount = filterRequest("amount");
|
||||
$wallet_type = filterRequest("wallet_type");
|
||||
$wallet_number = filterRequest("wallet_number");
|
||||
|
||||
// التحقق من أن البيانات الأساسية موجودة
|
||||
if (empty($driver_id) || empty($driver_name) || empty($amount) || empty($wallet_type) || empty($wallet_number)) {
|
||||
printFailure('Missing required fields.');
|
||||
exit();
|
||||
}
|
||||
|
||||
// --- 3. إدراج الطلب في قاعدة البيانات ---
|
||||
try {
|
||||
$sql = "INSERT INTO driver_withdrawal_requests (driver_id, driver_name, amount, wallet_type, wallet_number) VALUES (?, ?, ?, ?, ?)";
|
||||
$stmt = $con->prepare($sql);
|
||||
|
||||
// تنفيذ الاستعلام مع تمرير البيانات
|
||||
$success = $stmt->execute([
|
||||
$driver_id,
|
||||
$driver_name,
|
||||
$amount,
|
||||
$wallet_type,
|
||||
$wallet_number
|
||||
]);
|
||||
|
||||
if ($success) {
|
||||
// --- 4. الحصول على رقم الطلب وإرسال إشعار واتساب ---
|
||||
$transaction_id = $con->lastInsertId(); // الحصول على رقم التعريف الخاص بالطلب الجديد
|
||||
sendWhatsAppNotification($transaction_id, $driver_name, $amount, $wallet_type, $wallet_number);
|
||||
|
||||
// إرسال استجابة نجاح إلى التطبيق
|
||||
printSuccess("Withdrawal request saved and notification sent.");
|
||||
|
||||
} else {
|
||||
printFailure('Failed to save withdrawal request.');
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// التعامل مع أخطاء قاعدة البيانات
|
||||
error_log("Database Error in request_withdrawal.php: " . $e->getMessage());
|
||||
printFailure('A database error occurred.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* دالة لإرسال إشعار إلى خدمة العملاء عبر RaseelPlus API
|
||||
*/
|
||||
function sendWhatsAppNotification($transaction_id, $driver_name, $amount, $wallet_type, $wallet_number) {
|
||||
|
||||
// استخدام متغيرات البيئة (Environment Variables) هو الطريقة الأكثر أماناً لإدارة المعلومات الحساسة
|
||||
// بدلاً من كتابتها مباشرة في الكود.
|
||||
$customer_service_number = getenv('CUSTOMER_SERVICE_WHATSAPP');
|
||||
// $customer_service_number = "9639XXXXXXXX"; // كرقم احتياطي مؤقت
|
||||
|
||||
// نص الرسالة مع إضافة رقم الطلب
|
||||
$messageBody = "طلب سحب جديد (رقم الطلب: #$transaction_id):\n\n" .
|
||||
"اسم السائق: " . $driver_name . "\n" .
|
||||
"المبلغ: " . $amount . " ل.س\n" .
|
||||
"نوع المحفظة: " . $wallet_type . "\n" .
|
||||
"رقم المحفظة: " . $wallet_number;
|
||||
|
||||
// بيانات الطلب (Payload) للـ API
|
||||
$payload = [
|
||||
"number" => $customer_service_number,
|
||||
"type" => "text",
|
||||
"message" => $messageBody,
|
||||
"instance_id" => getenv('instance_idWhatsApp');
|
||||
"access_token" => getenv('access_tokenWhatsApp');
|
||||
];
|
||||
|
||||
// استدعاء الـ API
|
||||
// ملاحظة: لا نتحقق من استجابة الـ API هنا لأن العملية الرئيسية (حفظ الطلب) قد نجحت بالفعل.
|
||||
// يمكن إضافة تسجيل للأخطاء إذا لزم الأمر.
|
||||
callAPI_Withdrawal("POST", "https://raseelplus.com/api/send", json_encode($payload));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* دالة لإجراء استدعاءات API باستخدام cURL
|
||||
*/
|
||||
function callAPI_Withdrawal($method, $url, $data) {
|
||||
$curl = curl_init();
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => $method,
|
||||
CURLOPT_POSTFIELDS => $data,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Content-Type: application/json",
|
||||
"Accept: application/json"
|
||||
],
|
||||
]);
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
curl_close($curl);
|
||||
|
||||
if ($err) {
|
||||
// تسجيل الخطأ في سجلات الخادم للمراجعة لاحقًا
|
||||
error_log("[callAPI_Withdrawal] cURL Error #: " . $err);
|
||||
return null;
|
||||
} else {
|
||||
return json_decode($response);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,169 +0,0 @@
|
||||
<?php
|
||||
// /v1/main/ride/mtn/passenger/confirm_payment.php
|
||||
include "../../../connect.php";
|
||||
|
||||
$baseUrl = rtrim(getenv('MTN_API_BASE_URL'), '/');
|
||||
$terminalId = getenv('MTN_TERMINAL_ID');
|
||||
$privateKeyPem = getenv('MTN_PRIVATE_KEY');
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents("private_key.pem"));
|
||||
$invoice = filterRequest('invoiceNumber');
|
||||
$phone = filterRequest('phone');
|
||||
$guid = filterRequest('guid');
|
||||
$operationNumber = filterRequest('operationNumber');
|
||||
$code = filterRequest('otp'); // الـ OTP
|
||||
|
||||
error_log("MTN Confirm: Start request for invoice={$invoice}, phone={$phone}, guid={$guid}, opNum={$operationNumber}");
|
||||
|
||||
if (!$invoice || !$phone || !$guid || !$operationNumber || !$code) {
|
||||
error_log("MTN Confirm: Missing parameters");
|
||||
printFailure("Missing parameters.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// تشفير الكود
|
||||
$hashBin = hash('sha256', $code, true);
|
||||
$codeB64 = base64_encode($hashBin);
|
||||
|
||||
$body = [
|
||||
'Invoice' => intval($invoice),
|
||||
'Phone' => $phone,
|
||||
'Guid' => $guid,
|
||||
'OperationNumber' => intval($operationNumber),
|
||||
'Code' => $codeB64
|
||||
];
|
||||
$bodyJson = trim(stripslashes(json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS)), '"');
|
||||
|
||||
error_log("MTN Confirm: Prepared body JSON: " . $bodyJson);
|
||||
|
||||
// توليد التوقيع
|
||||
$signResult = openssl_sign($bodyJson, $sig, $privateKey, OPENSSL_ALGO_SHA256);
|
||||
if (!$signResult) {
|
||||
error_log("MTN Confirm: Failed to generate signature");
|
||||
printFailure("Signature error.");
|
||||
exit;
|
||||
}
|
||||
$xSignature = base64_encode($sig);
|
||||
error_log("MTN Confirm: Generated signature");
|
||||
|
||||
// إرسال الطلب
|
||||
$ch = curl_init("{$baseUrl}/pos_web/payment_phone/confirm");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $bodyJson,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Content-Type: application/json",
|
||||
"Request-Name: pos_web/payment_phone/confirm",
|
||||
"Subject: {$terminalId}",
|
||||
"X-Signature: {$xSignature}"
|
||||
]
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
error_log("MTN Confirm: HTTP $httpCode - Response: $response");
|
||||
if ($curlError) {
|
||||
error_log("MTN Confirm: cURL error - $curlError");
|
||||
}
|
||||
|
||||
// تحديث قاعدة البيانات في حال نجاح
|
||||
if ($httpCode === 200) {
|
||||
try {
|
||||
$stmt = $con->prepare(
|
||||
"UPDATE `paymentsLogSyria` SET status = 1, updated_at = NOW()
|
||||
WHERE order_ref = :inv"
|
||||
);
|
||||
$stmt->execute([':inv' => $invoice]);
|
||||
error_log("MTN Confirm: Payment updated successfully in DB for invoice={$invoice}");
|
||||
|
||||
$stmt = $con->prepare("SELECT * FROM paymentsLogSyria WHERE order_ref = :order_ref LIMIT 1");
|
||||
$stmt->execute([':order_ref' => $invoice]);
|
||||
$payment = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($payment) {
|
||||
$userId = $payment['user_id'];
|
||||
$amount = $payment['amount'];
|
||||
$paymentMethod = $payment['payment_method'] ?? 'mtn';
|
||||
|
||||
$finalAmount = calculateBonus($amount);
|
||||
$token = generatePaymentToken($userId, $finalAmount);
|
||||
$walletResult = addToPassengerWallet($userId, $finalAmount, $token);
|
||||
|
||||
$seferToken = generatePaymentToken($userId, $amount);
|
||||
$seferWalletResult = addToSeferWallet($userId, $amount, $paymentMethod, $seferToken);
|
||||
|
||||
printSuccess('MTN Confirm');
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_log("MTN Confirm: DB update error - " . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
error_log("MTN Confirm: Payment failed with HTTP code $httpCode");
|
||||
}
|
||||
|
||||
header('Content-Type: application/json');
|
||||
http_response_code($httpCode);
|
||||
echo $response;
|
||||
|
||||
function calculateBonus($amount) {
|
||||
if ($amount == 200000) return 205000;
|
||||
if ($amount == 400000) return 425000;
|
||||
if ($amount == 1000000) return 1040000;
|
||||
return $amount;
|
||||
}
|
||||
|
||||
function generatePaymentToken($passengerId, $amount) {
|
||||
$url = BASE_URL . "/passengerWallet/addPaymentTokenPassenger.php";
|
||||
$postData = ['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($postData));
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($httpCode != 200) return null;
|
||||
$data = json_decode($response, true);
|
||||
return $data['message'] ?? null;
|
||||
}
|
||||
function addToPassengerWallet($passengerId, $amount, $token) {
|
||||
$url = BASE_URL . "/passengerWallet/add.php";
|
||||
$postData = ['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($postData));
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($httpCode != 200) return null;
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
function addToSeferWallet($passengerId, $amount, $paymentMethod, $token) {
|
||||
$url = BASE_URL . "/seferWallet/add.php";
|
||||
$postData = [
|
||||
'amount' => $amount,
|
||||
'paymentMethod' => $paymentMethod,
|
||||
'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($postData));
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($httpCode != 200) return null;
|
||||
return json_decode($response, true);
|
||||
}
|
||||
?>
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
// wallet/finalize_wallet_payment.php
|
||||
include_once "../../../jwtconnect.php";
|
||||
|
||||
define("LOG_FILE", "../logs/payment_verification.log");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function finalizeWalletPayment($con) {
|
||||
$orderRef = $_GET['orderRef'] ?? null;
|
||||
if (empty($orderRef)) {
|
||||
logError("FINALIZE", "Missing orderRef");
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
try {
|
||||
$driverId = $payment['user_id'];
|
||||
$originalAmount = floatval($payment['amount']);
|
||||
$paymentMethod = $payment['payment_method'] ?? 'ecash';
|
||||
|
||||
// حساب المكافأة
|
||||
$bonusAmount = match ((int)$originalAmount) {
|
||||
10000 => 10000.0,
|
||||
20000 => 21000.0,
|
||||
40000 => 45000.0,
|
||||
100000 => 110000.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
|
||||
]);
|
||||
$con->prepare("UPDATE payment_tokens SET isUsed = TRUE WHERE token = :token")->execute([':token' => $tokenSefer]);
|
||||
|
||||
logError("FINALIZE", "Wallets updated successfully", ['orderRef' => $orderRef]);
|
||||
printSuccess("FINALIZE", "Wallets updated successfully");
|
||||
} catch (Throwable $e) {
|
||||
logError("FINALIZE", "Exception during finalization: " . $e->getMessage(), ['orderRef' => $orderRef]);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
// File: generate_keys.php
|
||||
// الوظيفة: إنشاء زوج المفاتيح (العام والخاص) لمرة واحدة فقط
|
||||
|
||||
// إعدادات لتوليد المفتاح
|
||||
$config = [
|
||||
"digest_alg" => "sha256",
|
||||
"private_key_bits" => 1024,
|
||||
"private_key_type" => OPENSSL_KEYTYPE_RSA,
|
||||
];
|
||||
|
||||
// إنشاء زوج المفاتيح
|
||||
$res = openssl_pkey_new($config);
|
||||
|
||||
if (!$res) {
|
||||
die('Failed to generate new private key. Error: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
// استخراج المفتاح الخاص
|
||||
openssl_pkey_export($res, $private_key);
|
||||
|
||||
// استخراج المفتاح العام
|
||||
$public_key_details = openssl_pkey_get_details($res);
|
||||
$public_key = $public_key_details["key"];
|
||||
|
||||
// حفظ المفاتيح في ملفات
|
||||
file_put_contents('private_key.pem', $private_key);
|
||||
file_put_contents('public_key.pem', $public_key);
|
||||
|
||||
echo "<h1>Keys Generated Successfully!</h1>";
|
||||
echo "<h2>Private Key (saved to private_key.pem):</h2>";
|
||||
echo "<pre>" . htmlspecialchars($private_key) . "</pre>";
|
||||
echo "<h2>Public Key (saved to public_key.pem):</h2>";
|
||||
echo "<pre>" . htmlspecialchars($public_key) . "</pre>";
|
||||
|
||||
// --- تحضير المفتاح العام لعملية التفعيل ---
|
||||
// إزالة الهيدر والفوتر والأسطر الجديدة كما هو مطلوب
|
||||
$formatted_public_key = str_replace("-----BEGIN PUBLIC KEY-----", "", $public_key);
|
||||
$formatted_public_key = str_replace("-----END PUBLIC KEY-----", "", $formatted_public_key);
|
||||
$formatted_public_key = preg_replace("/\s+/", "", $formatted_public_key);
|
||||
|
||||
|
||||
echo "<h2>Formatted Public Key (for Terminal Activation):</h2>";
|
||||
echo "<p><strong>انسخ هذا المفتاح لاستخدامه في خطوة تفعيل الجهاز (activate_terminal.php)</strong></p>";
|
||||
echo "<textarea rows='5' cols='80' readonly>" . htmlspecialchars($formatted_public_key) . "</textarea>";
|
||||
|
||||
?>
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
// /v1/main/ride/mtn/passenger/initiate_payment.php
|
||||
include "../../../connect.php";
|
||||
|
||||
$baseUrl = rtrim(getenv('MTN_API_BASE_URL'), '/');
|
||||
$terminalId = getenv('MTN_TERMINAL_ID');
|
||||
$privateKeyPem = getenv('MTN_PRIVATE_KEY');
|
||||
|
||||
$invoice = filterRequest('invoice'); // رقم الفاتورة
|
||||
$phone = filterRequest('phone'); // رقم الزبون
|
||||
$guid = uniqid('mtn_');
|
||||
|
||||
if (!$invoice || !$phone) {
|
||||
printFailure("Missing invoice or phone.");
|
||||
exit;
|
||||
}
|
||||
|
||||
$body = json_encode([
|
||||
'Invoice' => intval($invoice),
|
||||
'Phone' => $phone,
|
||||
'Guid' => $guid
|
||||
], JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$hash = hash('sha256', $body, true);
|
||||
openssl_sign($hash, $sig, $privateKeyPem, OPENSSL_ALGO_SHA256);
|
||||
$xSignature = base64_encode($sig);
|
||||
|
||||
$ch = curl_init("{$baseUrl}/pos_web/payment_phone/initiate");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $body,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Content-Type: application/json",
|
||||
"Request-Name: pos_web/payment_phone/initiate",
|
||||
"Subject: {$terminalId}",
|
||||
"X-Signature: {$xSignature}"
|
||||
]
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
// سجل المحاولة مع Guid
|
||||
$stmt = $con->prepare(
|
||||
"UPDATE `mtn_payments`
|
||||
SET guid = :guid, status = 3, updated_at = NOW()
|
||||
WHERE invoice = :inv"
|
||||
);
|
||||
$stmt->execute([':guid'=>$guid, ':inv'=>$invoice]);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
http_response_code($httpCode);
|
||||
echo $response;
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
// بيانات التفعيل
|
||||
$terminalId = "9001000000060863";
|
||||
$activationCode = "26164711";
|
||||
$serialNumber = "INTALEQ-001"; // يمكنك تغييره
|
||||
|
||||
// المفتاح العام على سطر واحد — بدون BEGIN/END وبدون أسطر جديدة
|
||||
//$publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNxFbepx2OrpyrNG4+/aAaH3Rjc8dGw6B6vMAfsZzzm4wzoSkrtsr6jfuaMTZRLwxS5h8k1ztLG1HrOmL/NDsiE/7yxaKLAIZyWB/rR9byvPeOCC8QnCd/08kmxNl/l7Akn6qlPwsVpKUUNsr0SkU9lShMAw4OBgQq399jsbkFSwIDAQAB";
|
||||
$publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOhVAdUyxFpVNSyjRndMWEPAN9vJEetMzLbjF9DTn2lPVuRj/Mkwq9wCNhy+tdeX2lIn4K3EkONBvYJubBhxnYOoQuMchPW5vG7VnmpLjZ7TkpM2n9fcMu8u1GkLatLblDI4LTfvn3851+nhpnYlUVkjw5GAhH4XnEpveIjqDhzQIDAQAB";
|
||||
// جسم الطلب
|
||||
$body = [
|
||||
"Key" => $publicKey,
|
||||
"Secret" => $activationCode,
|
||||
"Serial" => $serialNumber
|
||||
];
|
||||
//$bodyJson = json_encode($body, JSON_UNESCAPED_SLASHES);
|
||||
$bodyJson = trim(stripslashes(json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS)),'"');
|
||||
//$bodyJson = json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
// 1. توليد هاش SHA256 للـ JSON
|
||||
//$bodyHash = hash('sha256', $bodyJson, true);
|
||||
|
||||
// 2. تحميل المفتاح الخاص للتوقيع
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents("private_key.pem")); // تأكد من وجود هذا الملف بجانب السكربت
|
||||
|
||||
// 3. توقيع الهاش
|
||||
openssl_sign($bodyJson, $signature, $privateKey, OPENSSL_ALGO_SHA256);
|
||||
|
||||
// 4. تحويل التوقيع إلى Base64
|
||||
$xSignature = base64_encode($signature);
|
||||
|
||||
// 5. إرسال الطلب
|
||||
$headers = [
|
||||
"Content-Type: application/json",
|
||||
"Accept-Language: en",
|
||||
"Request-Name: pos_web/pos/activate",
|
||||
"Subject: $terminalId",
|
||||
"X-Signature: $xSignature"
|
||||
];
|
||||
|
||||
$ch = curl_init("https://cashmobile.mtnsyr.com:9000");
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyJson);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
// ✅ النتيجة
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
"httpCode" => $httpCode,
|
||||
"response" => json_decode($response, true),
|
||||
"sentBody" => $body,
|
||||
]);
|
||||
@@ -1,247 +0,0 @@
|
||||
<?php
|
||||
// /v1/main/ride/mtn/passenger/confirm_payment.php
|
||||
include "../../../connect.php";
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
function mlog(string $msg) { error_log($msg); } // timestamp يضاف تلقائياً من PHP
|
||||
|
||||
// قاعدة URL للتطبيق (لمعالجة BASE_URL غير المعروفة)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
$baseUrl = rtrim(getenv('MTN_API_BASE_URL'), '/');
|
||||
$terminalId = getenv('MTN_TERMINAL_ID');
|
||||
$privateKeyPem = getenv('MTN_PRIVATE_KEY');
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents("private_key.pem"));
|
||||
$invoice = filterRequest('invoiceNumber');
|
||||
$phone = filterRequest('phone');
|
||||
$guid = filterRequest('guid');
|
||||
$operationNumber = filterRequest('operationNumber');
|
||||
$code = filterRequest('otp'); // الـ OTP
|
||||
$lang = filterRequest("lang");
|
||||
|
||||
mlog("MTN Confirm: Start request for invoice={$invoice}, phone={$phone}, guid={$guid}, opNum={$operationNumber}");
|
||||
|
||||
if (!$invoice || !$phone || !$guid || !$operationNumber || !$code) {
|
||||
mlog("MTN Confirm: Missing parameters");
|
||||
printFailure("Missing parameters.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// تشفير الكود (SHA256 ثم Base64)
|
||||
$hashBin = hash('sha256', $code, true);
|
||||
$codeB64 = base64_encode($hashBin);
|
||||
|
||||
// جسم الطلب نحو MTN
|
||||
$body = [
|
||||
'Invoice' => (int)$invoice,
|
||||
'Phone' => $phone,
|
||||
'Guid' => $guid,
|
||||
'OperationNumber' => (int)$operationNumber,
|
||||
'Code' => $codeB64,
|
||||
'Accept-Language' => $lang
|
||||
];
|
||||
$bodyJson = json_encode($body, JSON_UNESCAPED_UNICODE);
|
||||
mlog("MTN Confirm: Prepared body JSON: " . $bodyJson);
|
||||
|
||||
// توقيع الجسم
|
||||
$sig = null;
|
||||
$signResult = openssl_sign($bodyJson, $sig, $privateKey, OPENSSL_ALGO_SHA256);
|
||||
if (!$signResult || !$sig) {
|
||||
mlog("MTN Confirm: Failed to generate signature");
|
||||
printFailure("Signature error.");
|
||||
exit;
|
||||
}
|
||||
$xSignature = base64_encode($sig);
|
||||
mlog("MTN Confirm: Generated signature");
|
||||
|
||||
// إرسال الطلب إلى MTN
|
||||
$ch = curl_init("{$baseUrl}/pos_web/payment_phone/confirm");
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $bodyJson,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Content-Type: application/json",
|
||||
"Request-Name: pos_web/payment_phone/confirm",
|
||||
"Subject: {$terminalId}",
|
||||
"X-Signature: {$xSignature}"
|
||||
],
|
||||
CURLOPT_TIMEOUT => 25,
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
mlog("MTN Confirm: HTTP {$httpCode} - Response: " . ($response ?? ''));
|
||||
if ($curlError) {
|
||||
mlog("MTN Confirm: cURL error - {$curlError}");
|
||||
}
|
||||
|
||||
// فك JSON لرد MTN (حتى لو خطأ) لعرض سبب واضح
|
||||
$mtn = json_decode($response ?: '{}', true);
|
||||
if (!is_array($mtn)) {
|
||||
$mtn = [];
|
||||
}
|
||||
|
||||
// 🧠 سياسة القرار:
|
||||
// - إذا HTTP≠200 → فشل شبكة/بوابة
|
||||
// - إذا HTTP=200 لكن Errno≠0 → خطأ من MTN (مثل Incorrect sms code)
|
||||
// - فقط إذا HTTP=200 && Errno=0 → نجاح، نحدّث DB ونضيف للمحافظ
|
||||
if ($httpCode !== 200) {
|
||||
// لا تحدّث DB
|
||||
printFailure([
|
||||
'message' => 'MTN confirm HTTP failure',
|
||||
'http' => $httpCode,
|
||||
'mtn' => $mtn
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// HTTP 200 — افحص Errno
|
||||
$errno = isset($mtn['Errno']) ? (int)$mtn['Errno'] : null;
|
||||
if ($errno !== 0) {
|
||||
// لا تحدّث DB في هذه الحالة
|
||||
$errText = isset($mtn['Error']) ? $mtn['Error'] : 'Unknown MTN error';
|
||||
// اطبع لوج مشابه للمثال المطلوب
|
||||
// مثال: {"Errno":662,"Error":"Incorrect sms code","Abuse":2,"Transaction":""}
|
||||
mlog("MTN Confirm: Business failure from MTN - Errno={$errno}, Error=" . json_encode($mtn, JSON_UNESCAPED_UNICODE));
|
||||
printFailure([
|
||||
'message' => $errText,
|
||||
'errno' => $errno,
|
||||
'mtn' => $mtn
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ✅ نجاح كامل من MTN — تحديث DB ثم المحافظ
|
||||
try {
|
||||
global $con;
|
||||
|
||||
$stmt = $con->prepare(
|
||||
"UPDATE `paymentsLogSyria` SET status = 1, updated_at = NOW()
|
||||
WHERE order_ref = :inv"
|
||||
);
|
||||
$stmt->execute([':inv' => $invoice]);
|
||||
mlog("MTN Confirm: Payment updated successfully in DB for invoice={$invoice}");
|
||||
|
||||
$stmt = $con->prepare("SELECT * FROM paymentsLogSyria WHERE order_ref = :order_ref LIMIT 1");
|
||||
$stmt->execute([':order_ref' => $invoice]);
|
||||
$payment = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$payment) {
|
||||
mlog("MTN Confirm: Payment row not found after update");
|
||||
printFailure("Payment row not found");
|
||||
exit;
|
||||
}
|
||||
|
||||
$userId = $payment['user_id'];
|
||||
$amount = $payment['amount'];
|
||||
$paymentMethod = $payment['payment_method'] ?? 'mtn';
|
||||
|
||||
$finalAmount = calculateBonus($amount);
|
||||
|
||||
$token = generatePaymentToken($userId, $finalAmount);
|
||||
$walletResult = addToPassengerWallet($userId, $finalAmount, $token);
|
||||
|
||||
$seferToken = generatePaymentToken($userId, $amount);
|
||||
$seferWalletResult = addToSeferWallet($userId, $amount, $paymentMethod, $seferToken);
|
||||
|
||||
// رجّع رد موحّد + ضمّن رد MTN
|
||||
printSuccess([
|
||||
'message' => 'MTN Confirm',
|
||||
'data' => [
|
||||
'invoice' => $invoice,
|
||||
'finalAmount' => $finalAmount,
|
||||
'wallet' => $walletResult,
|
||||
'seferWallet' => $seferWalletResult,
|
||||
'mtn' => $mtn
|
||||
]
|
||||
]);
|
||||
exit;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
mlog("MTN Confirm: DB update error - " . $e->getMessage());
|
||||
printFailure("DB error");
|
||||
exit;
|
||||
}
|
||||
|
||||
} catch (Throwable $e) {
|
||||
mlog("MTN Confirm: Exception - " . $e->getMessage());
|
||||
printFailure("Server error");
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* نفس دوال المساعدة، لكن باستعمال 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) {
|
||||
$url = rtrim(BASE_URL, '/') . "/passengerWallet/addPaymentTokenPassenger.php";
|
||||
$postData = ['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($postData));
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($httpCode != 200 || !$response) return null;
|
||||
$data = json_decode($response, true);
|
||||
return $data['message'] ?? null;
|
||||
}
|
||||
|
||||
function addToPassengerWallet($passengerId, $amount, $token) {
|
||||
$url = rtrim(BASE_URL, '/') . "/passengerWallet/add.php";
|
||||
$postData = ['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($postData));
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($httpCode != 200 || !$response) return null;
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
function addToSeferWallet($passengerId, $amount, $paymentMethod, $token) {
|
||||
$url = rtrim(BASE_URL, '/') . "/seferWallet/add.php";
|
||||
$postData = [
|
||||
'amount' => $amount,
|
||||
'paymentMethod' => $paymentMethod,
|
||||
'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($postData));
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($httpCode != 200 || !$response) return null;
|
||||
return json_decode($response, true);
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
<?php
|
||||
include "../../../connect.php";
|
||||
date_default_timezone_set("Asia/Damascus");
|
||||
|
||||
// ========== إعدادات MTN ==========
|
||||
$terminalId = "9001000000060863";
|
||||
$currencyCode = 760;
|
||||
$sessionNumber = 0;
|
||||
$ttl = 15;
|
||||
|
||||
// ====== استقبال البيانات من فلاتر ======
|
||||
$amount = filterRequest("amount");
|
||||
$passengerId = filterRequest("passengerId");
|
||||
$phone = filterRequest("phone");
|
||||
$lang = filterRequest("lang");
|
||||
|
||||
// ✅ Log مبدئي
|
||||
error_log("🚦 START | passengerId: $passengerId | phone: $phone | amount: $amount");
|
||||
|
||||
// تحقق من المدخلات
|
||||
if (empty($amount) || empty($passengerId) || empty($phone) || $amount <= 0) {
|
||||
error_log("❌ Invalid input: amount=$amount, passengerId=$passengerId, phone=$phone");
|
||||
printFailure("بيانات الدفع غير كاملة أو غير صالحة.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// ====== توليد invoiceNumber و GUID ======
|
||||
$invoiceNumber = mt_rand(10000000000, 99999999999);
|
||||
//$invoiceNumber = "MTN_" . $passengerId . "_" . time();
|
||||
$guid = uniqid("mtn_");
|
||||
error_log("🧾 Generated Invoice: $invoiceNumber");
|
||||
error_log("🧭 Generated GUID: $guid");
|
||||
|
||||
// ====== 1. إنشاء الفاتورة ======
|
||||
$createInvoiceBody = [
|
||||
"Amount" => intval($amount * 100),
|
||||
"Invoice" => $invoiceNumber,
|
||||
"Session" => $sessionNumber,
|
||||
"TTL" => $ttl
|
||||
];
|
||||
error_log("📦 Create Invoice Body: " . json_encode($createInvoiceBody, JSON_UNESCAPED_UNICODE));
|
||||
$invoiceResponse = sendMtnApiRequest("pos_web/invoice/create", $terminalId, $createInvoiceBody);
|
||||
error_log("📥 Create Invoice Response: " . json_encode($invoiceResponse, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
if (!$invoiceResponse || isset($invoiceResponse['Errno']) && $invoiceResponse['Errno'] != 0) {
|
||||
error_log("❌ Failed to create invoice. Error: " . json_encode($invoiceResponse));
|
||||
printFailure("فشل إنشاء الفاتورة عبر MTN.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// ====== 2. بدء الدفع ======
|
||||
$initiateBody = [
|
||||
"Invoice" => $invoiceNumber,
|
||||
"Phone" => $phone,
|
||||
"Guid" => $guid
|
||||
];
|
||||
error_log("📤 body initiateBody: $initiateBody");
|
||||
error_log("📦 Initiate Payment Body: " . json_encode($initiateBody, JSON_UNESCAPED_UNICODE));
|
||||
$initiateResponse = sendMtnApiRequest("pos_web/payment_phone/initiate", $terminalId, $initiateBody);
|
||||
error_log("📥 Initiate Response: " . json_encode($initiateResponse, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
if (!$initiateResponse || !isset($initiateResponse['OperationNumber'])) {
|
||||
error_log("❌ Failed to initiate payment.");
|
||||
printFailure($initiateResponse);
|
||||
exit;
|
||||
}
|
||||
|
||||
$operationNumber = $initiateResponse['OperationNumber'];
|
||||
|
||||
// ====== 3. تسجيل العملية ======
|
||||
try {
|
||||
$stmt = $con->prepare("INSERT INTO `paymentsLogSyria`
|
||||
(`user_id`, `amount`, `status`, `order_ref`, `payment_method`, `created_at`)
|
||||
VALUES (?, ?, 2, ?, 'mtn', NOW())");
|
||||
$stmt->execute([$passengerId, $amount, $invoiceNumber]);
|
||||
error_log("✅ DB Log Inserted.");
|
||||
} catch (PDOException $e) {
|
||||
error_log("❌ DB ERROR: " . $e->getMessage());
|
||||
printFailure("فشل في تسجيل العملية.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// ====== 4. نجاح
|
||||
error_log("✅ Payment initiation successful.");
|
||||
printSuccess([
|
||||
"invoiceNumber" => $invoiceNumber,
|
||||
"operationNumber" => $operationNumber,
|
||||
"guid" => $guid
|
||||
]);
|
||||
|
||||
|
||||
// ====== دالة إرسال الطلب =====================
|
||||
function sendMtnApiRequest($requestName, $terminalId, $body)
|
||||
{
|
||||
$apiUrl = "https://cashmobile.mtnsyr.com:9000";
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents("private_key.pem"));
|
||||
|
||||
// ✅ تحويل الـ body إلى JSON بدون فراغات أو أسطر
|
||||
$bodyJson = trim(stripslashes(json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS)), '"');
|
||||
//$bodyJson = json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
// ✅ توليد التوقيع
|
||||
// $bodyHash = hash('sha256', $bodyJson, true);
|
||||
error_log("📤 body before JSON: $bodyJson");
|
||||
openssl_sign($bodyJson, $signature, $privateKey, OPENSSL_ALGO_SHA256);
|
||||
$xSignature = base64_encode($signature);
|
||||
error_log("📤 body xSignature: $xSignature");
|
||||
// ✅ رؤوس الطلب
|
||||
$headers = [
|
||||
"Content-Type: application/json",
|
||||
"Accept-Language: $lang",
|
||||
"Request-Name: $requestName",
|
||||
"Subject: $terminalId",
|
||||
"X-Signature: $xSignature"
|
||||
];
|
||||
|
||||
$ch = curl_init($apiUrl);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyJson);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
// ✅ لوق داخلي
|
||||
error_log("🔐 Signature for $requestName: $xSignature");
|
||||
error_log("📤 Sent JSON: $bodyJson");
|
||||
|
||||
curl_close($ch);
|
||||
return json_decode($response, true);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXwIBAAKBgQDOhVAdUyxFpVNSyjRndMWEPAN9vJEetMzLbjF9DTn2lPVuRj/M
|
||||
kwq9wCNhy+tdeX2lIn4K3EkONBvYJubBhxnYOoQuMchPW5vG7VnmpLjZ7TkpM2n9
|
||||
fcMu8u1GkLatLblDI4LTfvn3851+nhpnYlUVkjw5GAhH4XnEpveIjqDhzQIDAQAB
|
||||
AoGBALRcAvqJT8nHN7y+8QNFHNZ+XwIpc4egmJY1Ny0iJvPtZWaYHVG5PRE4Qu4+
|
||||
29+3oX5dYDx146tu4L5mQvLS3ULBsvxaUZt2lT/vxkQzI9pNfXw584WvIrbtxQod
|
||||
ILvBcnamwQa9hEOIFZVyZ/hzkzUcMO6cAXqvsfqqPgJhm7PBAkEA+xgE9CUOLDFl
|
||||
vLePQKGcHIUOsPLr16qNEgGhTW7Km3OMMqoB2f7t67xOHGqK6tnANRM4Sk6IModI
|
||||
wbZuVh4jMQJBANKOVmIdDLNffZVHp90SDRG7/YdK2R5ob361CIkcUzjh927Wfs5W
|
||||
A/WroB7eJ7pWiq2BMaj/xq65nYaCOldvaV0CQQDm12c+eY61DFjnDa6ykaEvCxi9
|
||||
jydJp+93vW3o/VFhZvJeZbO8EcX0MrNxJnY+gSBW6yuWDOrj4UH/bVO08pIRAkEA
|
||||
lH3TiBAqo9nlTEEjrnILi4VD0IVFx/8pGnf71A6I1qXuBVn6RfQ9iKWIIBzWccCU
|
||||
vrZNWn1AFntLD9CJ6p3k9QJBAMbSQ9CoXWlOLJRduV15ER1ZyE/inVd4jIvtjAgz
|
||||
b7QaM62Ecxl3D8EI/LTSZV9Oa8D/62cJeMsflVa7gpavL70=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,6 +0,0 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqBQZEJXWCQwPsPzBM70M3TjyU
|
||||
5vwCZWoEtUomR9Qu+dEQaa0Hniz6JY8+goCxfMYuZQw6+kimctA2KqzT2pCsJufN
|
||||
b92pSAMZgb0RSTl2y62oJkJd2WY7dj36AvPEyw6DxCFItvFOu7HGl3LlHQBriiw3
|
||||
jwtuS6DO7gbmAJPU8wIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
Reference in New Issue
Block a user