I ran into this same problem a month ago and after reading the docs, there's currently no way to accomplish this with the REST API. If there is a way, it's not documented.
The only way I found to do this is with the NVP API and possibly the SOAP API. The NVP API will give you back most of the fields that you want but if you've stored custom fields for a transaction, it will only give you 3 of the custom fields but not all of them (weird).
I haven't tried the NVP method GetExpressCheckoutDetails but I have used the GetTransactionDetails method. It will give you back the transaction details. It returns a text block that you must parse. Each field is URL encoded and separated by an ampersand. Here's an example in PHP:
<?php
// Get cURL resource
$ch = curl_init();
// Set url
curl_setopt($ch, CURLOPT_URL, 'https://api-3t.paypal.com/nvp/');
// Set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
// Set options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Set headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/x-www-form-urlencoded; charset=utf-8",
]
);
// Create body
$body = [
"VERSION" => "204.0",
"METHOD" => "GetTransactionDetails",
"USER" => "nvp_api_username_here",
"PWD" => "nvp_api_password_here",
"SIGNATURE" => "nvp_api_signature_here",
"TRANSACTIONID" => "some_paypal_transaction_id_here",
];
$body = http_build_query($body);
// Set body
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
// Send the request and save response to $resp
$resp = curl_exec($ch);
if(!$resp) {
die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
} else {
parse_str($resp, $formated_response);
print_r($formated_response);
}
// Close request to clear up some resources
curl_close($ch);
Here's the formatted return body:
Array
(
[RECEIVERBUSINESS] => [email protected]
[RECEIVEREMAIL] => [email protected]
[RECEIVERID] => 1111111111111
[EMAIL] => [email protected]
[PAYERID] => 55551
[PAYERSTATUS] => verified
[COUNTRYCODE] => US
[BUSINESS] => buyers_business_name_here
[ADDRESSOWNER] => PayPal
[ADDRESSSTATUS] => None
[SALESTAX] => 0.00
[SHIPAMOUNT] => 0.00
[SHIPHANDLEAMOUNT] => 0.00
[SHIPDISCOUNT] => 0.00
[INSURANCEAMOUNT] => 0.00
[GIFTRECEIPT] => 0
[TIMESTAMP] => 2016-08-02T17:04:58Z
[CORRELATIONID] => 55552
[ACK] => Success
[VERSION] => 204.0
[BUILD] => 22386173
[FIRSTNAME] => Foo
[LASTNAME] => Bar
[TRANSACTIONID] => 55553
[TRANSACTIONTYPE] => webaccept
[PAYMENTTYPE] => instant
[ORDERTIME] => 2016-08-01T20:49:28Z
[AMT] => 1.00
[TAXAMT] => 0.00
[CURRENCYCODE] => USD
[PAYMENTSTATUS] => Completed
[PENDINGREASON] => None
[REASONCODE] => None
[SHIPPINGMETHOD] => Default
[PROTECTIONELIGIBILITY] => Ineligible
[PROTECTIONELIGIBILITYTYPE] => None
[L_QTY0] => 0
[L_TAXAMT0] => 0.00
[L_SHIPPINGAMT0] => 0.00
[L_HANDLINGAMT0] => 0.00
[L_CURRENCYCODE0] => USD
[L_OPTIONSNAME0] => first_custom_field_label_here
[L_OPTIONSVALUE0] => first_custom_field_value_here
[L_OPTIONSNAME1] => second_custom_field_label_here
[L_OPTIONSVALUE1] => second_custom_field_value_here
[L_OPTIONS1NAME0] => second_custom_field_label_here_duplicate
[L_OPTIONS1VALUE0] => second_custom_field_value_here_duplicate
[L_TAXABLE0] => false
[L_TAXRATE0] => 0.0
[L_AMT0] => 1.00
[INSURANCEOPTIONSELECTED] => 0
[SHIPPINGOPTIONISDEFAULT] => 0
)
Warning:
This only applies if you're storing custom fields in a PayPal transaction.
PayPal's NVP API only returns up to 3 custom fields for a transaction, even though you can store up to 7 custom fields in a transaction. Even crazier, one of the custom fields it returns is a duplicate of the second custom field. At least that's the case when I try to retrieve a custom fields from a transaction.