E-commerce website design - php

I'm working on a e-commerce website. This website shall be integrated with a payment- processor. I have the following orders table.
orders(InnoDB)
-----------------------
id int PRIMARY KEY
user_account_id int
item_id int
price decimal(6,2)
payment_mode ENUM(cash,pg)
payment_status(pending,paid,lost)
order_timestamp Timestamp
When the order is placed, payment_status will be 'pending'. User is redirected to payment-processor.If the payment is authorized, payment_status shall be updated as 'paid'. If the transaction is lost (or) unauthorized payment_status shall be updated as
'lost'. I want to give user 30mins to pay. If he fails to pay within 30mins payment_status shall be updated as lost and ordered item will be cancled and available for others to book.
So, How can this be achived? How can I run a script after 30mins to update order as lost (or) should I use a cron-job every 5mins checking for lost transactions?

I would have done so, in application store pending transactions info, and with timer after 30mins update database + cron task everу N mins(for reliability)
UPD:
Oops, not noticed php tag. As variant, update payment status before selecting payments by status

Related

CS-Cart The transaction was not sent to the host because of a duplicate order id

I'm using Menoris payment processor on CS-Cart v 4.3.9, a while ago this error has become more frequent "Payment processor response: The transaction was not sent to the host because of a duplicate order id".
I don't understand why is it happening, so I don't know where to look, I have tried to trigger the error myself but couldn't.
Check you table cscart_orders and have a look at those IDs.
I dont think you've reched the maximum limit of mysql entries in cscart_order to be duplicate (16777215 - is the maximum value for the field with the integer type).
In my opinion the problem is where you send data, consider to ask them for that.
Check this too: http://forum.cs-cart.com/topic/45830-issue-with-order-id/
Please change the code and create an unique order id for each time a customer try to pay the order, something like
ex: 12345_1
where order_id = 12345 and 1 order_repaid value
you can check how 2checkout payment gateway is doing for example ;) app/payments/2checkout.php
...
$cart_order_id = ($order_info['repaid']) ? ($order_id .'_'. $order_info['repaid']) : $order_id;
...
if Monoris doesn't accept for order_id to be string than you will need to generate and unique order_id for each time customer try to buy and attach to order_id in this way on payment return you will be able to get the real order_id and compete the payment
*[duplicate order id] - issue is happening when a customer goes to Monoris payment page and customer click cancel or get back to website and after that he goes again to pay the order
Thanks all for your answers, i have managed to solve this by adding a time stamp next to the order id
'order_id' => $processor_data['processor_params']['order_prefix'] . $order_info['order_id'] .'_'. date("G:i:s"),

How to prevent race condition in online hotel booking

I am writing a hotel booking software using PHP and MySQL. I am pretty much done with it but I ran into a race condition problem. For example there is only one standard room left and when 2 guests both select it it shows available to both of them. I tried fixing it by checking the room again when the guest clicks confirm before payment but that still has issues. I also tried making the room status to pending when whoever clicks the confirm first but I can't figure out how to change it back to available if the guest decides not to pay or just closes the browser. I searched SO for answers but I didn't really find a definitive answer. Thanks in advance
One solution is to add two columns to a table in the database. One column is the session ID or user ID or whatever of the user that is being offered the room. The second column is a timestamp indicating when that offer will expire.
Then, in your app, only show rooms that have an expired timestamp in the hold column. (Set the initial timestamp to 0 so that it starts out expired.) When a room is selected, check the column again. If there's an unexpired timestamp there, the user gets a "sorry, you were too slow" message. Otherwise, put a timestamp there for 15 minutes into the future or whatever, and proceed.
You see this on travel sites and ticket-purchasing sites a lot where it says something like "We're holding these seats for you for another 14 minutes. Please complete the transaction by then or it will be released blah blah blah."
I would also go with the pending state. You could save the state together with the session id of this user and have a cronjob that deletes all pending states that have expired session ids associated to them.

What is the best way to increment invoice ID?

I'm developing a simple invoice system using PHP and MySQL.
My initial thought was to use ID (auto incremented) for invoice ID. But that will not work.
A temporary invoice is created when user commits an order to my Payment Service Provider.
If the transaction fails, I need to delete the temporary invoice.
The problem is that the invoice has been created and given and ID - and by law, I'm not allowed to delete any invoices that has been given a invoice number. So I need to add another column 'invoice_id' and add an ID after successful transaction.
Multiple users may do a purchase at the same time.
My question is, how can I make sure to retrieve the last created invoice ID and increment this?
Should I use a $_SESSION[]for storing invoice_id? Or should I retrieve latest ID from DB? If retrieving from DB, should I lock the table for this transaction?
Any guidance much appreciated.
Create a temporary table for invoices which have not been processes.
Once the invoice has been processed, move over to permanent table and assign an invoice id using the AUTO_INCREMENT option in mysql
This will allow for two tables, one for unprocessed and the other for processed. You can also place an id field to keep track of the movement from temp -> perm
I wouldn't delete it, I would just cancel it. Additional usually after a failed transaction the trader reminds the customer to pay, which is not possible, when the invoice doesn't exist anymore.
One approach would be to keep the invoice in session until the payment has been approved. If the payment is not approved, the invoice will die with the user's session.
Another approach would be to create a holding table for pending invoices. When payment is approved, simply move the data into the invoice table.
And the last approach, go ahead and create the invoice in the invoice table, but soft delete it if the payment fails. Just set a flag, deleted = 1 and in all your procs add "where deleted = 0".
I would generate purely random invoice numbers. Simplest strategy:
md5(uniqid())
But still – storing unfinished invoices in the database sounds more sane.
Also the random factor will make guessing the invoice number more difficult.

Synchronizing database update/checking for bidding platform

I am building a platform on php/mysql that allows users to but for a percentage of a product. Basically they choose what percentage they want to bid for and the markup price they'd like to bid at e.g. 1.2.
The issue I have is that if there are several bids placed simultaneously for the same product, I need to queue the bids so when processed only the valid ones go through. For example, if there is 20% available at a value of 1.2 and two users simultaneously bid for 20% at 1.2, the process for each bid would be:
1----- select current bids
2----- php processing to work out if bid is still available
3----- place bid
The issue here is if both of the 'check if availables' happen before either of the 'place bids' then both bids will go through and effectively cause a stock issue.
Is there a way of queuing this process so the whole of steps 1-3 happen for a bid before the next one can run.
My initial thought was to use a cache table to store all the bids and then run a cron every few seconds which will process in order of ID from the cache table and notify accordingly but this seems like it may not be viable on a high traffic system as the server would get hammered over it.
Any help much appreciated
If two bids can never be identical I would solve it at the data layer. Create a unique key on your bid table based on item_id, bid_value and whatever else needs to be unique. The second insert will fail and you can let user know they were beaten to the post
I solved this at PHP level by injecting the bid as an 'accepted bid' first so that any subsequent bids would fail. Then I ran the check to see if the bid was ok, if not the bid gets removed, if it is the table gets updated as required in place for new bids.

Payment Gateway Implementation

I am integrating one of the payment gateway to my site in PHP, Before proceeding further, As I am new to this, I have some doubts (use cases/scenarios), So I need a solution to deal with these scenarios. I have listed them here
1) How to pass unique id to payment gateway, while It considers it as a Order No, But In real scenario Order NO/ID will be generated only on successful transaction. I thought of sending a random number to Payment gateway. On successful transaction i can store in Order table.
Table: Order
1) aID:(unique, Primary, AI)
2) RandomNo(unique)
3) Order Date
Is this a good Idea
2) Which ID to be shown to user As ORDER ID either the aID or RandomNO
3) Do I need to store the Response from the payment gateway in the DB, such as Payment ID(unique), Response Code, OrderNO & Amount. How it will be useful.
4) What are the possible scenarios that can occur after payment gateway integration, And How to deal them
1) How to pass unique id to payment gateway, while It considers it as a Order No, But In real scenario Order NO/ID will be generated only on successful transaction. I thought of sending a random number to Payment gateway. On successful transaction i can store in Order table.
ANS : First of all insert the order in database before redirecting to payment gateway and use the unique id of that insertion as order id.
2) Which ID to be shown to user As ORDER ID either the aID or RandomNO
ANS : The order id as mentioned above can be shown to the user.
3) Do I need to store the Response from the payment gateway in the DB, such as Payment ID(unique), Response Code, OrderNO & Amount. How it will be useful.
ANS : Yes! You must store response from payment gateway as you may need it in future in case of any dispute.
4) What are the possible scenarios that can occur after payment gateway integration, And How to deal them
ANS : I didn't get you in this question.

Categories