Developer forum

Forum » Development » CheckoutDoneOrderIsComplete

CheckoutDoneOrderIsComplete

Michael Nielsen
Reply

On a webshop that sends orders to the suppliers via webservices, we are having some problems with 

Dynamicweb.Notifications.eCommerce.Cart.CheckoutDoneOrderIsComplete

(see attached code.png for code example)

It fires multiple times, which is probably caused by this

CheckoutHandler Redirecting to checkout handler: Dynamicweb.eCommerce.Cart.CheckoutHandlers.QuickPayPaymentWindow

being called multiple times on the order (see attached order log)

DynamicWeb has classified it as a bug #27719
http://developer.dynamicweb-cms.com/releases/known-bugs.aspx 

which should be fixed sometime next week. 

However, upgrading is not an option right now, so we are looking for alternative solutions, e.g. is there a way to find out if it is the first time CheckoutDoneOrderIsComplete has been fired, or anything else?

code.png log.jpg

Replies

 
Nicolai Pedersen
Reply
This post has been marked as an answer

Hi Michael

It is a really tricky one - and it happens because of long lasting server-to-server callbacks from the payment gateway. So we have 2 contexts - the user and the payment callback and those 2 have to communicate to each other that it happened.

In you code above, it should be fairly simple to add a check. In your OrderComplete method, first add a Synclock on the entire content of the method. On your EksportToKOEBT class, add a static property of type ConcurrentDictionary, call it i.e. ProcessedOrders or something. Inside your synclock, check if the Order.ID exists in the dictionary, and if it does, return from the method. If it does not exist, the order has not been processed and you process it and add the orderid to the dictionary.

BR Nicolai

Votes for this answer: 1
 
Michael Nielsen
Reply

Hi Nicolai

Thanks for the answer.

Wouldn't that limit for only one order to be handled at a time?

But if it's the best solution for right now, then that will have to do.

 

 
Nicolai Pedersen
Reply

Hi Michael

Yes it would. So of course it is a problem if your order processing takes time.

But it is 2 incoming requests from different endpoints - so you need a way to tell the difference. You could change the behavior of my suggestion to have the synclock in the OnNotify method and if the OrderID is in the dictionary return from the method. So the synclock will not be encapsulating the actual order processing, but just the check on the dictionary. You might not even need the synclock if you are using a concurrent dictionary.

BR Nicolai

 
Michael Nielsen
Reply

For anyone else, who this might help, this is the solution we went with

public class ExportedOrderCollection
{
        private static ConcurrentDictionary _instance;

        public ExportedOrderCollection()
        {
            if (_instance == null)
            {
                _instance = new ConcurrentDictionary();
            }
        }

        //Will return true if this order is exported.
        public bool IsAlradyExported(Order order)
        {
            if (_instance.TryAdd(order.ID, order))
            {
                //2min in ms
                Timer timer = new Timer(2*60*1000){
                    AutoReset = false
                };
                timer.Elapsed += (sender, args) => {
                    Order trash;
                    _instance.TryRemove(order.ID, out trash);
                    timer.Dispose();
                };
                timer.Start();
                return false;
            }

            return true;
        }
}

private void OrderComplete(Order dwOrder)
{
            ExportedOrderCollection alreadyExported = new ExportedOrderCollection();
            if (alreadyExported.IsAlradyExported(dwOrder))
            {
                return;
            }
(...)
} 
 
Nicolai Pedersen
Reply

Nice.

Thanks for sharing!

 

You must be logged in to post in the forum