Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#GCC currency - saved amount on create adyen order #1385

Closed
wants to merge 5 commits into from

Conversation

dejankar
Copy link
Contributor

@dejankar dejankar commented Mar 3, 2022

Description

  • Issue occurs on - Adyen_Payments version 7 and above

  • When display currency is KWD, or BHD data is not formatted correctly in :
    $this->adyenDataHelper->originalAmount($notification->getAmountValue(), $order->getBaseCurrencyCode());

  • Shop base currency is different than KWD, BHD, and all others mentioned for formatting here:
    \Adyen\Payment\Helper\Data::originalAmount

  • It will always format the amount based on base currency not on display currency and therefore the amount is not correctly saved here: \Adyen\Payment\Helper\AdyenOrderPayment::createAdyenOrderPayment

  • Adyen notification returns back the amount in mentioned currency that should be formatted(divided) by 1000, but since the base currency is different it falls under the default case which is /100, which leads to a wrong amount saved in the database.

Steps to reproduce the issue before the fix:

  1. Set USD as the base currency
  2. Place an order with BHD, KWD as a display currency
  3. Wait for the auth and capture notifications to be executed.
  4. Order status stays in pending payment after capture.
    Comment: order was partially authorized but it's actually the whole amount.
  5. No invoice, no status update is performed.

Tested scenarios

  • Placed orders in KWD and USD as a display currency
  • Works as expected
  • Notifications are sent and Magento handle those as needed after the fix
  • I tested only for GCC currencies which are KWD, BHD as those are we are using, but I assume the fix will work for all the rest included here: \Adyen\Payment\Helper\Data::originalAmount

Fixed issue:

- When display currency is KWD, or BHD data is not formatted correctly in :
$this->adyenDataHelper->originalAmount($notification->getAmountValue(), $order->getBaseCurrencyCode());

- It will always format the amount based on base currency not on display currency and therefore amount is not correctly saved here: \Adyen\Payment\Helper\AdyenOrderPayment::createAdyenOrderPayment

Example:
I place an order for 10BHD but in adyen_order_payment database the amount saved is 100.00 when base currency of the shop is different than BHD, KWD...
Later it crushes the whole flow of generating invoices and capturing the right amount
@tnaber tnaber self-assigned this Mar 3, 2022
@@ -214,7 +214,7 @@ public function createAdyenOrderPayment(Order $order, Notification $notification
{
$adyenOrderPayment = null;
$payment = $order->getPayment();
$amount = $this->adyenDataHelper->originalAmount($notification->getAmountValue(), $order->getBaseCurrencyCode());
$amount = $this->adyenDataHelper->originalAmount($notification->getAmountValue(), $order->getOrderCurrencyCode());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use $notification->getAmountCurrency()? Maybe that way the entity is created in adyen_order_payment with the matching currency everytime.

I see that @Morerice introduced this, do you know if we can make that change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @acampos1916 ,

thanks for replying back.

Not sure if the question is directed to me but I took the liberty to respond:
Looking at the plugin code, I believe both options will work as expected.

However, I would stick to the Magento default $order->getOrderCurrencyCode() as that's following the formatting that Magento needs always.

If you use $notification->getAmountCurrency() and in the future, you decide to change the code how webhooks pass the currency code or decide not to pass it at all, it will break the function again.

In the end, it's a matter of preference :).

I applied my solution on our live website and so far we didn't experience any bugs or problems after applying the patch.

Best
Dejena

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @dejankar. If I get it right there are multiple scenarios to cover:

Base currency A, Display currency B (getOrderCurrencyCode != getAmountCurrency)
Base currency B, Display currency A (getOrderCurrencyCode != getAmountCurrency)
Base currency A, Display currency A (getOrderCurrencyCode == getAmountCurrency)
Base currency B, Display currency B (getOrderCurrencyCode == getAmountCurrency)

If the charged currency config included in the plugin is set to Display the payment will be processed with the Display currency, but the getOrderCurrencyCode would return the Base currency. I think it is safer to use $notification->getAmountCurrency() because of that, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Angel,

Extended solution committed that checks how the Adyen plugin is set.
If it's set to use display currency then we have only one scenario actually.

  1. OrderCurrencyCode will always return the display currency code and will be matching Magento values.

  2. If plugin is set to use base currency code , we can always return the base currency code with :
    $order->getBaseCurrencyCode();

So the check I add will solve the concerns you have from the Magento side.

However, what you mentioned is not wrong and $notification->getAmountCurrency() can be used too if as mentioned you are not a plugin to change the data on your end and how data is passed from the webhooks back to Magento.

Great conversation btw 👍

Best Regards,
Dejan

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @dejankar, of course! Thanks for helping us figure this out.

I'll test your patience a bit more 😄 since the notification is being processed after the payment has been completed there's a small chance that the plugin's config for charged currency has been modified between the order placement and the webhook being received, that would set the wrong currency with your updated approach.

I would indeed suggest to use the $notification->getAmountCurrency(), to my knowledge there are no plans at all to change the format from the Adyen side and hasn't been changed for a while. It is safe to use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @acampos1916 ,

Sure it's my pleasure.

Yeah, I agree there is a small chance for the mentioned use case but in such config, the whole process might be wrong.
There might be a problem if let's say the order was placed in base currency and then someone changes the charged currency setting and then webhooks returns the values with a different currency.

That might interfere with Magento's internal logic for let's say if someone invoice later and want to capture the amount in charged currency. Than anyway the order needs to be fixed from the M2 side.

But all in all, I'm really fine with the proposal from your side: $notification->getAmountCurrency(), especially as you mentioned that format won't be changed in the future, and the field will always be called like this.

I will leave the decision for you and your team!

It's been a pleasure chatting with all of you guys :)

Looking forward to the solution and all the great stuff that this plugin offer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dejankar good point! We do have a mechanism in place so that orders are captured and refunded in the currency with which it was placed, see the docblock for this helper function.

I'm doing a suggestion with the use of the notification currency. Thank you!

peterojo
peterojo previously approved these changes Mar 11, 2022
@sonarcloud
Copy link

sonarcloud bot commented Mar 14, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 3 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

Comment on lines +225 to +227
$chargedCurrencyCode = $this->config->getChargedCurrency() === "display"
? $order->getOrderCurrencyCode() : $order->getBaseCurrencyCode();
$amount = $this->adyenDataHelper->originalAmount($notification->getAmountValue(), $chargedCurrencyCode);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dejankar would you mind doing quick check for this testing your scenario?

Suggested change
$chargedCurrencyCode = $this->config->getChargedCurrency() === "display"
? $order->getOrderCurrencyCode() : $order->getBaseCurrencyCode();
$amount = $this->adyenDataHelper->originalAmount($notification->getAmountValue(), $chargedCurrencyCode);
$amount = $this->adyenDataHelper->originalAmount($notification->getAmountValue(), $notification->getAmountCurrency());

Copy link
Contributor Author

@dejankar dejankar Mar 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dejankar would you mind doing quick check for this testing your scenario?

Hi Angel, I don't mind and I already tested your suggestion even before and can confirm that's working as expected when capturing payments.

However when refunding from the Adyen platform the amount is wrong, and always tries to refund the base amount instead of the correct amount.

I'm checking if this is related with this code or not.

Dejan

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dejankar would you mind doing quick check for this testing your scenario?

Hi Angel, I don't mind and I already tested your suggestion even before and can confirm that's working as expected when capturing payments.

However when refunding from the Adyen platform the amount is wrong, and always tries to refund the base amount instead of the correct amount.

I'm checking if this is related with this code or not.

Dejan

Seems that issue is not related with those changes and it's another issue.

So when order is placed with one of KWD, OMR, BHD as a display currency and then I try to refund from Adyen platform the full amount.

This is the response in M2:

Adyen Refund Successfully completed

IPN "Refunded". Refund issued by merchant. Registered notification about refunded amount of $15.90. Transaction ID: "". Credit Memo has not been created. Please create offline Credit Memo.

Adyen HTTP Notification(s):
eventCode: REFUND
pspReference: JR6PFJ8VBGNG5S82
paymentMethod: visa
success: true

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dejankar interesting, can you spot anything in the logs that could clarify if this is a bug?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @acampos1916 ,
Nothing in the logs that clarifies it.

The notification seems correct and data inside is correct:
[2022-03-16 09:11:43] AdyenLoggerTest.ADYEN_NOTIFICATION: The content of the notification item is: {"amount":{"currency":"KWD","value":15900},"eventCode":"REFUND","eventDate":"2022-03-16T10:10:38+01:00","merchantAccountCode":"Lens_Me","merchantReference":"1000612602","originalReference":"JXVHHCW6PP4WHD82","paymentMethod":"visa","pspReference":"JR6PFJ8VBGNG5S82","reason":"","success":"true"} {"is_exception":false} []
[2022-03-16 09:11:43] AdyenLoggerTest.ADYEN_NOTIFICATION: The result is accepted {"is_exception":false} []

I guess it's the same issue how the amount is being formated when sent back from Adyen webhooks, but will debug later on and get back when I have more info.

It's not a general bug as i tried the same with our base currency and a refund was successfully created.

Best Regards,
Dejan

@raoulritter
Copy link
Contributor

raoulritter commented May 26, 2023

Hi @dejankar

Charged currency should have been fixed in #1789 and refunds in #1772 so this can be closed. If there is still an issue please create a new issue that we can then check and verify the fix.

Kind regards,

Raoul

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants