fix(security): wallet race conditions - FOR UPDATE + atomic claims on payments, webhooks, bonuses

This commit is contained in:
Hamza-Ayed
2026-06-17 06:34:51 +03:00
parent 0ceb67ee56
commit c82b0071bb
7 changed files with 77 additions and 66 deletions

View File

@@ -96,24 +96,26 @@ try {
// ============================================================
global $con;
// 4) التحقق من السجل في قاعدة البيانات
$chk = $con->prepare("SELECT status, user_id, amount, payment_method FROM paymentsLogSyria WHERE order_ref = :ref LIMIT 1");
// بدء المعاملة أولاً (قبل SELECT للحماية من السباق)
$con->beginTransaction();
// 4) التحقق من السجل في قاعدة البيانات مع FOR UPDATE
$chk = $con->prepare("SELECT status, user_id, amount, payment_method FROM paymentsLogSyria WHERE order_ref = :ref LIMIT 1 FOR UPDATE");
$chk->execute([':ref' => $transactionID]);
$payment = $chk->fetch(PDO::FETCH_ASSOC);
if (!$payment) {
$con->rollBack();
printFailure($lang === 'ar' ? "لم يتم العثور على السجل." : "Payment row not found");
exit;
}
if ((int)$payment['status'] === 1) {
$con->rollBack();
printSuccess(['message' => 'Already confirmed', 'data' => ['order_ref' => $transactionID]]);
exit;
}
// بدء المعاملة (Transaction)
$con->beginTransaction();
try {
// أ) تحديث حالة الدفع في السجل
$stmtUpdate = $con->prepare("UPDATE `paymentsLogSyria` SET status = 1, updated_at = NOW() WHERE order_ref = :ref");