paypal / PayPal-PHP-SDK

PHP SDK for PayPal RESTful APIs
https://developer.paypal.com/docs/api/
Other
27 stars 99 forks source link

the response tells me that I miss total amount #188

Closed anouarabdsslm closed 9 years ago

anouarabdsslm commented 9 years ago

Hi , I'm working onn laravel package , but when I process my payment . I get this response issue

my code as bellow

    // ### Address
    // Base Address object used as shipping or billing
    // address in a payment. [Optional]
    $addr= Paypalpayment::address();
    $addr->setLine1("3909 Witmer Road");
    $addr->setLine2("Niagara Falls");
    $addr->setCity("Niagara Falls");
    $addr->setState("NY");
    $addr->setPostal_code("14305");
    $addr->setCountry_code("US");
    $addr->setPhone("716-298-1822");

    // ### CreditCard
    $card = Paypalpayment::creditCard();
    $card->setType("visa")
        ->setNumber("4758411877817150")
        ->setExpireMonth("05")
        ->setExpireYear("2019")
        ->setCvv2("456")
        ->setFirstName("Joe")
        ->setLastName("Shopper");

    // ### FundingInstrument
    // A resource representing a Payer's funding instrument.
    // Use a Payer ID (A unique identifier of the payer generated
    // and provided by the facilitator. This is required when
    // creating or using a tokenized funding instrument)
    // and the `CreditCardDetails`
    $fi = Paypalpayment::fundingInstrument();
    $fi->setCredit_card($card);

    // ### Payer
    // A resource representing a Payer that funds a payment
    // Use the List of `FundingInstrument` and the Payment Method
    // as 'credit_card'
    $payer = Paypalpayment::payer();
    $payer->setPaymentMethod("credit_card")
        ->setFundingInstruments(array($fi));

    $item1 = Paypalpayment::item();
    $item1->setName('Ground Coffee 40 oz')
        ->setDescription('Ground Coffee 40 oz')
        ->setCurrency('USD')
        ->setQuantity(1)
        ->setTax("0.3")
        ->setPrice("7.50");

    $item2 = Paypalpayment::item();
    $item2->setName('Granola bars')
        ->setDescription('Granola Bars with Peanuts')
        ->setCurrency('USD')
        ->setQuantity(5)
        ->setTax("0.2")
        ->setPrice("2");

    $itemList = Paypalpayment::itemList();
    $itemList->setItems(array($item1, $item2));

    $details = Paypalpayment::details();
    $details->setShipping("1.2")
        ->setTax("1.3")
        ->setSubtotal("17.5");

    //Payment Amount
    $amount = Paypalpayment::amount();
    $amount->setCurrency("USD")
        ->setTotal("20")
        ->setDetails($details);

    // ### Transaction
    // A transaction defines the contract of a
    // payment - what is the payment for and who
    // is fulfilling it. Transaction is created with
    // a `Payee` and `Amount` types

    $transaction = Paypalpayment::transaction();
    $transaction->setAmount($amount)
        ->setItemList($itemList)
        ->setDescription("Payment description")
        ->setInvoiceNumber(uniqid());

    // ### Payment
    // A Payment Resource; create one using
    // the above types and intent as 'sale'

    $payment = Paypalpayment::payment();

    $payment->setIntent("sale")
        ->setPayer($payer)
        ->setTransactions(array($transaction));

    try {
        // ### Create Payment
        // Create a payment by posting to the APIService
        // using a valid ApiContext
        // The return object contains the status;
        $payment->create($this->_apiContext);
    } catch (\PPConnectionException $ex) {
        return  "Exception: " . $ex->getMessage() . PHP_EOL;
        exit(1);
    }
    dd($payment);

Response issue [11-12-2014 05:49:11] PayPal\Core\PPHttpConnection: FINE: Response : {"name":"VALIDATION_ERROR","details":[{"field":"transactions","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/webapps/developer/docs/api/#VALIDATION_ERROR","debug_id":"d993059e951ad"}

jaypatel512 commented 9 years ago

I am not sure why you are receiving this error. When I tried to reproduce the code in one of the samples, it worked. Can you please make sure you are using the latest version of SDK ?

I just downloaded the 0.15.1 version of SDK release, and tested your code, and I got the following result. I will also provide the code that I replaced in samples/payment/CreatePayment.php to reproduce your code: screen shot 2014-12-11 at 12 28 57 pm

Here is the code:

<?php

// # CreatePaymentSample
//
// This sample code demonstrate how you can process
// a direct credit card payment. Please note that direct 
// credit card payment and related features using the 
// REST API is restricted in some countries.
// API used: /v1/payments/payment

require __DIR__ . '/../bootstrap.php';
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\CreditCard;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\FundingInstrument;
use PayPal\Api\Transaction;

// ### Address
// Base Address object used as shipping or billing
// address in a payment. [Optional]
$addr= new \PayPal\Api\Address();
$addr->setLine1("3909 Witmer Road");
$addr->setLine2("Niagara Falls");
$addr->setCity("Niagara Falls");
$addr->setState("NY");
$addr->setPostal_code("14305");
$addr->setCountry_code("US");
$addr->setPhone("716-298-1822");

// ### CreditCard
$card = new CreditCard();
$card->setType("visa")
    ->setNumber("4758411877817150")
    ->setExpireMonth("05")
    ->setExpireYear("2019")
    ->setCvv2("456")
    ->setFirstName("Joe")
    ->setLastName("Shopper");

// ### FundingInstrument
// A resource representing a Payer's funding instrument.
// Use a Payer ID (A unique identifier of the payer generated
// and provided by the facilitator. This is required when
// creating or using a tokenized funding instrument)
// and the `CreditCardDetails`
$fi = new FundingInstrument();
$fi->setCreditCard($card);

// ### Payer
// A resource representing a Payer that funds a payment
// Use the List of `FundingInstrument` and the Payment Method
// as 'credit_card'
$payer = new Payer();
$payer->setPaymentMethod("credit_card")
    ->setFundingInstruments(array($fi));

$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
    ->setDescription('Ground Coffee 40 oz')
    ->setCurrency('USD')
    ->setQuantity(1)
    ->setTax("0.3")
    ->setPrice("7.50");

$item2 = new Item();
$item2->setName('Granola bars')
    ->setDescription('Granola Bars with Peanuts')
    ->setCurrency('USD')
    ->setQuantity(5)
    ->setTax("0.2")
    ->setPrice("2");

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

$details = new Details();
$details->setShipping("1.2")
    ->setTax("1.3")
    ->setSubtotal("17.5");

//Payment Amount
$amount = new Amount();
$amount->setCurrency("USD")
    ->setTotal("20")
    ->setDetails($details);

// ### Transaction
// A transaction defines the contract of a
// payment - what is the payment for and who
// is fulfilling it. Transaction is created with
// a `Payee` and `Amount` types

$transaction = new Transaction();
$transaction->setAmount($amount)
    ->setItemList($itemList)
    ->setDescription("Payment description")
    ->setInvoiceNumber(uniqid());

// ### Payment
// A Payment Resource; create one using
// the above types and intent as 'sale'

$payment = new Payment();

$payment->setIntent("sale")
    ->setPayer($payer)
    ->setTransactions(array($transaction));

// For Sample Purposes Only.
$request = clone $payment;

try {
    // ### Create Payment
    // Create a payment by posting to the APIService
    // using a valid ApiContext
    // The return object contains the status;
    $payment->create($apiContext);
} catch (Exception $ex) {
    ResultPrinter::printError('Create Payment Using Credit Card', 'Payment', null, $request, $ex);
    exit(1);
}

ResultPrinter::printResult('Create Payment Using Credit Card', 'Payment', $payment->getId(), $request, $payment);

return $payment;

I Just made the changes to how you were creating new instances, and $this->_apiContext, to $apiContext. Everything else, is pretty much the same. I have not changed your pricing/data at all.

anouarabdsslm commented 9 years ago

I'm using the latest version 0.15.1 ,I think the issue is related to the details . when I process payment without specifying the details it's work . here the function where I create new instance of details . could you take look: https://github.com/xroot/laravel-paypalpayment/blob/master/src/Anouar/Paypalpayment/PaypalPayment.php#L210

jaypatel512 commented 9 years ago

Could you please check the paypal logs, and see if the shipping and subtotals, are shown as something like this: 1.20, 1.30 and 17.50 by any chance. The SDK automatically formats the data with 2 decimals.

[11-12-2014 07:38:34] PayPal\Core\PPHttpConnection: INFO: POST https://api.sandbox.paypal.com/v1/payments/payment
[11-12-2014 07:38:34] PayPal\Core\PPHttpConnection: FINE: Content-Type: application/json
[11-12-2014 07:38:34] PayPal\Core\PPHttpConnection: FINE: User-Agent: PayPalSDK/PayPal-PHP-SDK 0.15.1 (lang=PHP;v=5.5.14;bit=64;os=Darwin_14.0.0;machine=x86_64;openssl=0.9.8r;curl=7.28.1)
[11-12-2014 07:38:34] PayPal\Core\PPHttpConnection: FINE: Authorization: Bearer A015.GBl7FeLIi5A9d2XB9wNn1ptsm2fFBWMm43FyHCpp38
[11-12-2014 07:38:34] PayPal\Core\PPHttpConnection: FINE: PayPal-Request-Id: LM-AUN-0087640373620141832311325017
[11-12-2014 07:38:34] PayPal\Core\PPHttpConnection: FINE: Payload : {"intent":"sale","payer":{"payment_method":"credit_card","funding_instruments":[{"credit_card":{"type":"visa","number":"4758411877817150","expire_month":"05","expire_year":"2019","cvv2":"456","first_name":"Joe","last_name":"Shopper"}}]},"transactions":[{"amount":{"currency":"USD","total":"20.00","details":{"shipping":"1.20","tax":"1.30","subtotal":"17.50"}},"item_list":{"items":[{"name":"Ground Coffee 40 oz","description":"Ground Coffee 40 oz","currency":"USD","quantity":1,"tax":"0.30","price":"7.50"},{"name":"Granola bars","description":"Granola Bars with Peanuts","currency":"USD","quantity":5,"tax":"0.20","price":"2.00"}]},"description":"Payment description","invoice_number":"5489e4a9b8523"}]}

[11-12-2014 07:38:38] PayPal\Core\PPHttpConnection: FINE: Response : {"id":"PAY-35557280T4857844UKSE6JKI","create_time":"2014-12-11T18:38:33Z","update_time":"2014-12-11T18:38:34Z","state":"approved","intent":"sale","payer":{"payment_method":"credit_card","funding_instruments":[{"credit_card":{"type":"visa","number":"xxxxxxxxxxxx7150","expire_month":"5","expire_year":"2019","first_name":"Joe","last_name":"Shopper"}}]},"transactions":[{"amount":{"total":"20.00","currency":"USD","details":{"subtotal":"17.50","tax":"1.30","shipping":"1.20"}},"description":"Payment description","invoice_number":"5489e4a9b8523","item_list":{"items":[{"name":"Ground Coffee 40 oz","price":"7.50","currency":"USD","quantity":"1","description":"Ground Coffee 40 oz","tax":"0.30"},{"name":"Granola bars","price":"2.00","currency":"USD","quantity":"5","description":"Granola Bars with Peanuts","tax":"0.20"}]},"related_resources":[{"sale":{"id":"5A060870U4106590S","create_time":"2014-12-11T18:38:33Z","update_time":"2014-12-11T18:38:34Z","amount":{"total":"20.00","currency":"USD"},"state":"completed","parent_payment":"PAY-35557280T4857844UKSE6JKI","links":[{"href":"https://api.sandbox.paypal.com/v1/payments/sale/5A060870U4106590S","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/payments/sale/5A060870U4106590S/refund","rel":"refund","method":"POST"},{"href":"https://api.sandbox.paypal.com/v1/payments/payment/PAY-35557280T4857844UKSE6JKI","rel":"parent_payment","method":"GET"}]}}]}],"links":[{"href":"https://api.sandbox.paypal.com/v1/payments/payment/PAY-35557280T4857844UKSE6JKI","rel":"self","method":"GET"}]}

Can you please confirm this with your logs. This could give us a good idea why this error is showing up. My apologies you are seeing this issue.

anouarabdsslm commented 9 years ago

this is my log: [11-12-2014 06:43:06] PayPal\Core\PPHttpConnection: INFO: POST https://api.sandbox.paypal.com/v1/oauth2/token [11-12-2014 06:43:06] PayPal\Core\PPHttpConnection: FINE: User-Agent: PayPalSDK/PayPal-PHP-SDK 0.15.1 (lang=PHP;v=5.5.9-1ubuntu4.2;bit=32;os=Linux3.13.0-24-generic;machine=i686;openssl=1.0.1f;curl=7.35.0) [11-12-2014 06:43:06] PayPal\Core\PPHttpConnection: FINE: Authorization: Basic QVZKeDBSQXJRemtDQ3NXQzBldlppMVNzb080Z3hqRGtrVUxRQmRtUE5CWlQ0ZmMxNEFST1VxLWV0TUVZOkVINUYwQkF4cW9uVm5QOE00YTBjNmV6VUhxLVVULUNXZkdjaVBOUU9kVWxUcFdQa055dVM2ZUROLXRwQQ== [11-12-2014 06:43:06] PayPal\Core\PPHttpConnection: FINE: Accept: /_ [11-12-2014 06:43:06] PayPal\Core\PPHttpConnection: FINE: Payload : grant_type=client_credentials

[11-12-2014 06:43:11] PayPal\Core\PPHttpConnection: FINE: Response : {"scope":"https://api.paypal.com/v1/developer/. https://api.paypal.com/v1/payments/. https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/vault/credit-card/.*","access_token":"A015BDPkBISlkd1rpzeJjjr5NG04DO2QB8eAEHcZmpM2H5I","token_type":"Bearer","app_id":"APP-80W284485P519543T","expires_in":28800}

[11-12-2014 06:43:11] PayPal\Core\PPHttpConnection: INFO: POST https://api.sandbox.paypal.com/v1/payments/payment [11-12-2014 06:43:11] PayPal\Core\PPHttpConnection: FINE: Content-Type: application/json [11-12-2014 06:43:11] PayPal\Core\PPHttpConnection: FINE: User-Agent: PayPalSDK/PayPal-PHP-SDK 0.15.1 (lang=PHP;v=5.5.9-1ubuntu4.2;bit=32;os=Linux_3.13.0-24-generic;machine=i686;openssl=1.0.1f;curl=7.35.0) [11-12-2014 06:43:11] PayPal\Core\PPHttpConnection: FINE: Authorization: Bearer A015BDPkBISlkd1rpzeJjjr5NG04DO2QB8eAEHcZmpM2H5I [11-12-2014 06:43:11] PayPal\Core\PPHttpConnection: FINE: PayPal-Request-Id: -10627292061198141832337861009 [11-12-2014 06:43:11] PayPal\Core\PPHttpConnection: FINE: Payload : {"intent":"sale","payer":{"payment_method":"credit_card","funding_instruments":[{"credit_card":{"type":"visa","number":"4758411877817150","expire_month":"05","expire_year":"2019","cvv2":"456","first_name":"Joe","last_name":"Shopper"}}]},"transactions":[{"amount":{"currency":"USD","total":"20.00","details":{"shipping":"1.20","tax":"1.30","subtotal":"17.50"}},"item_list":{"items":[{"name":"Granola bars","description":"Granola Bars with Peanuts","currency":"USD","quantity":5,"tax":"0.20","price":"2.00"},{"name":"Granola bars","description":"Granola Bars with Peanuts","currency":"USD","quantity":5,"tax":"0.20","price":"2.00"}]},"description":"Payment description","invoice_number":"5489e5ba1d1bd"}]}

[11-12-2014 06:43:12] PayPal\Core\PPHttpConnection: FINE: Response : {"name":"VALIDATION_ERROR","details":[{"field":"transactions","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/webapps/developer/docs/api/#VALIDATION_ERROR","debug_id":"559eb776cbf5d"}

jaypatel512 commented 9 years ago

Found the issue:

The issue is, you are adding two items in the itemList, However, your PayPalPayments::item() returns the same instance of item both time, and you are adding it twice. Check your body here:

"item_list": {
                "items": [
                    {
                        "name": "Granola bars",
                        "description": "Granola Bars with Peanuts",
                        "currency": "USD",
                        "quantity": 5,
                        "tax": "0.20",
                        "price": "2.00"
                    },
                    {
                        "name": "Granola bars",
                        "description": "Granola Bars with Peanuts",
                        "currency": "USD",
                        "quantity": 5,
                        "tax": "0.20",
                        "price": "2.00"
                    }
                ]
            },
anouarabdsslm commented 9 years ago

I have removed the second item2 and still get the same issue . here is the log [11-12-2014 06:49:41] PayPal\Core\PPHttpConnection: INFO: POST https://api.sandbox.paypal.com/v1/payments/payment [11-12-2014 06:49:41] PayPal\Core\PPHttpConnection: FINE: Content-Type: application/json [11-12-2014 06:49:41] PayPal\Core\PPHttpConnection: FINE: User-Agent: PayPalSDK/PayPal-PHP-SDK 0.15.1 (lang=PHP;v=5.5.9-1ubuntu4.2;bit=32;os=Linux_3.13.0-24-generic;machine=i686;openssl=1.0.1f;curl=7.35.0) [11-12-2014 06:49:41] PayPal\Core\PPHttpConnection: FINE: Authorization: Bearer A015nwqDeRCB.a1IO5cYtOZEuhieyEQA1j9eBcsN8zI-e5k [11-12-2014 06:49:41] PayPal\Core\PPHttpConnection: FINE: PayPal-Request-Id: -10627292061197141832377735071 [11-12-2014 06:49:41] PayPal\Core\PPHttpConnection: FINE: Payload : {"intent":"sale","payer":{"payment_method":"credit_card","funding_instruments":[{"credit_card":{"type":"visa","number":"4758411877817150","expire_month":"05","expire_year":"2019","cvv2":"456","first_name":"Joe","last_name":"Shopper"}}]},"transactions":[{"amount":{"currency":"USD","total":"19.00","details":{"shipping":"1.20","tax":"0.30","subtotal":"17.50"}},"item_list":{"items":[{"name":"Ground Coffee 40 oz","description":"Ground Coffee 40 oz","currency":"USD","quantity":1,"tax":"0.30","price":"7.50"}]},"description":"Payment description","invoice_number":"5489e74432f8c"}]}

[11-12-2014 06:49:43] PayPal\Core\PPHttpConnection: FINE: Response : {"name":"VALIDATION_ERROR","details":[{"field":"transactions","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/webapps/developer/docs/api/#VALIDATION_ERROR","debug_id":"a196d3546b7ce"}

jaypatel512 commented 9 years ago

It makes sense. As you can see, now you are only specifying one time, which is of 1 quantity of 7.50 price, with 0.30 tax. this will total up to 7.50 + 0.30 subtotal. So, this is how it would look then:

$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
    ->setDescription('Ground Coffee 40 oz')
    ->setCurrency('USD')
    ->setQuantity(1)
    ->setTax("0.3")
    ->setPrice("7.50");

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

$details = new Details();
$details->setShipping("1.2")
    ->setTax("0.3")
    ->setSubtotal("7.5");

//Payment Amount
$amount = new Amount();
$amount->setCurrency("USD")
    ->setTotal("9")
    ->setDetails($details);

As you can notice now, the total is $9 = (7.5 + 0.3) * 1 ( of quantity) + 1.2 ( of Shipping).

anouarabdsslm commented 9 years ago

yes that true , seems I have missed the calculation . thanks for help

jaypatel512 commented 9 years ago

No worries. Let me know if you need any additional information !

jaypatel512 commented 9 years ago

Btw, just as a suggestion, we have added an ability to pass in json string, or array into the constructor that would automatically, fill in the data into the model.

You can find more information here : https://github.com/paypal/PayPal-PHP-SDK#api-model-constructor