Forums / Setup & design / SOS: Paypal - checkAmount failed - Solved

SOS: Paypal - checkAmount failed - Solved

Author Message

Mingxing Chen

Tuesday 03 July 2007 12:10:56 am

Hi guys,

Please help me :( I have not found how to solve my problem in this forum.

IThe version is 3.91. When I order something and use paypal to pay for them. Sometimes it failed and got this information:

checkAmount failed: Order amount (21.85) and received amount (21.85) do not match.

*21.85 is the price.

This is the function in <i>/kernel/shop/classes/ezpaymentcallbackchecker.php</i>

    function checkAmount( $amount )
    {
        $orderAmount = $this->order->attribute( 'total_inc_vat' );
        if ( $orderAmount == $amount )
        {
            return true;
        }

        $this->logger->writeTimedString( "Order amount ($orderAmount) and received amount ($amount) do not match.", 'checkAmount failed' );
        return false;
    }

But 21.85==21.85!!!
Yes, the type of $orderAmount is float(double), and $amount is string, this seems not the problem in PHP. Even I changed the datatype of $amount to float, I failed as well.

But when I bought other things with different prices, I successed!
It really confuses me, any one can help me?

Help~~~

Cheers.

Shinetech is the leader in next generation global application outsourcing. Shinetech combines world class technical skills, recognized expertise in advanced development methodologies and industry experience to deliver results for global enterprises. Shinetech utilizes distributed Agile methods for rapid and precise systems development.
------------------------------------------------------------------------------------------
Blog: http://www.mingxing.me
Email: chenmx@shinetechchina.com

Pascal Specht

Tuesday 03 July 2007 11:51:24 pm

Hi Mingxing,

I suppose this is a rounding or type safety problem:
Did you try to check the following:
round both floats to 2 digits precision, like in
$order_amount = round($order_amount,2);
before the comparison (and use === as the operator)
or, after rounding, convert to strings and do a string comparison using the appropriate operator.

Hope this helps,

Pascal

Mingxing Chen

Wednesday 04 July 2007 9:03:58 pm

Hi Pascal,

Thanks for your reply.

Yes, we have found the same problem - comparision of two float(double) numbers.
It's really bad to use '==' to compare them, why eZ Publish makes this simple mistake?!
Or, am I wrong? :(

I used this code to check the Amount(price):

$amount = doubleval($amount);
$orderAmount = doubleval($orderAmount);
if ( abs($orderAmount - $amount )<=1e-6 )
{
    return true;
}

It's not good enough, because there would be inaccuracy.

After reading your message and suggestions from my colleague, I tried this way:

$orderAmount = sprintf("%01.2f", $orderAmount);
if(strcmp($orderAmount, $amount)==0)
{
    return true;
}

What do you think about them? I am looking forward to a better solution from you. ;D

Cheers.

Mingxing

Shinetech is the leader in next generation global application outsourcing. Shinetech combines world class technical skills, recognized expertise in advanced development methodologies and industry experience to deliver results for global enterprises. Shinetech utilizes distributed Agile methods for rapid and precise systems development.
------------------------------------------------------------------------------------------
Blog: http://www.mingxing.me
Email: chenmx@shinetechchina.com

Bruce Morrison

Wednesday 04 July 2007 10:34:38 pm

Hi Mingxing

Firstly I'd report this as a bug @ http://issues.ez.no

The php manual http://au.php.net/float says "never compare floating point numbers for equality"

From my reading it appears your final solution (use of sprintf) is the right way of doing things.

Cheers
Bruce

My Blog: http://www.stuffandcontent.com/
Follow me on twitter: http://twitter.com/brucemorrison
Consolidated eZ Publish Feed : http://friendfeed.com/rooms/ez-publish

Pascal Specht

Wednesday 04 July 2007 11:23:57 pm

Hi Mingxing,

OK, the good news is that you know how to solve your problem... Somehow, I'd like to add, in case this may be useful:

comparing two floats by a threshold via the absolute difference is the correct way to compare floats outside of e-commerce. In CAD/CAM or graphical programs, you should definitively use this so called epsilon compare method, where the correct value of epsilon (1e-6) is a very difficult empirical task, and there's no universal value.

The correct way to do it in e-commerce in my opinion is to first apply a round method of your own (I wouldn't rely on the internal sprintf round, because I don't know how it works). Apply the correct banker's rounding. In most cases, the round function does this correctly for your currency. After that, do a convert to a string, and use a smart and documented way for the separation signs, the presence or not of the currency symbol before or after the amount, the number of digits etc. Only then, application exchange via XML or CURL or whatever can be reliable. Also, my way of proceeding is to apply rounding at the latest moment possible in the computation chain. If you apply several sums and VAT or other taxes, the round operation should happen at the latest moment in the chain, to avoid cumulating rounding errors.

Have a nice day,
Pascal

eZ debug

Timing: Jan 18 2025 04:24:45
Script start
Timing: Jan 18 2025 04:24:45
Module start 'content'
Timing: Jan 18 2025 04:24:46
Module end 'content'
Timing: Jan 18 2025 04:24:46
Script end

Main resources:

Total runtime0.7141 sec
Peak memory usage4,096.0000 KB
Database Queries66

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0061 587.8281180.8281
Module start 'content' 0.00610.7022 768.6563628.4453
Module end 'content' 0.70830.0057 1,397.101650.0703
Script end 0.7140  1,447.1719 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00290.4086140.0002
Check MTime0.00130.1854140.0001
Mysql Total
Database connection0.00080.115010.0008
Mysqli_queries0.647590.6766660.0098
Looping result0.00090.1288640.0000
Template Total0.677294.820.3386
Template load0.00220.308420.0011
Template processing0.674994.518620.3375
Template load and register function0.00010.013510.0001
states
state_id_array0.00240.338110.0024
state_identifier_array0.00120.173120.0006
Override
Cache load0.00200.2736590.0000
Sytem overhead
Fetch class attribute can translate value0.00060.084730.0002
Fetch class attribute name0.00110.157380.0001
XML
Image XML parsing0.00160.230930.0005
class_abstraction
Instantiating content class attribute0.00000.0032100.0000
General
dbfile0.00130.1782300.0000
String conversion0.00000.000730.0000
Note: percentages do not add up to 100% because some accumulators overlap

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1node/view/full.tplfull/forum_topic.tplextension/sevenx/design/simple/override/templates/full/forum_topic.tplEdit templateOverride template
5content/datatype/view/ezimage.tpl<No override>extension/sevenx/design/simple/templates/content/datatype/view/ezimage.tplEdit templateOverride template
5content/datatype/view/ezxmltext.tpl<No override>extension/community_design/design/suncana/templates/content/datatype/view/ezxmltext.tplEdit templateOverride template
14content/datatype/view/ezxmltags/paragraph.tpl<No override>extension/ezwebin/design/ezwebin/templates/content/datatype/view/ezxmltags/paragraph.tplEdit templateOverride template
4content/datatype/view/ezxmltags/literal.tpl<No override>extension/community/design/standard/templates/content/datatype/view/ezxmltags/literal.tplEdit templateOverride template
6content/datatype/view/ezxmltags/line.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/line.tplEdit templateOverride template
1pagelayout.tpl<No override>extension/sevenx/design/simple/templates/pagelayout.tplEdit templateOverride template
 Number of times templates used: 36
 Number of unique templates used: 7

Time used to render debug report: 0.0002 secs