Skip to content

Commit 0e98a3d

Browse files
committed
feat(paypal): add rounding adjustment to fix amount mismatch
Introduce a new method `fixPaypalAmountMismatch` to handle edge cases where the calculated total does not match the expected grand total due to floating point precision issues. This ensures accurate totals are sent to the PayPal API. The method adjusts either the discount total or adds a rounding adjustment item to reconcile any discrepancies.
1 parent fcc5421 commit 0e98a3d

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

app/code/core/Mage/Paypal/Model/Order.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ public function buildPurchaseUnit(Mage_Sales_Model_Quote $quote, ?string $refere
191191
$totals = $adjustedCartData['totals'];
192192
$items = $adjustedCartData['items'];
193193

194+
$fixedCartData = $this->fixPaypalAmountMismatch($cart, $currency);
195+
$totals = $fixedCartData['totals'];
196+
$items = $fixedCartData['items'];
197+
194198
$breakdown = $this->buildAmountBreakdown($totals);
195199
$amount = $this->buildAmountWithBreakdown($currency, $quote->getGrandTotal(), $breakdown);
196200

@@ -347,6 +351,61 @@ public function adjustCartTotalsForRounding(Mage_Paypal_Model_Cart $cart, string
347351
return ['totals' => $totals, 'items' => $items];
348352
}
349353

354+
/**
355+
* Fix amount mismatch edge cases for PayPal API by adding rounding adjustments
356+
*
357+
* @return array{totals: array, items: array}
358+
*/
359+
public function fixPaypalAmountMismatch(Mage_Paypal_Model_Cart $cart, string $currency): array
360+
{
361+
$totals = $cart->getAmounts();
362+
$items = $cart->getAllItems();
363+
364+
$itemTotal = isset($totals[Mage_Paypal_Model_Cart::TOTAL_SUBTOTAL])
365+
? (float) $totals[Mage_Paypal_Model_Cart::TOTAL_SUBTOTAL]->getValue()
366+
: 0.00;
367+
368+
$taxTotal = isset($totals[Mage_Paypal_Model_Cart::TOTAL_TAX])
369+
? (float) $totals[Mage_Paypal_Model_Cart::TOTAL_TAX]->getValue()
370+
: 0.00;
371+
372+
$shippingTotal = isset($totals[Mage_Paypal_Model_Cart::TOTAL_SHIPPING])
373+
? (float) $totals[Mage_Paypal_Model_Cart::TOTAL_SHIPPING]->getValue()
374+
: 0.00;
375+
376+
$discountTotal = isset($totals[Mage_Paypal_Model_Cart::TOTAL_DISCOUNT])
377+
? (float) $totals[Mage_Paypal_Model_Cart::TOTAL_DISCOUNT]->getValue()
378+
: 0.00;
379+
380+
$expectedTotal = round($itemTotal + $taxTotal + $shippingTotal - $discountTotal, 2);
381+
$grandTotal = (float) $cart->getQuote()->getGrandTotal();
382+
$difference = round($expectedTotal - $grandTotal, 2);
383+
384+
if (abs($difference) > 0) {
385+
if ($difference < 0) {
386+
$newDiscountTotal = round($discountTotal + abs($difference), 2);
387+
$totals[Mage_Paypal_Model_Cart::TOTAL_DISCOUNT] = MoneyBuilder::init(
388+
$currency,
389+
number_format($newDiscountTotal, 2, '.', ''),
390+
)->build();
391+
} else {
392+
$moneyBuilder = MoneyBuilder::init($currency, number_format($difference, 2, '.', ''))->build();
393+
$roundingItem = ItemBuilder::init(
394+
Mage::helper('paypal')->__('Rounding Adjustment'),
395+
$moneyBuilder,
396+
quantity: '1',
397+
)
398+
->sku(Mage::helper('paypal')->__('rounding_fix'))
399+
->category(ItemCategory::DIGITAL_GOODS)
400+
->build();
401+
402+
$items[] = $roundingItem;
403+
}
404+
}
405+
406+
return ['totals' => $totals, 'items' => $items];
407+
}
408+
350409
/**
351410
* Update payment object with PayPal order information
352411
*/

0 commit comments

Comments
 (0)