0

i have integrated paypal adaptive payment system in a website, but i get an error while i checkout that if the amount upto 2 decimal places is not rounded off, the fractional amount could be lost. what is the solution to this? I am currently rounding off the amounts, but any idea how to get the fractional amount too?

  • What currency are you using that uses more than two digits to the right of the decimal point? US currency's smallest unit is one cent (0.01), and there is no smaller *fractional amount* than 1/100 of a dollar. The solution is proper rounding, so that fractional cents get rounded up (or down) appropriately. You can't very well tell a customer *Your cost is $11.125*, when that's not what's going to appear on their statement. – Ken White Oct 03 '17 at 17:34

2 Answers2

1

You have to make sure that the amount you're sending to PayPal is rounded properly for the currency. This means that a US dollar amount would have at most 2 subunits (cents).

If using the adaptive pay ruby gems and still experiencing issues:

Another issue that I recently ran into with their ruby gems is that they use floats instead of decimals, which is a bad practice for monetary values. Floats are inaccurate. For example in ruby...

2.20 - 2.01 = 0.1900000000000004

If you're properly setting the amount's subunits when passing in the param to their build_pay method and you're still getting the error...

If the fractional amount is rounded for currency conversion, funds could be lost

then the issue may very well be within their gem's use of float. Your logs will show this, and you can test it by using the amount 715.57, which their gem sends to their api as 715.57000000001 because of their use of .to_f in their paypal-sdk-core gem.

To fix this, I monkey patched their Float class in my rails app by adding this to my app, essentially casting it as a BigDecimal instead of a Float:

module PayPal::SDK::Core
  module API
    module DataTypes
      module SimpleTypes
        class Float < ::Float
          def self.new(float)
            # Floats are inccurate. BigDecimal is better.
            # Ruby example: 2.20 - 2.01 = 0.1900000000000004
            # To support currencies with up to 4 subunits, we round(4)
            BigDecimal.new(float.to_f.round(4).to_s)
          end
        end
      end
    end
  end
end

to my config/initializers/paypal.rb. I can't say this is the most elegant solution, but it works. I created an issue on their repo too, and can hopefully hear back soon.

More info on float problems with currency:

Reference 1: https://stackoverflow.com/a/3730040/1109211

Reference 2: https://stackoverflow.com/a/3730249/1109211

Nish
  • 153
  • 2
  • 7
-1

If you are using PHP you can apply this solution. It is working in my case

$amount = 50.4854;
$roundedAmount = number_format(round($amount, 2), 2, '.', '');

Send rounded amount to PayPal, Hope it will work!