@@ -37,6 +37,16 @@ abstract class AbstractRequest implements RequestInterface
37
37
*/
38
38
protected $ response ;
39
39
40
+ /**
41
+ * @var bool
42
+ */
43
+ protected $ zeroAmountAllowed = true ;
44
+
45
+ /**
46
+ * @var bool
47
+ */
48
+ protected $ negativeAmountAllowed = false ;
49
+
40
50
/**
41
51
* Create a new Request
42
52
*
@@ -158,6 +168,30 @@ public function setCardReference($value)
158
168
return $ this ->setParameter ('cardReference ' , $ value );
159
169
}
160
170
171
+ /**
172
+ * Convert an amount into a float.
173
+ *
174
+ * @var string|int|float $value The value to convert.
175
+ * @throws InvalidRequestException on any validation failure.
176
+ * @return float The amount converted to a float.
177
+ */
178
+
179
+ public function toFloat ($ value )
180
+ {
181
+ if ( ! is_string ($ value ) && ! is_int ($ value ) && ! is_float ($ value )) {
182
+ throw new InvalidRequestException ('Data type is not a valid decimal number. ' );
183
+ }
184
+
185
+ if (is_string ($ value )) {
186
+ // Validate generic number, with optional sign and decimals.
187
+ if ( ! preg_match ('/^[-]?[0-9]+(\.[0-9]*)?$/ ' , $ value )) {
188
+ throw new InvalidRequestException ('String is not a valid decimal number. ' );
189
+ }
190
+ }
191
+
192
+ return (float )$ value ;
193
+ }
194
+
161
195
/**
162
196
* Validates and returns the formated amount.
163
197
*
@@ -168,41 +202,31 @@ public function setCardReference($value)
168
202
public function getAmount ()
169
203
{
170
204
$ amount = $ this ->getParameter ('amount ' );
171
- $ message = 'Please specify amount as a string or float, '
172
- . 'with decimal places (e.g. \'10.00 \' to represent $10.00). ' ;
173
205
174
206
if ($ amount !== null ) {
175
207
// Don't allow integers for currencies that support decimals.
176
208
// This is for legacy reasons - upgrades from v0.9
177
- if (is_int ($ amount ) && $ this ->getCurrencyDecimalPlaces () > 0 ) {
178
- throw new InvalidRequestException ($ message );
179
- }
180
-
181
- if (is_string ($ amount )) {
182
- // Negative amounts are valid numbers at this stage.
183
- if (preg_match ('/[^0-9\.-]/ ' , $ amount )) {
184
- throw new InvalidRequestException ('Invalid character in amount. ' );
185
- }
186
-
187
- // Generic number, with optional sign and decimals.
188
- if (!preg_match ('/^[-]?[0-9]+(\.[0-9]*)?$/ ' , $ amount )) {
189
- throw new InvalidRequestException ('Amount string is not a valid decimal number. ' );
190
- }
191
-
192
- // Don't allow integers for currencies that support decimals (legacy v0.9).
193
- if ($ this ->getCurrencyDecimalPlaces () > 0 && false === strpos ((string ) $ amount , '. ' )) {
194
- throw new InvalidRequestException ($ message );
195
- }
209
+ if ($ this ->getCurrencyDecimalPlaces () > 0 ) {
210
+ if (is_int ($ amount ) || (is_string ($ amount ) && false === strpos ((string ) $ amount , '. ' ))) {
211
+ throw new InvalidRequestException (
212
+ 'Please specify amount as a string or float, '
213
+ . 'with decimal places (e.g. \'10.00 \' to represent $10.00). '
214
+ );
215
+ };
196
216
}
197
217
198
- // The number_format() used later requires a float.
199
- $ amount = (float )$ amount ;
218
+ $ amount = $ this ->toFloat ($ amount );
200
219
201
220
// Check for a negative amount.
202
- if ($ amount < 0 ) {
221
+ if ( ! $ this -> negativeAmountAllowed && $ amount < 0 ) {
203
222
throw new InvalidRequestException ('A negative amount is not allowed. ' );
204
223
}
205
224
225
+ // Check for a zero amount.
226
+ if ( ! $ this ->zeroAmountAllowed && $ amount === 0.0 ) {
227
+ throw new InvalidRequestException ('A zero amount is not allowed. ' );
228
+ }
229
+
206
230
// Check for rounding that may occur if too many significant decimal digits are supplied.
207
231
$ decimal_count = strlen (substr (strrchr ((string )$ amount , '. ' ), 1 ));
208
232
if ($ decimal_count > $ this ->getCurrencyDecimalPlaces ()) {
0 commit comments