fix(security): wallet race conditions - FOR UPDATE + atomic claims on payments, webhooks, bonuses
This commit is contained in:
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user