Introduction
I was using Paypal payment on one of my website, and suddenly lot of complaints started coming that their payment is not reflected. The exact error that was coming is:
Access Denied.
You don't have permission to access "/cgi-bin/webscr" on this server.Why Validation
Let me expand the scenario a bit more. When user initiate a payment, I redirect user to the Paypal website. When user do the payment, it calls my website URL with the payment details.
It is a best practice from security perspective to validate this payment from Paypal.
Old Code for Validation in Php
$req = 'cmd=_notify-validate';
if (function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = TRUE;
}
else {
$get_magic_quotes_exists = FALSE;
}
foreach ($postVars as $key => $value) {
if ($get_magic_quotes_exists == TRUE) {
$value = urlencode(stripslashes($value));
}
else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
$url = 'https://www.paypal.com/cgi-bin/webscr';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
if (!($res = curl_exec($ch))) {
//invalid response
curl_close($ch);
return;
}
curl_close($ch);
if (strcmp($res, "VERIFIED") == 0) {
$txn_type = strtoupper($_POST['txn_type']);
switch ($txn_type) {
// A subscriber has signed up for the service.
case 'SUBSCR_SIGNUP':
//handle_call1($res)
break;
case 'SUBSCR_CANCEL': // A subscriber cancelled a subscription.
case 'SUBSCR_MODIFY': // A subscriber profile has been modified.
case 'SUBSCR_FAILED': // A subscriber tried to pay for the service but things didn't work out.
case 'SUBSCR_EOT': // A subscriber has reached the end of the subscription term.
//do nothing
break;
// A subscriber has paid for the service.
case 'SUBSCR_PAYMENT':
case 'WEB_ACCEPT':
//handle_call2($res);
break;
}
}
else {
if (strcmp($res, "INVALID") == 0) {
//Invalid response returned from Paypal
return;
}
}Lets Focus on the main code:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));Working Earlier
This solution worked for years. Suddenly, without any information Paypal did change something at their side. And, it took lot of time for me to figure out. As, it was not expected from Paypal to implement the breaking changes.
And, the error was:
Access Denied.
You don't have permission to access "/cgi-bin/webscr" on this server.The Solution
Paypal started accepting a User-Agent header, with your company name. I think, the company name must have minimum 5 characters.
The code now becomes:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: mycompany'));And, it worked finally. Poor show Paypal. Hope it helps.













