This might work: change the rule for winning an auction.
Now, I guess, a user wins an auction if she's the highest bidder at the conclusion of the auction. You can change the rule so the user must BOTH be the high bidder AND have sufficient budget to cover the bid. If both criteria aren't met, the next highest bidder with enough budget wins.
This is easy to explain to users. "to win, you need enough in your budget. If you're losing auctions you can increase your budget."
Implementation wise, you can use a database transaction to handle the "win" operation. Inside a single database transaction, debit the winning buyer's budget and credit the seller's account.
You can use SQL sequences like this:
START TRANSACTION;
SELECT budget
FROM user
WHERE id = nnnn
AND budget >= bid
FOR UPDATE;
/* if you got a result do this */
UPDATE user SET budget=budget-bid
WHERE id= nnnn;
UPDATE seller SET balance=balance+bid
WHERE ID = sssss;
UPDATE auction
SET winner=nnnn, winning_bid=bid,
closetime=NOW()
WHERE auction = aaaa;
COMMIT;
/* if you got no result from the SELECT do this */
ROLLBACK;
You can use distributed locks to solve the double-spending /double booking issue. You need to acquire at least three locks that would update
You can also create a bid ledger to verify the user's spending, seller account balance, and user's wallet balance. You can run a cron job hourly or every 10 minutes to verify any error and notify support/dev to check for potential errors.
Your logic could be like this
Procedure BidProcessor
input: user, bid, seller
// this should get locks for auction, user wallet balance and seller balance
success = acquireLocks( bid.auction_id, user.id, seller.id )
if success then
hasSufficientFund = user.hasSufficientFund( bid.amount )
if hasSufficientFund then
ExecuteBid( user, bid, seller )
releaseLocks( bid.auction_id, user.id, seller.id )
else
releaseLocks( bid.auction_id, user.id, seller.id )
endif
else
releaseLocks( bid.auction_id, user.id, seller.id )
endif
Each executor can use their identity id as a lock value to avoid releasing someone else lock.
Procedure ExecuteBid
input: user, bid, seller
Description: Run a SQL transaction to update all related entities
START TRANSACTION;
UPDATE user SET budget=budget-bidAmount WHERE id= user.id;
UPDATE seller SET balance=balance+bidAmount WHERE ID = seller.id;
UPDATE auction SET winner=bid.id, closed_at=NOW() WHERE id = bid.auction_id;
UPDATE bid SET processed_at = NOW(), status='WON' WHERE id = bid.id;
COMMIT;
if commit fails then do a rollback
ROLLBACK;
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Find the answer in similar questions on our website.
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.
PHP (from the English Hypertext Preprocessor - hypertext preprocessor) is a scripting programming language for developing web applications. Supported by most hosting providers, it is one of the most popular tools for creating dynamic websites.
The PHP scripting language has gained wide popularity due to its processing speed, simplicity, cross-platform, functionality and distribution of source codes under its own license.
https://www.php.net/
Welcome to the Q&A site for web developers. Here you can ask a question about the problem you are facing and get answers from other experts. We have created a user-friendly interface so that you can quickly and free of charge ask a question about a web programming problem. We also invite other experts to join our community and help other members who ask questions. In addition, you can use our search for questions with a solution.
Ask about the real problem you are facing. Describe in detail what you are doing and what you want to achieve.
Our goal is to create a strong community in which everyone will support each other. If you find a question and know the answer to it, help others with your knowledge.