craftcms / commerce-paypal-checkout

PayPal Checkout gateway for Craft Commerce.
https://plugins.craftcms.com/commerce-paypal-checkout
MIT License
5 stars 10 forks source link

[Bug] Cannot mark as refunded when PayPal has already processed it. #38

Closed OwenMelbz closed 2 years ago

OwenMelbz commented 3 years ago

Description When trying to mark a previously refunded order as refunded via the CMS errors when it's already been handled in PayPal, in this case due to a customer opening a case against the order.

The API comes back with....

{
   "message":{
      "name":"UNPROCESSABLE_ENTITY",
      "message":"The requested action could not be performed, semantically incorrect, or failed business validation.",
      "debug_id":"111",
      "details":[
         {
            "issue":"CAPTURE_FULLY_REFUNDED",
            "description":"The capture has already been fully refunded"
         }
      ],
      "links":[
         {
            "href":"https://developer.paypal.com/docs/api/payments/v2/#error-CAPTURE_FULLY_REFUNDED",
            "rel":"information_link"
         }
      ]
   }
}

To Reproduce How, and what happened?

  1. Place an order
  2. Refund the payment within PayPal
  3. Try refund the payment via the CMS

Expected behavior The error/message to display - However you should still be marking the order as refunded - as currently this is blocking the management of the order when it should be resumable.

Versions Everything basically up to date or N/A

nfourtythree commented 2 years ago

Hi @OwenMelbz

Thank you for your message. Similarly to other gateways, this is expecting that you either do all your transaction management in either the Commerce control panel or logged into your gateway. At the moment there is no syncing of transactions (although this is something to think about).

At the moment this plugin does not support webhooks (something that would be required for the above), this is a feature that has been requested and is on the list for us to look into.

Thanks.

OwenMelbz commented 2 years ago

Hi,

Sorry I think this was misunderstood.

The "expectation" as mentioned isn't that it syncs the order. The expectation is that the CMS doesn't crash.

Eg when you click the refund button in the CMS, it should still mark the order locally as refunded. Or at a minimum give an appropriate error message saying it can't refund it due to XYZ.

nfourtythree commented 2 years ago

Hi

I have tested this with the latest version of Commerce and the plugin and it seems to work as expected. Video here

What version are you working with?

Thanks.

OwenMelbz commented 2 years ago

Which ever version was the latest 1 year ago 😂

From the video, the CMS no longer crashes, but you can see that it's not updating the order status to refunded.

This creates a problematic user experience for both admins and users.

An ideal situation is that this should still be able to have the status of the order changed to refunded, just like how you can make an offline payment, you can make an offline refund... 👀

nfourtythree commented 2 years ago

Hi

Thank you for the update.

Referring to my first response, the idea of synchronizing the transactions is definitely something that is on our radar as it would provide the best user experience. And, as mentioned, to make that happen this plugin would also need updates to be able to support webhooks incoming from PayPal (the feature request I linked to).

Thanks!

OwenMelbz commented 2 years ago

Sorry, not sure if I follow? No synchronising is needed at all.

It's simply "if I click refund order" I expect the status of the order to be "refunded" regardless of what some 3rd party api says.

nfourtythree commented 2 years ago

Take the following scenario:

Person A goes into the PayPal dashboard and refunds (or even partially refunds) order number 123. At this point, PayPal is fully aware of the state. But because this plugin currently does not support webhooks, Commerce is entirely unaware that this has happened and therefore continues to show the order as paid.

Person B logs into the Commerce control panel and sees that, as far as they know looking at the screen, order 123 has not yet been refunded. They click the refund button expecting that to happen at that moment. Behind the scenes, we get an error response from PayPal saying the refund has already happened but aren't provided with any further information (IDs, references etc). At this point we could try to look for the refund in PayPal but looking at the API docs I can't see anything in the capture details response (the only thing we have an ID for and are therefore able to retrieve) that would lead us to the refund data. The only way to retrieve the refund details is by its PayPal-generated ID which, in this scenario, we don't know.

We could, in theory, add a "dummy" refund child transaction but then the dates won't match up with what is in PayPal, and also what if Person A had refunded a different amount to what Person B is trying to do.

This all leads back to the things I initially pointed out. In its current state and the advice we give with most gateway plugins (that don't have synchronisation support) is that things should be managed in one place, either the gateway dashboard or in Commerce and that is the source of truth.

Obviously, this would be solved properly with in introduction of webhooks support.

Hope this explanation helps and we always welcome pull requests if people are looking to improve the code, add features etc.

Thanks!

OwenMelbz commented 2 years ago

Hi,

Sorry maybe I am missing something lol, very likely. But I'm not sure why this whole section is needed?

At this point we could try to look for the refund in PayPal but looking at the API docs I can't see anything in the capture details response (the only thing we have an ID for and are therefore able to retrieve) that would lead us to the refund data. The only way to retrieve the refund details is by its PayPal-generated ID which, in this scenario, we don't know.

We could, in theory, add a "dummy" refund child transaction but then the dates won't match up with what is in PayPal, and also what if Person A had refunded a different amount to what Person B is trying to do.


I'd be pretty confident in the fact most users after receiving the unexpected response would be fine with it. As long as they can just have the order marked as refunded within the CMS.

The current situation leads to orphaned orders sat in the CMS with inaccurate states, the customers left confused with odd order histories, admins left frustrated with stuck functionality and reports which don't add up.

From the outside, a simple route to a solution is when you click refund, if it fails for whatever reason, you still have a clear and visible option to mark the order as refunded so that the state can be manually overwritten.

This seems like a much better overall experience than being left with dead order order which nobody can fix?