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

@@ -20,30 +20,27 @@ if (empty($driverId) || $amount <= 0) {
}
try {
// --- 2. التحقق من بيانات السائق ورصيده ---
// --- Atomic balance check + insert with transaction ---
$con->beginTransaction();
$stmt_driver = $con->prepare("
SELECT SUM(amount) AS balance
SELECT COALESCE(SUM(amount), 0) AS balance
FROM driverWallet
WHERE driverID = :id
LIMIT 1
FOR UPDATE
");
$stmt_driver->execute([':id' => $driverId]);
$driver = $stmt_driver->fetch(PDO::FETCH_ASSOC);
if (!$driver) {
printFailure("Driver not found.");
exit;
}
$payout_fee = 3500.00; // عمولة السحب
$total_deduction = $amount + $payout_fee; // المبلغ المطلوب مع العمولة
$payout_fee = 3500.00;
$total_deduction = $amount + $payout_fee;
if ($driver['balance'] < $total_deduction) {
$con->rollBack();
printFailure("Insufficient balance. Required: $total_deduction");
exit;
}
// --- 3. إنشاء طلب السحب في قاعدة البيانات ---
$sql = "
INSERT INTO payout_requests (driver_id, driver_phone, amount, wallet_type)
VALUES (:did, :phone, :amount, :wallet)
@@ -56,6 +53,8 @@ try {
':wallet'=> $wallet_type
]);
$con->commit();
if ($stmt->rowCount() > 0) {
// --- 4. إرسال إشعار لخدمة العملاء ---
$customerServicePhone = getenv('CUSTOMER_SERVICE_PHONE');