I have an e-commerce site developed in magento, an I am using paypal as payment method. When user adds 2 items for a product "Dress" in cart, and goes to checkout page and click place order button then I am redirecting user to paypal site for payment. But there are some users who abandons payment and leave the paypal page.
When they click on place order, magento generates an order in backend and keep its status as Pendin, once paypal payment done and user redirected back to our site, that order's status updated to Processing because payment is done. But if user leaves from pyapal payment page without making payment then my product stocks are decreased and other users can't place the order until I cancel the junk orders.
Is there any way with which I can automate this process, if user do not pay on paypal then stocks/inventory should back to normal?
Please help, thanks!
Here is the cron that we are using since past few months. This code checks for pending orders for more than 7 minutes age to 30 minutes and cancels them. For me this restores the inventory.
public function cancelPending()
{
$orderCollection = Mage::getResourceModel('sales/order_collection');
$orderCollection
->addFieldToFilter('status', 'pending')
->addFieldToFilter('created_at', array('lt' => new Zend_Db_Expr("DATE_ADD('".now()."', INTERVAL -'0:07' HOUR_MINUTE)"),
'gt' => new Zend_Db_Expr("DATE_ADD('".now()."', INTERAL -'0:30' HOUR_MINUTE)")));
foreach($orderCollection->getItems() as $order)
{
$orderModel = Mage::getModel('sales/order');
$orderModel->load($order['entity_id']);
if(!$orderModel->canCancel())
continue;
$orderModel->cancel();
$orderModel->setStatus('canceled');
$orderModel->save();
}
My default status for an order pending payment is "pending". you may have to change that.
I guess you'll need to set up a magento cron job, which takes the orders which are in pending state for more than 20 minutes, and reverting those, therefore enabling your stock again.
I tried to google it, but couldn't find anything. I'm pretty sure something like this exists
'cron' is a way to schedule things periodically (like, every 10 minutes) on UNIX systems, Magento inherited this terminology, here you can find some details: http://www.magentocommerce.com/wiki/1_-_installation_and_configuration/how_to_setup_a_cron_job
So, algorithm plan:
for every 10 minutes
check for orders which are in Pending state and are older than (current_time -20 minutes)
revert these orders automatically
(perhaps you could send a mail to the people who have orders older than 10 minutes that heeey, don't you wanna pay?)
Related
I'm selling some stuff on my website using paypal IPN + PDT. I always check how many items are in the stock before payment. After customer makes his order, he is redirected into paypal for make payment. When payment is completed I'm updating database about selling stuff, until this moment I had no problem becouse I was selling unlimited items. I'm not sure what should I do in case where I have for example 10 items for sell, for example in this scenario:
There is last item for sell. Customer makes his order and he is going to pay on the paypal but he didn't payed yet (website still showing that there is one item for sell ), meanwhile customer B see that there is one item left in stock so he is going to buy it too. in this scenario both customers will pay but only one (faster one) get his product.
What I must do to dont make this happen ?
I can't give you a code answer without seeing yours first, but here's how it could be done on paper :
When customer A clicks the "Pay" button, the item quantity is updated in the database
If the payment goes through, do nothing, if the payment doesn't go through (cancelled, incorrect payment informations, etc) then revert the quantity back to the original
This should work fine as long as you do a final "quantity check" when the user clicks the checkout button. Let's say that both customer A and customer B have an item X in the cart, and there's only one left. They can't both pay for the item, since your system would check the quantity before redirecting to Paypal, and as soon as one of the customers do click on the button, the quantity is updated to reflect the purchase.
Drown's answer is right, and I think it's better to reserve the items (reduce them from the stock) for a period of time, for example for 20 minutes.
You need a cron job or something to give back the unpaid items into the stock.
And if you are worried about crawlers you can set another cron job to check those users who have for example 3 unpaid orders with 20 minutes interval among their payments.
You probably can check this out through the orders table in your database. Maybe you need to block these kinds of users for a while or make a better decision about them.
I've created a IPN code that allows paypal to update my database for a item purchased. I am thinking ahead though that the person buying my item, might not confirm upon checkout, or that while they are confirming check out, someone else might click the buy it now button as well before it's confirmed via paypal.
The point to all this is, I want to figure out the best way to fix this. My idea is after they click the buy now button it sets the item to pending, and they have 5 minutes to confirm the purchase or it's sent back to available.
Please help.. I can provide my code if needed.
I'd suggest using something like Resque - there is a PHP port (https://github.com/chrisboulton/php-resque).
When the user goes to PayPal, set the status of the product to be 'reserved', and create a Resque job that's scheduled to run 5 minutes from now.
If the user buys the product, change the status from 'reserved' to 'sold'.
When the Resque job runs after 5 minutes, it checks whether the status is 'reserved', and if it is, it changes it back to 'available'.
If the status is 'sold', then it does nothing.
If you don't want to use Resque, then you could do something a bit more simple like a cron job that selects all products that with a status of 'reserved' where the status was set more than 5 minutes ago. Then you change that status to 'available' again. You can run that cronjob every 60 seconds.
However, this can get into complicated race conditions, and it will be less flexible, so I'd implement a queue-based system if you can.
First sorry that I cant comment, cause of my lvl here. So your idea with locking it is user friendly and 5 minutes would be okay. But I would PayPal update my stock, when the payment is finished. who pays first... But I would program a ajax script which checks the stock for the user, who has this item in the basket and when the stock changed to 0 i would do an alert message like
alert('Item Xy changed his state to 0');
can i ask if what code should i put in my .php in order for my site to update values after a successful purchase using paypal sandbox? i'm already done with making transactions in paypal sandbox.. the problem is, how can it reflect to my site?
example a simple game that you should purchase coins in order to buy items:
MySite (has a current coins of 0) > after i choose to purchase 5 coins for $3 > make successful payment > then going back to my site it should have the value of 5 coins now..
Store the values you're talking about in some form of database, then make your php script update them after each successful payment (afaik, payment systems usually allow to specify some kind of a callback function, which will be execute when transaction is complete). You'd also add a logic for fetching these values from the DB when the start page is shown.
I have been developing an online retail shop.
It is written in php and uses paypal and IPN to handle payments.
I have written my own shopping cart. When the user wants to checkout they click on the checkout button which has the standard cart upload function wrapped around the button and the user is taken to paypal to complete payment. Paypal then sends me an IPN to notify me of the payment.
My question is, at what point should I store the order and when should the stock levels be reduced?
The standard process flow is that I have right now is as follows:
User adds item to cart.
If item is now sold out or the quantity added is more than available, the cart is updated to reflect this.
However, stock added to the cart does not reduce stock levels.
User clicks checkout.
The cart is loaded into an order record in the db AND the stock levels are reduced.
User is taken to paypal to complete payment.
(a) User completes payment.
(b) User does not complete payment by either returning to website or going somewhere else / closing browser.
(Optional) User clicks return to website.
User sees a 'thank you, order complete' complete page.
Nothing is processed relating to the order table since paypal will send IPN anyway.
Paypal sends IPN
Update order with the transaction status
As you may see, there are some issues with this process. If the customer leaves the paypal page without completing payment I will have a 'dangling' order and since stock levels are also reduced this stock will not be available to other customers! A solution to this is to manually 'clean' the database every so often.
Alternatives?
option I) Do not store the order in the database until a 'completed transaction' IPN is received, then use the cart info stored in the session to create an order and reduce stock levels. However, sessions can expire and paypal payments might take days depending on payment.
option II) Store the order as is now but do not reduce stock levels until completed transaction IPN is received. This still has the issue of dangling orders but at least no stock will have to be re added again when cleaning up, I'll just have to remove the orders. Another problem with this though is that if multiple people order at similar times and thus collectively their orders contain quantities that exceed stock. This could be quite chaotic when the system receives completed IPNS and then reduces stock levels to negative quantities!
I have looked everywhere on the internet for some sort of help, but it is not mentioned anywhere! Everyone just skips to how IPN should be handled. I just don't understand how other people could not have had this problem?!
Please help!
You're dealing with the same problem that airline reservation systems have for ages. Use the same solution ie
1.Upon user clicking checkout (while being redirected to Paypal)
reduce inventory count
place a timestamp in the database along with a state that this order is temporary
2a. Once you receive an IPN ie know the billing has been successful
change state of the order to permanent
2b. Have a cron job that runs every few minutes to track temporary orders. If temporary orders are from a time greater than what you allow eg 20 mins then:
remove the temporary order from database
undo the change in inventory count
As both a merchant and a developer, I prefer to adjust inventory stock with the IPN, even if that IPN is pending (eg. an eCheck). The chance of 2 customers going through checkout at the same time with your last remaining stock is typically low. If you do have high enough volume and low stock levels (why would you?) then you may want to do something in the cart to place locks on the items for the duration of the session timeout.
Make sure your order processing code returns the inventory to stock if the order is canceled or returned.
I have finally got my paypal system working using IPN and a reservation system to ensure that two people do not buy the same product.
The problem is, the reservations last for 10 mins on my application. If a user reserves the product the 'timer' starts, he clicks pay and ends up on paypals website. He then leaves the computer for 10 mins and comes back. He then buys it. By now though the reservation is up and it is possible that someone else could have already bought it.
Is it possible to send a time limit with the paypal IPN request to stop this happening?
As far as I know, you cannot specify that a transaction has to close within a certain amount of time with paypal.
However, I see two options you can use:
Offer a full refund if they purchase and the product is not available. You would check during the ipn notification of the purchase and if it is not available, then refund. You might be penalized by paypal if this happens a lot, but I don't have a lot of experience with offering refunds.
You can specify that the button needs to check inventory see "Step 2 – Tracking Inventory With Your Buy Now Button" in the standard payments guide. Once the product becomes sold out, you use the api to notify paypal the inventory is zero (if there is an api, you might have to use the website for this), and they should be able to notify the user there is zero inventory. I don't have experience with this either, but it seems more complicated than #1, and I would probably go with #1 if this didn't happen a lot. I think in the end you still end up having to issue a refund if the user goes through with the transaction even after seeing there is zero inventory, but I'm not sure about the wording in the docs.