Magento – REST API PayPal does not call setExpressCheckout method

magento-2.0magento2paypal-expresspaypal-standardrest

When making orders through REST API and selecting payment method paypal_express there is issue with invalid token.

1) Create guest cart through REST API:

Send POST request to http://example.com/index.php/rest/V1/guest-carts

2) Add some product to cart:

Send POST request to 
http://example.com/index.php/rest/V1/guest-carts/GUEST_CART_ID/items with data:
{
      "cartItem": {
        "quote_id": "GUEST_CART_ID",
        "sku": "PRODUCT_SKU",
        "qty": 1
      }
}

3) Set shipping information:

Send POST request to
http://example.com/index.php/rest/V1/guest-carts/GUEST_CART_ID/shipping-information with data:
{
    "addressInformation": {
            "shipping_address": {
                "firstname": "FirstName",
                "lastname": "LastName",
                "street": [
                    "My Address"
                ],
                "city": "MyCity",
                "telephone": "+99312xxxxxxx",
                "country_id": "TM"
            },
            "shipping_method_code": "freeshipping",
            "shipping_carrier_code": "freeshipping"
        }
}

4) Make payment:

Send POST request to http://example.com/index.php/rest/V1/guest-carts/GUEST_CART_ID/payment-information with data:
{
    "email": "myemail@example.com",
    "paymentMethod": {
        "method": "paypal_express"
    },
    "billingAddress": {
        "firstname": "BillingFirstName",
        "lastname": "BillingLastName",
        "street": [
            "Billing Address"
        ],
        "city": "Billing City",
        "country_id": "TM",
        "telephone": "+99365xxxxxx"
    }
}

Expected result

setExpressCheckout method must be called first. This is log when PayPal payment made through web site:

'url' => 'https://api-3t.paypal.com/nvp',
  'SetExpressCheckout' =>
  array (
    'PAYMENTACTION' => 'Sale',
    'AMT' => '10',
    'CURRENCYCODE' => 'USD',
    'RETURNURL' => 'http://example.com/paypal/express/return/',
    'CANCELURL' => 'http://example.com/paypal/express/cancel/',
    'INVNUM' => '2000000057',
    'SOLUTIONTYPE' => 'Sole',
    'GIROPAYCANCELURL' => 'http://example.com/paypal/express/cancel/',
    'GIROPAYSUCCESSURL' => 'http://example.com/checkout/onepage/success/',
    ...
    ...
    ...
    'ADDROVERRIDE' => 1,
    'METHOD' => 'SetExpressCheckout',
    'VERSION' => '72.0',
    'USER' => '****',
    'PWD' => '****',
    'SIGNATURE' => '****',
    'BUTTONSOURCE' => 'Magento_Cart_Community',
  ),
  'response' =>
  array (
    'TOKEN' => 'EC-XXXXXXXXXXX',
    'TIMESTAMP' => '2016-07-24T21:09:52Z',
    'CORRELATIONID' => 'xxxxxxxxxxxxxx',
    'ACK' => 'Success',
    'VERSION' => '72.0',
    'BUILD' => '23642192',
  ),
) {"is_exception":false} []

Actual result

Instead I receive this error in response to request in 4th step:

PayPal gateway has rejected request. Invalid token (#10410: Invalid token)

And in log file this:

main.DEBUG: array (
  'url' => 'https://api-3t.paypal.com/nvp',
  'DoExpressCheckoutPayment' =>
  array (
    'TOKEN' => NULL,
    'PAYERID' => NULL,
    'PAYMENTACTION' => 'Sale',
    'AMT' => '10',
    'CURRENCYCODE' => 'USD',
    'BUTTONSOURCE' => 'Magento_Cart_Community',
    'NOTIFYURL' => 'http://example.com/paypal/ipn/',
    'RETURNFMFDETAILS' => 1,
    'SHIPPINGAMT' => '0.00',
    'ITEMAMT' => '0.10',
    ...
    ...
    ...
    'SHIPTONAME' => 'Mynam',
    'ADDROVERRIDE' => 1,
    'METHOD' => 'DoExpressCheckoutPayment',
    'VERSION' => '72.0',
    'USER' => '****',
    'PWD' => '****',
    'SIGNATURE' => '****',
  ),
  'response' =>
  array (
    'TIMESTAMP' => '2016-07-24T21:59:26Z',
    'CORRELATIONID' => 'xxxxxxxxxxxxxxxx',
    'ACK' => 'Failure',
    'VERSION' => '72.0',
    'BUILD' => '23642192',
    'L_ERRORCODE0' => '10410',
    'L_SHORTMESSAGE0' => 'Invalid token',
    'L_LONGMESSAGE0' => 'Invalid token.',
    'L_SEVERITYCODE0' => 'Error',
  ),
) {"is_exception":false} []

Note:
I think the problem is with directly calling DoExpressCheckoutPayment instead of SetExpressCheckout.

Best Answer

We also had the same issue when we tried the below payload it worked

Endpoint: http://localhost:8888/Magento/index.php/rest/V1/carts/mine/payment-information

{ "paymentMethod": { "method": "paypal_express", "additional_data": { "paypal_express_checkout_token" : "EC-xxxxxxxxxxxx", "paypal_express_checkout_redirect_required" : false, "paypal_express_checkout_payer_id" : "XXXXXXXXXX" } } }

In order to get the payment token we used the paypal set express checkout api directly

Here is more details

https://developer.paypal.com/docs/classic/express-checkout/ht_ec-singleItemPayment-curl-etc/?mark=Do%20Express%20Checkout%20Call#

When the customer approves the payment we will get the payer id in the returned url.

Hope this helps!