Skip to content

Commit 27929bc

Browse files
committed
Merge branch 'pr/70'
# Conflicts: # tests/Omnipay/Common/Message/AbstractRequestTest.php
2 parents b980a16 + 6aee5a1 commit 27929bc

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/Omnipay/Common/Message/AbstractRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ public function getAmount()
335335
}
336336

337337
// Check for rounding that may occur if too many significant decimal digits are supplied.
338-
$decimal_count = strlen(substr(strrchr((string)$amount, '.'), 1));
338+
$decimal_count = strlen(substr(strrchr(sprintf('%.8g', $amount), '.'), 1));
339339
if ($decimal_count > $this->getCurrencyDecimalPlaces()) {
340340
throw new InvalidRequestException('Amount precision is too high for currency.');
341341
}

tests/Omnipay/Common/Message/AbstractRequestTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,41 @@ public function testAmountZeroNotAllowed()
124124
$this->changeProtectedProperty('zeroAmountAllowed', false);
125125
$this->request->setAmount('0.00');
126126
$this->request->getAmount();
127+
}
128+
129+
// See https://github.com/thephpleague/omnipay-common/issues/69
130+
public function testAmountPrecision()
131+
{
132+
// The default precision for PHP is 6 decimal places.
133+
ini_set('precision', 6);
134+
$this->assertSame($this->request, $this->request->setAmount('67.10'));
135+
$this->assertSame('67.10', $this->request->getAmount());
136+
137+
// At 17 decimal places, 67.10 will echo as 67.09999...
138+
// This is *why* PHP sets the default precision at 6.
139+
ini_set('precision', 17);
140+
$this->assertSame('67.10', $this->request->getAmount());
141+
142+
$this->assertSame($this->request, $this->request->setAmount('67.01'));
143+
$this->assertSame('67.01', $this->request->getAmount());
144+
145+
$this->assertSame($this->request, $this->request->setAmount('0.10'));
146+
$this->assertSame('0.10', $this->request->getAmount());
147+
148+
$this->assertSame($this->request, $this->request->setAmount('0.01'));
149+
$this->assertSame('0.01', $this->request->getAmount());
150+
}
151+
152+
/**
153+
* @expectedException Omnipay\Common\Exception\InvalidRequestException
154+
*
155+
* We still want to catch obvious fractions of the minor units that are
156+
* not precision errors at a much lower level.
157+
*/
158+
public function testAmountPrecisionTooHigh()
159+
{
160+
$this->assertSame($this->request, $this->request->setAmount('123.005'));
161+
$this->assertSame('123.005', $this->request->getAmount());
127162
}
128163

129164
public function testGetAmountNoDecimals()

0 commit comments

Comments
 (0)