Paypal Item prices are correct on localhost, not live/staging server
Closed this issue ยท 9 comments
General information
- SDK/Library version: 1.14.0
- Environment: sandbox
PayPal-Debug-ID
values: 87137f1a3b0- Language, language version, and OS: PHP 7.2 Debian stretch
Issue description
Initial issue was this error on my server:
[13-10-2019 12:00:31] PayPal\Core\PayPalHttpConnection : ERROR: Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/payments/payment. {"name":"VALIDATION_ERROR","details":[{"field":"transactions[0].amount","issue":"Transaction amount details (subtotal, tax, shipping) must add up to specified amount total"},{"field":"transactions[0]","issue":"Item amount must add up to specified amount subtotal (or total if amount details not specified)"}],"message":"Invalid request - see details","information_link":"https://developer.paypal.com/docs/api/payments//#errors","debug_id":"87137f1a3b0"}
While adding the same items to the transaction on localhost it does work. AFter debugging i found out this:
Items localhost:
[2019-10-13 12:11:04] local.INFO: array (
0 =>
PayPal\Api\Item::__set_state(array(
'_propMap' =>
array (
'name' => 'Sandwich',
'currency' => 'EUR',
'quantity' => 3,
'price' => '0.50',<== correct
),
)),
1 =>
PayPal\Api\Item::__set_state(array(
'_propMap' =>
array (
'name' => 'Witte pistolet',
'currency' => 'EUR',
'quantity' => 5,
'price' => '0.40', <== correct
),
)),
2 =>
PayPal\Api\Item::__set_state(array(
'_propMap' =>
array (
'name' => 'Zacht bruin',
'currency' => 'EUR',
'quantity' => 10,
'price' => '0.45',<== correct
),
)),
)
Items on staging server:
[2019-10-13 12:05:02] staging.INFO: array (
0 =>
PayPal\Api\Item::__set_state(array(
'_propMap' =>
array (
'name' => 'Sandwich',
'currency' => 'EUR',
'quantity' => 3,
'price' => '1', <== rounded
),
)),
1 =>
PayPal\Api\Item::__set_state(array(
'_propMap' =>
array (
'name' => 'Zacht bruin',
'currency' => 'EUR',
'quantity' => 10,
'price' => '0' ,<== rounded
),
)),
2 =>
PayPal\Api\Item::__set_state(array(
'_propMap' =>
array (
'name' => 'Witte pistolet',
'currency' => 'EUR',
'quantity' => 5,
'price' => '0', <== rounded
),
)),
)
The code is exactly the same (ofcourse) but on the staging/live server the item prices get rounded?
Items are getting loaded from the session cart which, when debugged, returns:
[2019-10-13 12:05:02] staging.INFO: {"rowId":"1ca30d70ab09187def0f79120f1607ee","id":43,"name":"Sandwich","qty":3,"price":0.5,"options":[],"tax":"0.00","subtotal":"1.50"}
[2019-10-13 12:05:02] staging.INFO: {"rowId":"8c9a90e4053cd74dcb83515e745419ae","id":42,"name":"Zacht bruin","qty":10,"price":0.45,"options":[],"tax":"0.00","subtotal":"4.50"}
[2019-10-13 12:05:02] staging.INFO: {"rowId":"0200fdfc7ee6c5b96ab26c639259d987","id":44,"name":"Witte pistolet","qty":5,"price":0.4,"options":[],"tax":"0.00","subtotal":"2.00"}
Which is exactly the same like on localhost.
What can be the issue here?
Might be related to #1265 - I'm using laravel too
@MichaelBelgium, can you add your code snippet here?
$total = (float)Cart::total(2, '.');
foreach (Cart::content() as $cartProduct)
{
$item = new Item();
$item->setName($cartProduct->name)
->setCurrency('EUR')
->setQuantity($cartProduct->qty)
->setPrice($cartProduct->price);
array_push($items, $item);
Log::info($cartProduct);
}
Log::info($items);
$payer = new Payer();
$payer->setPaymentMethod('paypal');
$item_list = new ItemList();
$item_list->setItems($items);
$details = new Details();
$details
->setSubtotal($subTotal)
->setHandlingFee(Cart::getCost(\Gloudemans\Shoppingcart\Cart::COST_TRANSACTION, 2, '.'));//paypal fee
Log::info('handling fee: ' . Cart::getCost(\Gloudemans\Shoppingcart\Cart::COST_TRANSACTION, 2, '.'));
$amount = new Amount();
$amount->setCurrency('EUR')
->setDetails($details)
->setTotal($total);
Log::info('Total: '.$total);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setInvoiceNumber($hash)
->setItemList($item_list)
->setDescription('Bestelling '.$hash);
$redirect_urls = new RedirectUrls();
$redirect_urls->setReturnUrl(route('paypal.status'))
->setCancelUrl(route('cart.index', ['cancel' => $hash]));
$payment = new Payment();
$payment->setIntent('Sale')
->setPayer($payer)
->setRedirectUrls($redirect_urls)
->setTransactions(array($transaction));
try {
$payment->create($this->paypalApi);
} catch (Exception $ex) {
return redirect()->route('cart.index')->with('error', $ex->getMessage());
}
$redirect_url = $payment->getApprovalLink();
//...
I found the issue. $cartProduct->price
returned "0.5" localhost and on the server "0,5" (with comma). I believe this is the cause then. And i can blame locale settings
@MichaelBelgium ,so the round off issue resolved now in stage?
It's not rounding it (or well partially), it's just the parsing of floats (by the locale) that screws up everything. Like "0,5" gets passed to setPrice
and in the function it set $decimals
to 0 as it can't find a dot. So everything after the comma gets cut, hence why it looks like it rounded off
@MichaelBelgium, I believe you resolved the issue now, aren't you?
I believe so, gotta use everywhere number_format
๐
That sounds cool ๐