Currency Amount Parser
Parses currency strings into integer minor units for safe storage and calculations.
Function signature
ogParseCurrencyAmount(amount, scale = 2)
Categories
- Forms and Validation
Parameters
amountRaw amount such as 12.34, USD 12.34, or -12.34.scaleNumber of decimal places used by the currency.Return value
Short public-safe status message.
- amount_minor
- amount_decimal
- scale
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Parses a currency string into integer minor units without using floating point math.
*
* This is intended for carts, invoices, import tools, and any place where a display
* amount must become a safe database value.
*
* @param string $amount Raw amount such as 12.34, $12.34, or -12.34.
* @param int $scale Number of decimal places used by the currency.
* @return array Parsed amount result with minor units and normalized display value.
*/
function ogParseCurrencyAmount($amount, $scale = 2) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
$amount = trim((string)$amount);
$scale = (int)$scale;
if ($scale < 0) {
$scale = 2;
}
if ($scale > 6) {
$result['message'] = 'Currency scale is too large.';
return $result;
}
if (empty($amount)) {
$result['message'] = 'Missing currency amount.';
return $result;
}
$clean_amount = preg_replace('/[^0-9.\-]/', '', $amount);
if (!preg_match('/^-?[0-9]+(\.[0-9]+)?$/', $clean_amount)) {
$result['message'] = 'Invalid currency amount.';
return $result;
}
$is_negative = false;
if (substr($clean_amount, 0, 1) == '-') {
$is_negative = true;
$clean_amount = substr($clean_amount, 1);
}
$parts = explode('.', $clean_amount, 2);
$whole_part = $parts[0];
$decimal_part = '';
if (!empty($parts[1])) {
$decimal_part = $parts[1];
}
if (strlen($decimal_part) > $scale) {
$result['message'] = 'Currency amount has too many decimal places.';
return $result;
}
$decimal_part = str_pad($decimal_part, $scale, '0');
$multiplier = 1;
$counter = 0;
while ($counter < $scale) {
$multiplier = $multiplier * 10;
$counter++;
}
$minor_units = ((int)$whole_part * $multiplier) + (int)$decimal_part;
if ($is_negative) {
$minor_units = $minor_units * -1;
}
$display = $whole_part;
if ($scale > 0) {
$display .= '.' . $decimal_part;
}
if ($is_negative) {
$display = '-' . $display;
}
$result['success'] = true;
$result['message'] = 'Currency amount parsed.';
$result['data'] = array(
'minor_units' => $minor_units,
'scale' => $scale,
'display' => $display,
'is_negative' => $is_negative
);
return $result;
}