MolteNolte
MolteNolte

Reputation: 183

PayPal Api Patch on Itemlist doesn't work

I want to add an item to my transaction.

$json = '
    [
      {
        "name": "Voucher",
        "description":"Voucher",
        "price":"50.00",
        "currency":"EUR",
        "quantity":"1"
      }
    ]';

    $patchAddItem = new \PayPal\Api\Patch();
    $patchAddItem->setOp('add')
        ->setPath('/transactions/0/item_list/items')
        ->setValue(json_decode($json));

$patchReplace = new \PayPal\Api\Patch();
$patchReplace->setOp('replace')
->setPath('/transactions/0/amount')
->setValue(json_decode('{
                "total": "159.00",
                "currency": "EUR",
            }'));

$patchRequest = new \PayPal\Api\PatchRequest();
$patchRequest->setPatches(array($patchAddItem, $patchReplace));

try {
    $this->payment->update($patchRequest, $this->apiContext);
} catch (PayPal\Exception\PayPalConnectionExceptio $ex) {
    echo '<pre>';print_r(json_decode($ex->getData()));exit;
}

But I get following Error

Eception: Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/payments/payment/PAY... in PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalHttpConnection.php on line 154
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Transport/PayPalRestCall.php on line 73: PayPal\Core\PayPalHttpConnection->execute("[{"op":"add","path":"/transactions/0/item_list/ite"... )
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Common/PayPalResourceModel.php on line 102: PayPal\Transport\PayPalRestCall->execute(array[1],"/v1/payments/payment/PAY-1S151200BX2478240LEAG3CI","PATCH","[{"op":"add","path":"/transactions/0/item_list/ite"... ,null)
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Api/Payment.php on line 615: PayPal\Common\PayPalResourceModel::executeCall("/v1/payments/payment/PAY-1S151200BX2478240LEAG3CI","PATCH","[{"op":"add","path":"/transactions/0/item_list/ite"... ,null,object,null)

At this moment I didn't execute the payment object. Do I have to edit the total attribut from amount too? Well, I tried this too, with same issue...

Upvotes: 0

Views: 1122

Answers (1)

favtech
favtech

Reputation: 11

Even if you are sending only one item to PayPal you still have to set them as an item list with setItemList().

That array should be visible if you json_decode in your payment array:

[item_list] => Array
    (
       [items] => Array
           (
               [0] => Array
                   (
                       [name] => Ground Coffee 40 oz
                       [sku] => 123123
                       [price] => 52.80
                       [currency] => USD
                       [quantity] => 1
                   )

           )

I had not run a patch for an item yet. I attempted to send an 'add' similar to your code and tried changing the path to '/transactions/0/item_list/items/1' using the next number in the items array. But could not get an add to work.

The only way I could modify the item_list was to do a complete 'replace' of the item_list, so in a running shopping cart would have to include all the items being purchased, not just the new item.

To do this I prefer to use the functions from the PayPal sdk vs building the json arrays. Their examples of how to create and execute a payment are fairly good and use the SDK functions. http://paypal.github.io/PayPal-PHP-SDK/sample/

However the example on updating a payments builds the json arrays outright.

Below is a testing function to modify the item_list using the Paypay PHP SDK Class Functions. I hard coded the Subtotal and Total to match the values coming form the shopping cart plus the increase from the new item. The item_list is also hard coded using PP's example data. Otherwise item's arrays would be built off of a user's shopping cart items. The type is set to 'replace'.

So, yes. Subtotals and Totals need to be updated to match as well, else the PP call will fail.

function updatePayPalPayment ($type, $createdPayment, $total, $subtotal, $shipping, $currency) {
$subtotal = '54.80';
$total = '71.73';

$details = new Details();
$details->setShipping($shipping)
    ->setSubtotal($subtotal);

$amount = new Amount();
$amount->setCurrency($currency)
    ->setTotal($total)
    ->setDetails($details);

$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
    ->setCurrency('USD')
    ->setQuantity(1)
    ->setSku("123123") // Similar to `item_number` in Classic API
    ->setPrice(52.80);

$item2 = new Item();
$item2->setName('Granola bars')
    ->setCurrency('USD')
    ->setQuantity(1)
    ->setSku("321321") // Similar to `item_number` in Classic API
    ->setPrice(2.0);

$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));


$patchItem = new Patch();
$patchItem->setOp($type)
    ->setPath('/transactions/0/item_list')
    ->setValue($itemList);

$patchAmount = new Patch();
$patchAmount->setOp($type)
    ->setPath('/transactions/0/amount')
    ->setValue($amount);


$patchRequest = new PatchRequest();
$patchRequest->setPatches(array($patchAmount, $patchItem));

$update = $createdPayment->update($patchRequest, getApiContext());

return $update;

}

I also have found it very helpful to set the apiContext for logging to DEBUG and output to a file in development for much better error messages.

'log.LogEnabled' => true,
'log.FileName' => '_PayPal.log',
'log.LogLevel' => 'DEBUG',

Hope that helps.

Upvotes: 1

Related Questions