MySQL transactions with ajax - php

I am currently working on a site that allows users to rent equipment. When the user wishes to add accessories to the current rent a pop up window will open with the accessories available for the equipment. When the user selects an accessory, I use a JavaScript function with AJAX to validate the users input and to check the existence of the accessories in my database.
After this validation the pop up window closes and I need to start a MySQL transaction to modify the accessories picked for the rented equipment. I need it to be a transaction because the user can cancel the rent at any moment and I need to "return" everything to the way it was before the rent.
Is it possible to handle MySQL transactions using several PHP files with AJAX?

No, you can't do it with mysql transactions because you will not be able to serialize a reference to the transaction or connection, and the transaction will either be rolled back or committed (not sure which, but I think it gets committed) when the script execution stops. This means that it will not work across multiple requests.
Instead of using transactions, a possible solution would be to update your schema to add a flag for "picked" accessories. When the customer selects them, set this flag. If they cancel, unset it.

Related

prevent concurrent request from a user

I have a question about concurrent request a user from different browser
Imagine we have balance in wallet for just buy one product, if a user request a product at the same time with two different browser, can user buy a product two times? if it is possible, how can I prevent the second action?
example:
user A balance : 100$
user A ----> mozila ----> request ----> product A50(price 100$)
user A ----> chrome ----> request ----> product A50(price 100$)
above request happen at the same time after that some process the amount of wallet decrease
You should perform these operations in SQL TRANSACTIONs having an appropriate isolation level. All of the operations performed within the transaction will be "all or nothing," which means that all of the changes take effect if you COMMIT and none of them do if you instead ROLLBACK. Furthermore, if two transactions attempt to touch the same row, one of them will either be forced to wait or will be turned away. Also, the other transaction will not see anything that hasn't yet been committed.
For instance, if you want to "deduct money from the user's account and apply it to an order," you would perform both updates in one transaction. So, "if everything worked, both updates happened instantaneously." And, "if it didn't work and the transaction was rolled back, nothing changed anywhere."
But it's important that you also test the user's balance within the same transaction! (Otherwise, there would be a "race" between testing the balance and proceeding with the sale.) Your logic might be something like this pseudocode:
BEGIN TRANSACTION with proper isolation level
Retrieve user's account.
If there isn't enough money:
ROLLBACK
exit
Else:
UPDATE user account to withdraw money.
UPDATE the invoice to show payment.
INSERT a new entry into the (financial ...) transaction log table.
COMMIT
This works as intended because the entire set of operations that occurs within the transaction is "atomic."
SQL servers vary slightly in their implementation of transactions but here is a web-page on the topic (covering MS SQL Server):
https://www.sqlserverlogexplorer.com/types-of-transaction-isolation-level/

How to add, reduced amount of item, to its table, when user close browser tab in payment gateway

I have a situation for shop market, when user wants to pay, first a factor will create then redirect him to the payment gateway.
In factor creation, number of items that user is selected, reduce from stock number count of existence items, so if user close the payment gateway browser's tab, wanted items are reduced from stock items count and never returns.
How manage this situation for payment??
My Solution
I think a lot on that and come with this solution that create a reserved factors table to store current factor that is going to pay and when back from payment gateway, simply delete it.
If browser's tab was close by user then calculate that if time of reserved factor is more than payment gateway the delete it from reserved table and add reduced items number to stock number count.
I add this code to my construct (because I think this is right place to check for all items in reserved factor right before show items to user. This helps for items that are not available, to be available now) but in another hand I think if number of reserved factors in database are big enough, it might have a huge effect of loading performance.
SO what is the right solution for situations like this?
Can I have something like a schedule plan in MySQL to delete those records? or even in PHP?
OR ANY IDEA...
EDIT:
I do want a code base solution if any exists.
Can I have something like a schedule plan in MySQL to delete those records? or even in PHP?
Usually this sort of thing is done using your server's "cron" feature (or "Scheduled Tasks" if your server is running Windows). You can write a PHP script that clears these abandoned carts when run, and configure your server to execute that PHP script at regular intervals.
MySQL also has an "Event Scheduler" feature; I don't think that gets used very often, but it is an option.
...so if user close the payment gateway browser's tab, wanted items are reduced from stock items count and never returns.
This is the wrong way to look at this problem. Consider these scenarios:
User accidentally closes their browser, re-opens it, and tries to finish purchasing
User loses internet access and cannot finish purchasing... browser isn't closed
While it is possible to use the Beacon API in newer browsers to send an update when a browser is closed, for these reasons it's a bad idea.
You have two general options:
Option 1: Track the user/cart activity
Every time the user does something meaningful on the site, update their last active time on a record for their cart. If a user is still browsing the site and they have a product in their cart, keep it reserved there until the sale is complete or until they are no longer active for some period of time. For example, if they haven't been on the page in 15 minutes, release the reservation for the product. (Be prepared to reserve it again if they come back and the product is still available.)
Option 2: Don't reserve until purchase
Keep the item in-stock until it's actually bought. If at the time of purchase the product is no longer available, let the user know.
Which of these options you choose depends on your business conditions and the sort of stuff you're selling.

What's the best practice to handle multiple MySQL transaction?

I'm developing an order system with PHP + mySQL. There's a high chance that multiple users will create new orders with same product at the same time.
This is the scenario: in MySQL DB, there's a table named "inventory", in which all products' item numbers and available quantity are listed.
Now,
Product A's inventory is 500 pcs.
User1 is working on a new order with 300 pcs of product A, but he hasn't submitted yet. However, there's an AJAX script to send a query to table "inventory" and since the inventory qty is 500 pcs, so it returns 300 pcs as available for this order.
User2 is working on another new order now, while User1 still hasn't submitted his order. User2 wants 400 pcs of product A, and since 300 pcs from User1 has't been submitted, AJAX function returns 400 pcs are available for User2's order.
Now here's the problem. Either User1 or User2 submits his order first, the another user will not have enough quantity to fulfill his order as the result returned by AJAX.
I want to know what is the best (or normally) practice to handle this type of task.
I have thought about PDO transaction handling (not sure if it will work, have never used it, I'm quite new), or maybe should I just forget about AJAX but do the inquiry when user submit the form?
Also I had thought about putting a "check" button on the page then after the user finished inputting the order, they hit "check" to send an inquiry to DB then get the most 'updated' quantity, maybe it's soon enough before the user hits submit.
Thanks.
Thwo things you have to understand first:
There is no such thing like "PDO transaction"
Transactions are inapplicable here anyway.
What you actually need is simple reservation system. Or a notification one.
In case of reservation, you may mark 300 items as "reserved". Then all others may either content with remained 200 or wait till reservation gets released or stock refunded.
While an example of notification system you may see right here on this very site: in case there is a user who is working on the answer, and question happened to be closed, an ajax notification is shown to the user, saying he has not enough items to reserve anymore.
there are 2 ways:
1) you reserve the stock as user1 puts it in their basket
(and deal with timeouts / abandoned orders and moving stock back to inventory and a way to notify the users when items come back in stock)
this means that user2 can't add them if user1 has them.
(you could physically remove the number from the inventory, or you could add another column with 'reserved' in it - e.g. 200 in stock and 300 reserved)
2) you do the stock check + reserve when the user has begun the checkout process and notify the users if the items aren't in stock and you don't have to deal with abandoned orders as they haven't reserved the stock yet.
I have developed e-commerce systems based on both, and #1 is, imho the best - as a user I want to know if the things are in stock as I add them to my basket
This isn't a matter of what you're using to make your query (though using PDO is still a good idea.) When the user finally submits their order, your php script should perform an extra check that the requested amount is in stock. If not, the user should presented with an error that the amount of product is no longer avaiable.
Use ajax to check the stock periodically so the user gets a javascript notification when something in their order is no longer available.

Run php script in background on nginx

I'm trying to develop a payment module for one shop cms.
Payment is based on acquiring in a Bank.
So firstly for each order creates (with curl) a "ticket" on bank side. Ater that client is forwarded on payment page on bank server with its ticket id. If customer pays and push button "go back to store" everything is fine.
But if customer pays and don't push this button i need to check the result (if he paid or not). It is also made by curl. I'm requesting info by ticket id and receive an array with parameters i need among them is result code i need to check.
So i need to check it automatically (for ex. 1 time each 5 mins during an hour).
Cron can't help me coz it is all dynamically processes.
I created a function that returns me the result. But how can i start it in background with any interval?
Using cron. PHP does not offer anything like scheduler because it is out of scope of the language. You may use DB to store some of parameters needed to the whole process.
I'll extend a little bit WebnetMobile answer on using cron for what you want.
Likely you have a table in your DB where you store are tickets you get from Bank and whenever they suceed or did not suceed as well the date the ticket was created.
Then, if what you want is to check every five minutes from bank ticket creation date whetever it suceed or not if unknown, you should run a cron each minute that will do the following:
Check if there are bank tickets without defined state (Suceed or Failed).
Check if time created (without seconds) minus current time (without seconds) MOD 5 == 0.
If true, means another 5 minutes period have passed from that ticket creation and should be checked, Else do nothing.
I think this will do what you want

Creating a ordering and checkout system, protecting against changing the cart during payment

So I have a multi paged checkout system that relies on sessions to store the contents of the shopping cart. I'm also using a third party system to process credit cards, which hosts the actual payment page on their servers. I just have to POST to the page the final total.
The problem I foresee is what if someone clicks to go to the hosted pay page, and then for some legitimate or nefarious reason changes the shopping cart contents in another tab. I had initially planned that when the hosted pay page redirects back to my receipt page I would then INSERT the order into my database. But, if the session is changed at that point, the order will be different from the total cost charged.
What would be a solution to this problem. I can see this sort of thing being an issue for all cart systems, so I'm wondering how they do it.
Maybe when the user clicks the button to go to the hosted paypage I can make a temporary order entry in a temp_order table in the database, and then when the payment goes through I can transfer that temp record into the permanent record table? That way I don't insert the record from the session information that has changed. But if I have to POST to the hosted pay page, where do I have the opportunity to save the shopping cart to the temp table?
Also, the temp order id must be unique across both temp and permanent tables since I don't want any overlap.
Lastly, I should want to clear the temp order table frequently as they are just temp records. Some might not go through as the user could change their mind on the hosted pay page.
I'm really confused as to what I should do!
I see no need to create a separate table. Just add one column into existing table, say, payment_in_progress and analyse it when client submits any changes to the cart.
The requirement to clear out unprocessed outdated orders remains
When the payment gateway returns just store the amount received against the shopping cart and if the amount received is less then the total, put them back onto the payment page, showing the outstanding balance left to pay.
Unless the payment system returns control to your website before final processing of the order, e.g. like PayPal Express Checkout, there is no way to stay in control of the checkout process. One-way checkout systems are really meant to be one-way. Follow-up management is manual (by a payment receipt) or handled by server to server notifications.
Posting directly to the payment site is not going to give you any control once you submit away to the other website. Probably the best case scenario is you submit the order to your website as an UNPAID order into your database, then provide a page that says "You're almost finished. Continue to payment." -- At this point, you should have also emptied the customer's cart so they cannot change anything about the order in process (which is already in your DB). When the payment system redirects back to your website, you will simply look for the unpaid order and mark it paid. It would also be a good idea to verify the payment amount, just in case the user modified the POST data in an effort to pay less.
EDIT:
You might really be in need of a payment gateway solution that gives you more control over the checkout process. Your concerns are real, but they are not typically addressed adequately using payment flows that send the user directly away from your website without first setting up the transaction server-side.

Categories