In order to execute the sale you'll have a return page setup where PayPal redirects to after the customer has paid. Since the user is going away from the page and returning to either the same one or a new one you need to find a way of storing the access token so that you can use this again for execution.
While it's true that you can simply create a new access token, and this will be equally valid for performing the execution, what you are meant to do is to use access tokens until their expiry (which occurs 8–9 hours after their creation). So in all likelihood the access token will be active when the user returns from PayPal.
To address this it is possible to store the token as a cookie or in session storage. Session storage keeps the data on the server and cookies save to the user's machine. So session storage seems like the obvious choice.
To perform this we need to add a two lines of code to the original call to retrieve the PayPal access token. First we need to start a session, which can be done at the head of the page:
session_start();and second a line needs to be added to the token creation code
$_SESSION["paypal_access_token"] = $token;so that it looks like this
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; $_SESSION["paypal_access_token"] = $token; echo "\n \n";For safety, we also need to retrieve the expiry time of the token. To do this we can place a line of code inside the get_access_token: method:
$_SESSION["paypal_expires"] = time() + $jsonResponse->expires_in;immediately before its return statement.
Executing the sale
Now everything will be prepared for the execution of the sale and our code looks like this:<?php session_start(); // 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 = "your client id goes here"; $secret = "your secret goes here"; // check expiry and if expired request new token $_SESSION["paypal_expiry"] $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; } // check if token has expired, create new one if it has if (isset($_SESSION["expiry_time"]) && $_SESSION["expiry_time"] > time()) { $url = $host.'/v1/oauth2/token'; $postArgs = 'grant_type=client_credentials'; $token = get_access_token($url,$postArgs); } else if (isset($_SESSION["paypal_access_token"])) { $token = $_SESSION["paypal_access_token"]; } $payment_execute_url = $host."/v1/payments/payment/".$_GET["paymentId"]."/execute/"; $payerId = $_GET["PayerID"]; // payerId not being received. echo "\n \n"; echo $token; echo "###########################################\n"; echo "Executing the PayPal Payment for PayerId (".$_GET["PayerID"].")... \n".$payment_execute_url; $payment_execute = array( "payer_id" => $_GET["PayerID"] ); $json = json_encode($payment_execute); echo $json; $json_resp = make_post_call($payment_execute_url, $json); echo "Payment Execute processed " . $json_resp['id'] ." with state '". $json_resp['state']."'"; echo "\n \n"; ?>In real use you probably don't want to go repeating your storing your secret and id across multiple files, it's just done here for convenience in order to show a self-contained return file but in real-world use we can be smarter in our code arrangement. Not only this but of course functions themselves have been repeated across the transaction and execution files, which again doesn't actually need to be happening. The point is, however, that within two fairly simple files we're able to send a request for payment and receive back the information necessary to execute that payment and to then execute.
Comments
Post a Comment