Adding additional cart items during checkout dilemma - php

I am having a problem on an e-comm site i am trying to build where it's possible for a user to add additional cart items when checking out with the SecurePay payment gateway.
When the user clicks 'pay now' button, they are redirected off site to the SecurePay payment page where they enter their credit card information. It's here where its possible for the user to open another page and add/remove cart items after the payment information has already been sent to the payment gateway without me being able to detect it. The shopping cart is a database shopping cart with a cookie as a unique identifier to remember the user.
The problem is that there is no input fields to for any product data in the SecurePay form that's sent to the payment gateway, you can only specify limited information about the order, ie, the total $ amount of the order including shipping(can't even send shipping total separately), a reference number(invoice number) and the currency type(AUD), surcharge percentage etc. So i have to process everything based on the the users shopping cart after the order is successful and they are redirect back to my site. If the user add/removes cart items while they are paying offsite, it is then reflected when i generate the invoice and do the stock take on the order completion page.
Im just not sure how to combat this.
My possible scenario:
I lock the cart when the user hits the checkout page, then unlock it if they hit any other page than the checkout page. Though then there is no possibility of any up selling without taking the user completely out of the checkout process and i'm also worried about any possible scenarios where if the user returns to the site their cart may still be locked. Plus maybe it seems a little messy/hackish of a solution?
I did test a couple random e-comm sites, and it was also possible to add additional cart items from another page during the 'pay now' stage of the checkout process without it detecting the additional cart items unless you actually manually refresh the page. Though i did not verify by actually paying for the items, but i can't see how it would be any different to my problem.
Does anyone have any suggestions?

I initially thought this kind of behaviour was a bug until I learned about upselling. So my solution to this (if I ever needed one), is to make sure every checkout process is a new order, and not a update. And add a hook, to let the user know about the new order, and give an option to discard (clear out) items currently in the cart.

If you can send a reference number, why not use that to generate the order? Whenever the user goes to pay, create an order with the items in their basket and send that number to SecurePay. When the payment is complete mark that order as paid for. If they change the contents of the basket then the old reference number will still refer to the products originally in the basket and if they go to check out again a new order will be created with the correct items in it.

There could be an option - that when the user is redirected back to your site - that secure pay could pass back some information including the amount charged. Then you could check and confirm that figure against whatever is in the cart.
Or - I'm looking at the secure pay developers page and they have two different methods where the customer would never leave your website.
https://www.securepay.com.au/developers/products-and-services/accepting-e-commerce-payments/
Are you in Australia - if yes you could also look at Stripe, it might be easier https://stripe.com/au/pricing

Related

Prestashop cart and order lifesycle, how to "confirm" a cart and let it become an order coming from external payment method

Good day all. I'm developing a payment module on Prestashop 1.7.
the payment process is external, and before the redirection I had to make a POST on their server in order to create a token, then redirect to them and "wait" for the user to come back on the store.
I'm trying to figure out the best approach to this and the correct loop to be done with cart and order.
1) the user arrive on the checkout page (he has a cart, but not an order)
2) the user choose the payment method.
3) upon clicking the button, the user is sent to the "preparation" controller (still has a cart and no order)
4) the front controller called "preparation" will execute a POST to the payment gateway, and with the response, will redirect the user to their gateway (and I will pass them a "returnUrl" that point to my "confirmation" controller).
5) the user is on their gateway, he will do some gateway things.
6) the user is sent back to Prestashop, on the returnUrl I had given before, some data will be attached to this.
7) here it is my concern:
to confirm the order, I have to redirect the user to:
Tools::redirect('index.php?controller=order-confirmation&id_cart='.$cart->id.'&id_module='.$this->module->id.'&id_order='.$this->module->currentOrder.'&key='.$customer->secure_key);
but actually I don't have a "id_order" right? I didn't confirmed the cart and trasfromed it into an order yet... right?
Do I have to make a:
$this->module->validateOrder($cart->id, Configuration::get('PS_OS_BANKWIRE'), $total, $this->module->displayName, NULL, $mailVars, (int)$currency->id, false, $customer->secure_key);
before redirecting the user to the order-confirmation?
is all of this true, or I didn't understand nothing about the transformation of the cart into an order?
thanks in advance.
Yes you have to call validateOrder() method to transform cart into order.
On step 4 you pass a redirectUrl to your own controller in shop which will validate an order and then redirect to success page.
One thing you have to be careful about is cart manipulation while the user is on payment gateway page. When a user is redirected to payment gateway, the cart is still active and he can open the shop in another tab and manipulate his cart (add, remove, choose different shipping etc.) and then click Pay button on the gateway page, so before redirecting the user to the payment gateway, make sure you store cart total value in your custom table and before you validate an order, make sure that the amount is the same or I think Prestashop will do that for you in validateOrder() by comparing cart amount and paid amount and set the Payment error status on the order if the amounts don't match (It's been a while since I touched prestashop so I'm not sure).

Is it possible to send multiple ids via Paypal custom Field?

i have a Custom Cart Page which i have built its pretty standard, what i am trying to do is send all the ids of the items in the cart when the user clicks checkout so the user flow is as follows:
1) User Click Checkout
2) Packages added to table one row each item with waiting payment status.
3) User goes to paypal and pays
4) Paypal Ipn picks up payment and order ids via custom field and updates payment status of orders.
So essentially the paypal pay will be a single total payment as opposed to displaying each item. Is it possible to send all item ids via one custom field or do i have to implement a cart style paypal feature which i don't really want to?
I don't see any reason why you can't put a series of Id values in the custom field, perhaps comma separated, but it is only 255 characters long. You would have to parse the field in your IPN handler to separate out the id values again.
But I would suggest using PayPal's cart handling instead, there are no problems with how many items you have to process and also the customer sees a proper list of the items they have bought when they go through the PayPal payment process. More robust and friendlier to the user.
You may find PayPal's Third Party Shopping Cart documentation useful

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.

Paypal IPN Inventory Control

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.

Model cart locking with Paypal

I'm currently implementing Paypal Express Checkout within a Zend Framework Application, I wrote my own cart model which consist of two simple class Cart & CartItem, and they are able to se quantity, get total price, etc.
I'm not much aware on payment system, and I only use Paypal (it's my first time), but I though since I'm not able to control what's happing there (at Paypal) it is a good idea to "lock" the Cart at the beginning of the process (when redirecting to Paypal) to avoid inconsistencies over the current Order processed by paypal and the actual cart on the website.
It can happen for example if the user open a new tab and try to add products while he is a payment process with paypal.
If your cart is locked the use is not able to add or remove anything from its cart until he finished to process the payment thorough paypal or cancel its order.
My question is do you think it is a good approach?
Edit: The reason I don't store anything in the database but only the shopping cart in session is all order are stored with Paypal, so I don't want to store it twice, it is a really really simple system.
I've done it a different way.
When the user browses the site, the cart is stored using a session, a cookie or whatever.
Once he clicks the "pay" button, the content of the cart goes to a orders datable table with a unique ID.
You delete the session or the cookie to prevent him to add new stuff to the order.
You use the unique ID to give it to paypal. Once the payment is done, Paypal comes back to you with IPN, and gives you back the unique ID. From that you know it's paid and can put a boolean or something in your orders table.
Sometimes the user won't pay, and you'll have some never paid orders. You should have a cron that check orders older than one day and remove them from the table.
I think your approach is fine. But make sure you inform the users why they can't add items to cart and offer an easy option to unlock the cart.
Use case:
fill cart
start payment
ah, I forgot the socks
close payment tab
shop opened in other tab
add socks
"you can't add, it's locked"
I can't return to payment to cancel it and can't add anything to cart => i leave

Categories