Files
Siro/walletintaleq.intaleq.xyz/v2/main/ride/mtn/passenger/mtn_confirm.php
2026-06-16 22:44:11 +03:00

247 lines
8.8 KiB
PHP
Executable File

<?php
// /v1/main/ride/mtn/passenger/confirm_payment.php
include "../../../jwtconnect.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);
$siroToken = generatePaymentToken($userId, $amount);
$siroWalletResult = addToSiroWallet($userId, $amount, $paymentMethod, $siroToken);
// رجّع رد موحّد + ضمّن رد MTN
printSuccess([
'message' => 'MTN Confirm',
'data' => [
'invoice' => $invoice,
'finalAmount' => $finalAmount,
'wallet' => $walletResult,
'siroWallet' => $siroWalletResult,
'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 addToSiroWallet($passengerId, $amount, $paymentMethod, $token) {
$url = rtrim(BASE_URL, '/') . "/siroWallet/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);
}