Sample PHP code for Paypal RefundTransaction using Paypal NVP API

Depending on different conditions, sometimes we might need to refund the amount paid by users. We can refund the user by directly logging into the Paypal or use their API so, that everything can be handle from our own site with just one click. On this post, we will learn, how we can use Paypal NVP(Name Value Pair) API to refund users.

Paypal consists of RefundTransaction Method for these purposes. RefundTransaction API operation can be used to issue a full or partial refund for any transaction within a default period of 60 days from when the payment is received. Below, we use CURL to request the Paypal API, but you can use fsock as well.

Before, diving into the code, lets grab necessary API credentials from Paypal, which is required to authenticate the call to Paypal API’s. Below are the steps you need to follow to get your API credentials:

  • Login to your Paypal Business Account
  • Navigate to “My Selling Tools” under Profile menu. Refer to screenshot below:my-selling-tools-paypal
  • Under Selling online category, locate “API access” and click on “Update” button showing next to it. Refer to screenshot below:paypal-api-access
  • You will be presented with the Paypal API access page, click on Request API signature under Option 2
  • On Request API Credentials page, select Request API access and click Agree and Submit as shown in screenshot below.
  • Once submit, you will be taken to the page with your api credentials, as shown in screenshot below:paypal-api-credentials

API Username, API Password and Signature is what required for requesting Paypal API. Once you get these details, you can use the following code to refund the transaction.

Sample code in PHP to refund transaction using Paypal API NVP

 * Send HTTP POST Request
 * @param     string     The API method name
 * @param     string     The POST Message fields in &name=value pair format
 * @return     array     Parsed HTTP Response body
function PPHttpPost($methodName_, $nvpStr_, $env) {

 // Set up your API credentials, PayPal end point, and API version.
 $API_UserName = urlencode('Your API username');
 $API_Password = urlencode('Your API password');
 $API_Signature = urlencode('Your API signature');
 if("sandbox" === $env)
 	$API_Endpoint = "https://api-3t.$";
 	$API_Endpoint = "";
 $version = urlencode('119');

 // Set the curl parameters.
 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
 curl_setopt($ch, CURLOPT_VERBOSE, 1);

 // Turn off the server and peer verification (TrustManager Concept).

 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_POST, 1);

 // Set the API operation, version, and API signature in the request.
 $nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";

 // Set the request as a POST FIELD for curl.
 curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);

 // Get response from the server.
 $httpResponse = curl_exec($ch);

 if(!$httpResponse) {
 	exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');

 // Extract the response details.
 $httpResponseAr = explode("&", $httpResponse);

 $httpParsedResponseAr = array();
 foreach ($httpResponseAr as $i => $value) {
	 $tmpAr = explode("=", $value);
	 if(sizeof($tmpAr) > 1) {
	 	$httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];

 if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
 	exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");

 return $httpParsedResponseAr;

// Set request-specific fields.
$transactionID = urlencode('example_transaction_id');
$refundType = urlencode('Full');  // or 'Partial'
$amount;                          // required if Partial.
$memo;                            // required if Partial.
$currencyID = urlencode('USD');   // or other currency ('GBP', 'EUR', 'JPY', 'CAD', 'AUD')

// Add request-specific fields to the request string.
$nvpStr = "&TRANSACTIONID=$transactionID&REFUNDTYPE=$refundType&CURRENCYCODE=$currencyID";

if(isset($memo)) {
	$nvpStr .= "&NOTE=$memo";

if(strcasecmp($refundType, 'Partial') == 0) {
	if(!isset($amount)) {
		exit('Partial Refund Amount is not specified.');
	} else {
		$nvpStr = $nvpStr."&AMT=$amount";
	if(!isset($memo)) {
		exit('Partial Refund Memo is not specified.');

// Execute the API operation; see the PPHttpPost function above.

$env = 'sandbox';
$httpParsedResponseAr = PPHttpPost('RefundTransaction', $nvpStr);

if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {
	exit('Refund Completed Successfully: '.print_r($httpParsedResponseAr, true));
} else  {
	exit('RefundTransaction failed: ' . print_r($httpParsedResponseAr, true));

Paypal PDT (Sample code for validating transaction when auto return from Paypal)

This post is continue of my previous post:
» Auto Return users from Paypal on successful payment and introduction to PDT

In previous post, we have successfully completed setting up the Paypal Auto Return and Payment Data Transfer (PDT) features on Paypal. In this post, we will be adding up transaction validation code to our return url so that, we can finally give access to the users into our members area.

Below I am listing the whole process being followed from when the user clicks buy now button to when they are given access to members area.

  • First of all, user clicks on the buy now button and is taken to the paypal for payment. Paypal displays the lists of available methods of payment so that user can pay for the item they want to purchase.
  • After successful payment, user is redirected to the return URL setup in Paypal, with certain parameters appended to the URL. If you haven’t setup/enable the Paypal Auto Return and Payment Data Transfer option in your Paypal Business Account, then click here to read my previous post on Auto Return users from Paypal on successful payment and introduction to PDT
  • Return URL is where we have the transaction validation code. As paypal redirects the user with certain parameters, as tx=, amount, quantity, etc. our script, would validate these locally and then send a request to Paypal for confirmation. While requesting paypal, we will need PDT Identity Token from paypal to verify which I am going to explain in more details below.
  • As the request is send to Paypal, Paypal verifies the request and responds back with the complete transaction details. Transaction details consists of each and every attributes which we need to validate again with our script to avoid fraudulent transactions.
  • Once validation succeeds, we can show user with success message, create member and redirect them to members area, or anything the payment was made for.

Paypal PDT Identity Token

Paypal PDT Token is an access token that uniquely identifies your account. Like any other access token, this is required to request Paypal for any transaction details within your account, and to prevent any non authenticated users from requesting the details.

If you have gone through my previous post, you might have already known how this token is generated. On Website Payment Preferences page, after you enable Auto Return and Payment Data Transfer and click save, you will be redirected to My Profile page with a message as on screenshot below:

which displays the PDT Identity token. You can access this token anytime from your PDT section on Website Payment Preference page.

Below, is the sample code in PHP for validating transaction using this PDT identity token:

Sample code in PHP for Paypal PDT Transaction Validation

Once payment is successful, user is redirected to Return URL with certain parameters appended to the URL with transaction id. Grab this transaction id from URL and validate transaction by communicating with Paypal and execute script to process order.

// defining some constants
define("USE_SANDBOX", 1);
define("PDT_TOKEN", "your PDT Identity Token");
define("VERIFY_EMAIL", 'Your email for Business Paypal');
define("VERIFY_CURRENCY", 'Currency to be verified');
define("VERIFY_AMOUNT", 'Amount to be verified');

function alreadyExist($txid){
	// check if this transaction id has already been processed	

function processOrder(){
	// process the Order
	// create member or get users access to item what they had paid for	
if(isset($_GET['tx']) &amp;&amp; ($_GET['tx'])!=null &amp;&amp; ($_GET['tx'])!= "") {
	$txn_id = $GET['tx'];
	$request = 'cmd=_notify-synch';
	$auth_token = PDT_TOKEN;
	$request .= "&amp;tx=$txn_id&amp;at=$auth_token";
	// post back to PayPal system to validate
	$header .= "POST /cgi-bin/webscr HTTP/1.1\r\n";
	$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
	$header .= "Host:\r\n";
	$header .= "Content-Length: " . strlen($request) . "\r\n";
	$header .= "Connection: close\r\n\r\n";
	if(USE_SANDBOX == true)
		$fp = fsockopen ('ssl://', 443, $errno, $errstr, 30); 
		$fp = fsockopen ('ssl://', 443, $errno, $errstr, 30);
	if (isset($fp) &amp;&amp; $fp) {
		fputs ($fp, $header . $req);
		// read the body data
		$res = '';
		$headerdone = false;
		while (!feof($fp)) {
			$line = fgets ($fp, 1024);
			if (strcmp($line, "\r\n") == 0) {
				// read the header
				$headerdone = true;
			else if ($headerdone) {
				// header has been read. now read the contents
				$res .= $line;
		// parse the data
		$lines = explode("\n", $res);
		$response = array();
		if (strcmp ($lines[1], "SUCCESS") == 0) {
			for ($i=1; $i&lt;count($lines);$i++){
				list($key,$val) = explode("=", $lines[$i]);
				$response[urldecode($key)] = urldecode($val);
			$itemName = $response["item_name"];
			$amount = $response["payment_gross"];
			$email = $response["receiver_email"];
			$userEmailPaypalId = $response["payer_email"];
			$paymentStatus = $response["payment_status"];
			$TxId = $response["txn_id"];
			$currency = $response["mc_currency"];
			// check the payment_status is Completed, receiver email is your paypal account, currency and amount are correct
			if($paymentStatus=="Completed" &amp;&amp; $email == VERIFY_EMAIL &amp;&amp; $currency == VERIFY_CURRENCY &amp;&amp; $amount == VERIFY_AMOUNT) {
				// check that txn_id has not been previously processed			
					// process the order
	fclose ($fp);
} else {
    // Display appropriate error message

Auto Return users from Paypal on successful payment and introduction to PDT

On my recent project, I was suppose to give my users access to the members area as soon as they complete the payment. I was using Paypal as the mode of the payment as this is the most widely used and is available for most of the countries.

By default, user is presented with the buy now button, which takes them to paypal for the payment and on successful payment, users are presented with options as shown in image below, where users need to click on the link to get back to our webpage.

My requirement was different, I was suppose to get buyers back to my website after they complete the payment process automatically and validate transaction to create a member and log in successfully, displaying them their dashboard page with thank you message and a summary of their payment. Paypal provides us with the Auto Return and Payment Data Transfer(PDT) features for this purpose. Below, I have listed out the steps to enable the Paypal auto return and PDT:

  • Login to your Paypal Business Account.
  • Navigate to “My Selling Tools” under Profile menu. Refer to screenshot below:
  • Under Selling online category, locate “Website preferences” and click on “Update” button showing next to it. Refer to screenshot below:
  • You will be presented with the Website preferences page with Auto Return, Return URL, PDT and other options as below:
  • Select “on” for the Auto Return and Payment Data Transfer radio button. For Return URL, you need to mention the link to your webpage, where you wish to redirect your buyers or where the whole processing after the payment takes place. Refer to 3 red boxes above in the screenshot.
  • Scroll to the bottom of the page and click on the Save button to Save the settings. Once saved you will be presented with the Identity token at the bottom of “Payment Data Transfer” section. You will need this token to access and call Paypal servers to validate transactions.

These steps, ensures that you successfully completed setting up Paypal Auto Return and Payment Data Transfer feature on Paypal Business Account. Next step is to add the transaction validation code to the Return URL we just saved. I will cover this up on my next article, explaining details on setting up Paypal PDT with sample code.