Laravel PayMongo

Amounts & Money

Every amount the package sends or returns is an integer number of centavos, the smallest unit of the peso, exactly as the PayMongo API uses them. 150050 is PHP 1,500.50, and 10000 is PHP 100.00. The package never converts an amount, so a float or a peso value reaches PayMongo exactly as you passed it.

This applies to every amount attribute, checkout line_items[].amount, refunds, captures, plans, and every amount on a data object, such as $payment->amount, $payment->fee, and $payout->netAmount.

Convert pesos to centavos

Store prices as integer centavos, in an unsignedInteger or unsignedBigInteger column, and you never convert. When a price arrives in pesos, multiply by 100 and round before casting:

use Luigel\Paymongo\Facades\Paymongo;

$price = '1500.50'; // pesos, e.g. from a form or a DECIMAL(10, 2) column

$centavos = (int) round((float) $price * 100); // 150050

$intent = Paymongo::paymentIntents()->create([
    'amount' => $centavos,
    'currency' => 'PHP',
    'payment_method_allowed' => ['card'],
]);

$intent->amount;             // 150050: amounts come back in centavos too
$intent->money()?->format(); // "₱1,500.50"

Round before casting to int. Floats cannot hold most decimal fractions exactly, and a cast alone drops the fraction: (int) (19.99 * 100) is 1998, while (int) round(19.99 * 100) is 1999.

PayMongo sets a minimum and maximum amount for each endpoint and payment method, and throws an InvalidRequestException outside them. A payment intent, for example, must be at least 2000 (PHP 20.00). See PayMongo's Payment Intent and Payment Method errors.

Show and add amounts with Money

Luigel\Paymongo\Support\Money is an immutable amount in centavos. Every data object with an amount has a money() method that returns it, or null when the amount is missing (a payout's is its net amount), and you can make your own with Money::ofCentavos():

use Luigel\Paymongo\Support\Money;

$subtotal = Money::ofCentavos(150050);
$shipping = Money::ofCentavos(12000);

$total = $subtotal->add($shipping);

$total->centavos();                   // 162050
$total->toDecimal();                  // "1620.50"
$total->format();                     // "₱1,620.50"
(string) $total;                      // "₱1,620.50"
json_encode(['amount' => $total]);    // {"amount":162050}

$total->subtract($shipping)->equals($subtotal); // true
Method Returns
Money::ofCentavos(int $centavos) A new Money
centavos() The amount in centavos, int
toDecimal() The amount in pesos as an exact string, "1500.50", for a DECIMAL column or an export
format(string $symbol = '₱') A display string, "₱1,500.50". (string) $money gives the same
add(Money $other), subtract(Money $other) A new Money
equals(Money $other) Whether both hold the same amount, bool

Money does its arithmetic on integers and never on floats. It is always pesos: PHP is the only currency PayMongo's APIs accept. It serializes to JSON as its centavos, so a Money in an array or API response comes out as 150050.