@@ -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