Paypal cancel order url still creating order instead of cancelling it (for NopCommerce 4.2)

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
3 years ago
I discovered a problem when a customer creates an order and decides to pay via PayPal (using the NOP PayPal plugin), but cancels their payment to PayPal by clicking the "cancel and return to whatever.com website" link on the PayPal page.  When they click the link, they are taken to the final checkout page in NopCommerce and the order is "Placed" instead of being cancelled.
This creates an order with the payment type of PayPal and the payment status of "Pending".
Anyone know how to remedy this problem?
3 years ago
Yes as a redirection payment method the payment is done after the order is created.
To cancel the order in the case you have identified you would need to customise the plugin.

Yes you can cancel on return but I am guessing there is no special message sent from paypal to say it was a cancel. If you want to do the cancel automatically on return there is a problem to consider - what do you do if if the payment is made and there is a disconnect before receiving the “order is paid” message from PayPal do you still delete the order automatically and have no later record for the actual payment that was made fpr the orginal order which is now deleted?

Hence the reason for the manual process to delete the cancelled order.

More info https://developer.paypal.com/docs/api-basics/notifications/payment-data-transfer/
3 years ago
Ah okay.  I was hoping PayPal distinguished between a payment rejection (for whatever reason) verses someone who simply clicked on the "Cancel and return to .... [website] ..." (never hitting the final submit button) after they logged in.
3 years ago
Actually payment redirect create order then try to get payment from customer so customer get order complete page if still payment is cancel. you have to modify the code of paypal to solved your issue.
3 years ago
Actaully had a proper look - there is a Cancel Function
So you could modify the Routine as below
But be aware the above condition I highlighted can still apply if the order is deleted and the payment did get made - hopefully the cancel return from PayPal always works reliably.
        
        public IActionResult CancelOrder()
        {
            var order = _orderService.SearchOrders(_storeContext.CurrentStore.Id,
                customerId: _workContext.CurrentCustomer.Id, pageSize: 1).FirstOrDefault();

            if (order.PaymentStatus == PaymentStatus.Pending)
            {
                if (_orderProcessingService.CanCancelOrder(order))
                    _orderProcessingService.CancelOrder(order, false);
                order = _orderService.GetOrderById(order.Id);
                if (order != null)
                {
                    if (order.OrderStatus == OrderStatus.Cancelled)
                        _orderService.DeleteOrder(order);
                }
            }
            else if (order != null)
                return RedirectToRoute("OrderDetails", new { orderId = order.Id });

            return RedirectToRoute("Homepage");
        }
3 years ago
I've found it useful to see if AuthorizationTransactionId is NULL in the database.  If there is no value, then no payment was issued (the user should not see any charge - pending or otherwise - on their PayPal account).
I'll post the changes here when I've worked it out.
3 years ago
This checks for a transactionId as well.
The only issue now is that the order receipt is sent BEFORE 3rd party transactions (PayPal included) are complete, so I need to write code in the SendNotificationsAndSaveNotes function to not send notifications, then add a function somewhere to do the check again.  This is a HUGE logic flaw in NOP (I hope this is fixed in future releases) - sending notifications before payment processing is complete.

        public IActionResult CancelOrder()
        {
            var order = _orderService.SearchOrders(_storeContext.CurrentStore.Id,
                customerId: _workContext.CurrentCustomer.Id, pageSize: 1).FirstOrDefault();

            if (order.PaymentStatus == PaymentStatus.Pending && order.AuthorizationTransactionId == null)
            {
                if (_orderProcessingService.CanCancelOrder(order))
                    _orderProcessingService.CancelOrder(order, false);
                order = _orderService.GetOrderById(order.Id);
                if (order != null)
                {
                    if (order.OrderStatus == OrderStatus.Cancelled)
                        _orderService.DeleteOrder(order);
                }
            }
            else if (order != null)
                return RedirectToRoute("OrderDetails", new { orderId = order.Id });

            return RedirectToRoute("Homepage");
        }
3 years ago
beefydog wrote:

(order.PaymentStatus == PaymentStatus.Pending && order.AuthorizationTransactionId == null)
This checks for a AuthorizationTransactionId as well.

These two checks are logically the same thing - I mean if the status is != Pending then the status was set to Paid at the same time AuthorizationTransactionId was changed - so not sure what extra check it provides ?

beefydog wrote:

The only issue now is that the order receipt is sent BEFORE 3rd party transactions (PayPal included) are complete, so I need to write code in the SendNotificationsAndSaveNotes function to not send notifications. This is a logic flaw

I dont know what the flaw is - this the way it works and the way it has always worked for Redirect payment mthods. If you dont want to send the Order Placed email turn it off and send the Order Paid email instead
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.