EUR currency was getting saved in all refunds for non EUR currencies.#255
EUR currency was getting saved in all refunds for non EUR currencies.#255knit-pay wants to merge 4 commits into
Conversation
Prevent the default Money currency (EUR) from leaking into the refunded amount for non-EUR payments.
There was a problem hiding this comment.
Code Review
This pull request updates src/Plugin.php to prevent the default EUR currency from leaking into refunded amounts for non-EUR payments by explicitly setting the refunded amount's currency to match the payment's total amount currency. The reviewer pointed out a broader issue where unrefunded non-EUR payments will still default to 0 EUR due to how the refunded amount is initialized in the Payment class. They recommend refactoring Payment::get_refunded_amount() in a follow-up to dynamically set the currency and resolve this display bug globally.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| // Prevent the default Money currency (EUR) from leaking into the refunded amount for non-EUR payments. | ||
| $refunded_amount->set_currency( $payment->get_total_amount()->get_currency() ); | ||
|
|
There was a problem hiding this comment.
While this fix successfully prevents the default EUR currency from leaking into the refunded amount when a refund is created, there is a broader issue: any non-EUR payment (e.g., USD) that has not been refunded yet will still return 0 EUR when $payment->get_refunded_amount() is called. This is because refunded_amount is initialized as new Money() (defaulting to EUR) in Payment::__construct and is never updated unless a refund is processed.
This can lead to UI display bugs where unrefunded USD payments show a refunded amount of €0,00 instead of $0.00 in dashboards or reports.
Recommendation
A more robust and centralized solution would be to ensure that the refunded amount's currency always matches the payment's total amount currency directly within the Payment class. For example, we could update Payment::get_refunded_amount() to dynamically set its currency if it doesn't match the total amount's currency:
public function get_refunded_amount() {
if ( $this->refunded_amount->get_currency() !== $this->get_total_amount()->get_currency() ) {
$this->refunded_amount->set_currency( $this->get_total_amount()->get_currency() );
}
return $this->refunded_amount;
}Since Payment.php is not part of this pull request's diff, we can keep this local fix in Plugin.php for now, but it is highly recommended to refactor this in the Payment class as a follow-up to fix the display bug for unrefunded payments.
|
@copilot It does not seem correct to me to update the currency when a refund currency does not match the currency of the original payment. |
There was a problem hiding this comment.
Pull request overview
Fixes a currency-mismatch issue where a refunded amount could retain the default Money currency (EUR) for non-EUR payments by attempting to align the refunded amount currency with the payment total amount currency.
Changes:
- Adds a currency alignment check in
Payment::get_refunded_amount()to prevent EUR from “leaking” into non-EUR refunded amounts.
|
@knit-pay we prefer to avoid this kind of logic in a get method, see my earlier comment:
When creating refunds, the correct refund currency must be set. It is inconvenient that when creating a new payment, this is set to EUR by default by calling wp-pay-core/src/Payments/Payment.php Lines 144 to 164 in 8627aaa It is also inconvenient that we potentially just add different currencies together: Lines 1126 to 1161 in 8627aaa Actually, you can't just add different currency amounts together; that might be a design flaw in https://github.com/pronamic/wp-money/blob/f2762d981b1d6ab8739b6f74a9f5ff21bd759efc/src/Money.php#L275-L286. In https://github.com/moneyphp/money/blob/d49ee625c6ba79b9d7a228ce153b02fc1032152b/src/Money.php#L199-L220, for example, that is also not possible and results in a |
|
Thanks @remcotolsma I will check this and update the code accordingly. Or you may also do it, if it's a small change and if you have already checked how to do it properly. |
|
Today I got some time to review the comments and code again. You are right about this. I also noticed this while reviewing the code today. I raised the issue at pronamic/wp-money#11
You are right about this. It was my mistake to blindly follow the suggestion by Gemini and implement what it said during the review (#255 (review)). At first glance it was looking fine.
|
|
Kindly check the new logic. What is your opinion on this? |
|
Thanks for the update. After analyzing the problem, we've arrived at the following insights (with the help of AI): 1. How problematic is 0 EUR vs 0 USD really?Mathematically, a zero amount has the same value regardless of currency. The problem only surfaces when you try to add this to an amount with a different currency: $payment->get_refunded_amount()->add( $refund->get_amount() );
// 0 EUR + 50 USD = ❌ Currency mismatchThis is the real issue—not the fact that the initial 2. Current approach feels like patchingThe current PR adds the same logic in two places:
This feels defensive and scattered. If we add this logic, we'd prefer it to exist in one central place. 3. Single Responsibility PrincipleWe considered solving this in public function set_total_amount( Money $total_amount ) {
$this->total_amount = $total_amount;
// Auto-sync refunded_amount currency
}This works, but doesn't feel quite right—a setter for Better approachWhen creating and adding refunds, the correct currency should simply be set by the code responsible for doing so: // In create_refund() or refund-creation flow:
$refund = new Refund( $payment, new Money( $amount, $payment->get_total_amount()->get_currency() ) );This way:
What's your take on this? |
|
Hello @remcotolsma
In WooCommerce, we are already passing the currency during refund. kindly refer As per my understanding in the code below, these are the meaning of the variables used. Kindly correct me if I am wrong.
Because Before setting the currency, I am considering 2 things.
I hope this explaination would help you understand the changes in a better way. What is your opinion on this? Do you still think we need to change anything? |
|
Yes, I think we’re aligned on the immediate issue. What do you think about this approach?
This keeps the currency setup centralized in |
|
@remcotolsma, I agree, your structural approach is better. It fixes the root cause (EUR default in Payment::__construct) rather than patching at refund time. I have below concerns about this approach. Kindly share your opinion on this. I think we will still have to keep the changes in the file meta-box-payment-lines.php; without this, we may see incorrect currency on the payment edit page. |
Prevent the default Money currency (EUR) from leaking into the refunded amount for non-EUR payments.