Adventures in PayPal: Missing amount and items


The sample code included here will enable you to make a charge through PayPal for a certain amount but unless you provide a breakdown of the items being purchased then the fee being charged and the items within that charge won't be displayed.
<?php

// http://stackoverflow.com/questions/15729167/paypal-api-with-php-and-curl
// https://github.com/paypal/adaptivepayments-sdk-php/issues/24
// https://github.com/paypal/rest-api-curlsamples/blob/master/execute_all_calls.php

// http://stackoverflow.com/questions/15885742/pay-with-paypal-through-paypal-rest-api-does-not-show-up-payment-description-on
// Full payment capabilities
// https://developer.paypal.com/docs/integration/direct/explore-payment-capabilities/
$host = 'https://api.sandbox.paypal.com';
$clientId = 'Replace with your clientId';
$secret = 'Replace with your secret';
$token = '';

function get_access_token($url, $postdata) {
 global $clientId, $clientSecret;
 $curl = curl_init($url); 
 curl_setopt($curl, CURLOPT_POST, true); 
 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
 curl_setopt($curl, CURLOPT_USERPWD, $clientId . ":" . $clientSecret);
// curl_setopt($ch, CURLOPT_SSLVERSION, 1);
// curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
 curl_setopt($curl, CURLOPT_HEADER, false); 
 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
 curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata); 
 // curl_setopt($curl, CURLOPT_VERBOSE, TRUE);
 $response = curl_exec( $curl );
 if (empty($response)) {
     // some kind of an error happened
     die(curl_error($curl));
     curl_close($curl); // close cURL handler
 } else {
     $info = curl_getinfo($curl);
  echo "Time took: " . $info['total_time']*1000 . "ms\n";
     curl_close($curl); // close cURL handler
  if($info['http_code'] != 200 && $info['http_code'] != 201 ) {
   echo "Received error: " . $info['http_code']. "\n";
   echo "Raw response:".$response."\n";
   die();
     }
 }
 // Convert the result from JSON format to a PHP array 
 $jsonResponse = json_decode( $response );
 return $jsonResponse->access_token;
}


function make_post_call($url, $postdata) {
 global $token;
 $curl = curl_init($url); 
 curl_setopt($curl, CURLOPT_POST, true);
 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
 curl_setopt($curl, CURLOPT_HEADER, false);
 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($curl, CURLOPT_HTTPHEADER, array(
    'Authorization: Bearer '.$token,
    'Accept: application/json',
    'Content-Type: application/json'
    ));
 
 curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata); 
 #curl_setopt($curl, CURLOPT_VERBOSE, TRUE);
 $response = curl_exec( $curl );
 if (empty($response)) {
     // some kind of an error happened
     die(curl_error($curl));
     curl_close($curl); // close cURL handler
 } else {
     $info = curl_getinfo($curl);
  echo "Time took: " . $info['total_time']*1000 . "ms\n";
     curl_close($curl); // close cURL handler
  if($info['http_code'] != 200 && $info['http_code'] != 201 ) {
   echo "Received error: " . $info['http_code']. "\n";
   echo "Raw response:".$response."\n";
   die();
     }
 }

 // Convert the result from JSON format to a PHP array 
 $jsonResponse = json_decode($response, TRUE);
 return $jsonResponse;
}

echo "\n";
echo "###########################################\n";
echo "Obtaining OAuth2 Access Token.... \n";
$url = $host.'/v1/oauth2/token'; 
$postArgs = 'grant_type=client_credentials';
$token = get_access_token($url,$postArgs);
echo "Got OAuth Token: ".$token;
echo "\n \n";
echo "###########################################\n";
echo "Initiating a Payment with PayPal Account... \n";
$url = $host.'/v1/payments/payment';
$payment = array(
                'intent' => 'sale',
                'payer' => array(
                        'payment_method' => 'paypal'
  ),
                'transactions' => array (array(
                                'amount' => array(
                                        'total' => '7.47',
                                        'currency' => 'USD'
                                        ),
                                'description' => 'payment using a PayPal account',                                              
                                'item_list' => array(
                                'items' => array(
                                array(
                                'quantity' => '1',
                                'name' => 'Book',
                                'price' => '7.47',
                                'sku' => 'ISBN96821394391231',
                                'currency' => 'USD',
                                'tax' => '0'
                                                        )),
                                ))),
  'redirect_urls' => array (
   'return_url' => 'http://www.example.com/paypal/return.php',
   'cancel_url' => 'http://www.example.com/paypal/cancel.php'
  )
                );
$json = json_encode($payment);
$json_resp = make_post_call($url, $json);
foreach ($json_resp['links'] as $link) {
 if($link['rel'] == 'execute'){
  $payment_execute_url = $link['href'];
  $payment_execute_method = $link['method'];
 } else  if($link['rel'] == 'approval_url'){
   $payment_approval_url = $link['href'];
   $payment_approval_method = $link['method'];
  }
}
echo "Payment Created successfully: " . $json_resp['id'] ." with state '". $json_resp['state']."'\n\n";
echo "Please goto <a href='".$payment_approval_url."'>link</a> in your browser and approve the payment with a PayPal Account.\n";
?>
important here is the 'item_list' and the way it is nested. See StackOverflow and PayPal's extended payment capabilities for further details.

As with the previous post an access token is obtained and that token is now used as a way to make a PayPal payment. All the standalone Credit Card processes have been stripped from PayPal's sample code along with the execution code, which is something that needs to be placed within the page that is located at your return_url.

To make this work you need to place your own values within the $clientId and $secret variables as well replace the generic return_url and cancel_url within the $payment variable.


Comments