I have been pulling my hair out trying to get this to work for over a week. I have even purchased an SSL cert for the domain.
I keep getting the error:
[2016-03-14 18:07 Europe/London] Can not connect to PayPal to validate IPN message: SSL connect error
Heres my code.
<?php
// CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory.
// Especially useful if you encounter network errors or other intermittent problems with IPN (validation).
// Set this to 0 once you go live or don't require logging.
define("DEBUG", 1);
// Set to 0 once you're ready to go live
define("USE_SANDBOX", 1);
define("LOG_FILE", "ipn.log");
error_log(date('[Y-m-d H:i e] '). "Test message: " . PHP_EOL, 3, LOG_FILE);
// Read POST data
// reading posted data directly from $_POST causes serialization
// issues with array data in POST. Reading raw POST data from input stream instead.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// Post IPN data back to PayPal to validate the IPN data is genuine
// Without this step anyone can fake IPN data
if(USE_SANDBOX == true) {
$paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
} else {
$paypal_url = "https://www.paypal.com/cgi-bin/webscr";
}
//$userAgent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2';
$ch = curl_init($paypal_url);
if ($ch == FALSE) {
return FALSE;
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent );
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);
if(DEBUG == true) {
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
}
// CONFIG: Optional proxy configuration
//curl_setopt($ch, CURLOPT_PROXY, $proxy);
//curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// CONFIG: Please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below. Ensure the file is readable by the webserver.
// This is mandatory for some environments.
$res = curl_exec($ch);
if (curl_errno($ch) != 0) // cURL error
{
if(DEBUG == true) {
error_log(date('[Y-m-d H:i e] '). "Can not connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, LOG_FILE);
}
curl_close($ch);
exit;
} else {
// Log the entire HTTP response if debug is switched on.
if(DEBUG == true) {
error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $req" . PHP_EOL, 3, LOG_FILE);
error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $res" . PHP_EOL, 3, LOG_FILE);
}
curl_close($ch);
}
// Inspect IPN validation result and act accordingly
// Split response headers and payload, a better way for strcmp
$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));
if (strcmp ($res, "VERIFIED") == 0) {
// check whether the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your PayPal email
// check that payment_amount/payment_currency are correct
// process payment and mark item as paid.
// assign posted variables to local variables
//$item_name = $_POST['item_name'];
//$item_number = $_POST['item_number'];
//$payment_status = $_POST['payment_status'];
//$payment_amount = $_POST['mc_gross'];
//$payment_currency = $_POST['mc_currency'];
//$txn_id = $_POST['txn_id'];
//$receiver_email = $_POST['receiver_email'];
//$payer_email = $_POST['payer_email'];
if(DEBUG == true) {
error_log(date('[Y-m-d H:i e] '). "Verified IPN: $req ". PHP_EOL, 3, LOG_FILE);
}
} else if (strcmp ($res, "INVALID") == 0) {
// log for manual investigation
// Add business logic here which deals with invalid IPN messages
if(DEBUG == true) {
error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE);
}
}
?>
I'm not sure why you bought an SSL certificate to fix connecting to PayPal.
Try changing
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
to
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
My bet is the SSL handshake is failing to the server. Disabling the checks should help clear it up.
Related
On my PayPal autoReturn page with a known-to-work PHP script to accommodate Payment Data Transfer, no matter what I do I keep getting this error message: "Warning: fgets(): SSL: Connection reset by peer...*(on the line where this is: '$line = fgets($fp, 1024);'* "
Before I ask my question, let me just say that I've tried everything suggested here and in any other forum or article that I've been advised to read, e.g. changing HTTP 1.0 to HTTP 1.1, using $res=stream_get_contents($fp, 1024) instead of the while loop with $line = fgets($fp, 1024), etc., etc. My problem persists.
Here's what I think might be the problem (and I'm hoping someone can tell me if I'm on the right track): My auto return page for PDT is on an add-on site and I'm thinking that PayPal hangs up when the shared SSL (for my primary domain on a shared server) isn't recognized. So I've asked my web host for SSL to be installed specifically for my add-on domain.
Could the add-on domain SSL thing be the reason for my warning message? Again, that message is: "Warning: fgets(): SSL: Connection reset by peer...*(on the line where this is: '$line = fgets($fp, 1024);'* "
Here's my code:
//look if the parameter 'tx' is set in the GET request and that it does not have a null or empty value
if(isset($_GET['tx']) && ($_GET['tx'])!=null && ($_GET['tx'])!= "") {
$tx = $_GET['tx'];
verifyWithPayPal($tx);
}
else {
exitCode();
}
function verifyWithPayPal($tx) {
$req = 'cmd=_notify-synch';
$tx_token = $tx;
$auth_token = "MY SANDBOX AUTH_TOKEN HERE";
$req .= "&tx=$tx_token&at=$auth_token";
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
// url for paypal sandbox
//$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// url for payal
// $fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);
// If possible, securely post back to paypal using HTTPS
// Your PHP server will need to be SSL enabled.
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
exitCode();
} else {
fputs($fp, $header . $req);
// read the body data
$res = '';
$headerdone = false;
while (!feof($fp)) {
$line = fgets($fp, 1024);
// $res=stream_get_contents($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[0], "SUCCESS") == 0) {
for ($i=1; $i<count($lines);$i++){
list($key,$val) = explode("=", $lines[$i]);
$response[urldecode($key)] = urldecode($val);
}
$itemName = $response["item_name"];
$amount = $response["payment_gross"];
$myEmail = $response["receiver_email"];
$userEmailPaypalId = $response["payer_email"];
$paymentStatus = $response["payment_status"];
$paypalTxId = $response["txn_id"];
$currency = $response["mc_currency"];
// check the payment_status is Completed
if($paymentStatus!="Completed") {
payment_complete();
emailer($userEmailPayPalID);
} else {
payment_incomplete($paymentStatus);
}
/*
// check that txn_id has not been previously processed
checkIfTransactionHasAlreadyBeenProcessed($paypalTxId);
// check that receiver_email is your Primary PayPal email
checkThatPaymentIsReceivedAtYourEmailAddress($myEmail);
// check that payment_amount/payment_currency are correct
checkPaymentAmountAndCurrency($amount, $currency);
// process the order
processOrder();
} else {
exitCode();
*/
}
}
fclose ($fp);
}
I notice you're connecting to www.sandbox.paypal.com. I believe you want to connect to api.sandbox.paypal.com.
I have just authored a WHMCS addon module that works great on my server; however, others that have tried to use it are not having success. There are 2 issues...
1) I use the WHMCS License Addon; however, it does not appear that their remote machines are making a successful connection to my machine to validate the license. I use the WHMCS supplied code to handle the connection and validation. No idea on what else to check... Any ideas?
2) I have a database that my script checks to see if the user has the most current version of the script. Access to the database works great from my local machine and RemoteSQL is enabled with a % wildcard so anyone should be able to connect but yet the remote machines do not seem to be able to connect. Here is my info...
$link = mysql_connect('gjinternetsolutions.com', 'gj_Guest', 'Password1');
mysql_select_db("gj_Software", $link);
$query = "SELECT * FROM `VersionCheck` where `Software`='RedemptionFee'";
... additional code to display the results
Is anyone able to successfully make a remote connection to the above database?
=========== UPDATE ===========
The second issue above has been resolved. We are still having an issue with the licensing code.... Here is what we have....
# Values obtained from our database...
$localkey=$row['LocalKey'];
$licensekey=$vars['License'];
$results = RedemptionFee_check_gj_license($licensekey,$localkey);
function RedemptionFee_check_gj_license($licensekey,$localkey="")
{
$whmcsurl = "http://gjinternetsolutions.com/home/";
$licensing_secret_key = "####-VALUE REMOVED FOR THIS POST-####"; # Unique value, should match what is set in the product configuration for MD5 Hash Verification
$check_token = time().md5(mt_rand(1000000000,9999999999).$licensekey);
$checkdate = date("Ymd"); # Current date
$usersip = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : $_SERVER['LOCAL_ADDR'];
$localkeydays = 1; # How long the local key is valid for in between remote checks
$allowcheckfaildays = 5; # How many days to allow after local key expiry before blocking access if connection cannot be made
$localkeyvalid = false;
if ($localkey) {
$localkey = str_replace("\n",'',$localkey); # Remove the line breaks
$localdata = substr($localkey,0,strlen($localkey)-32); # Extract License Data
$md5hash = substr($localkey,strlen($localkey)-32); # Extract MD5 Hash
if ($md5hash==md5($localdata.$licensing_secret_key)) {
$localdata = strrev($localdata); # Reverse the string
$md5hash = substr($localdata,0,32); # Extract MD5 Hash
$localdata = substr($localdata,32); # Extract License Data
$localdata = base64_decode($localdata);
$localkeyresults = unserialize($localdata);
$originalcheckdate = $localkeyresults["checkdate"];
if ($md5hash==md5($originalcheckdate.$licensing_secret_key)) {
$localexpiry = date("Ymd",mktime(0,0,0,date("m"),date("d")-$localkeydays,date("Y")));
if ($originalcheckdate>$localexpiry) {
$localkeyvalid = true;
$results = $localkeyresults;
$validdomains = explode(",",$results["validdomain"]);
if (!in_array($_SERVER['SERVER_NAME'], $validdomains)) {
$localkeyvalid = false;
$localkeyresults["status"] = "Invalid";
$results = array();
}
$validips = explode(",",$results["validip"]);
if (!in_array($usersip, $validips)) {
$localkeyvalid = false;
$localkeyresults["status"] = "Invalid";
$results = array();
}
if ($results["validdirectory"]!=dirname(__FILE__)) {
$localkeyvalid = false;
$localkeyresults["status"] = "Invalid";
$results = array();
}
}
}
}
}
if (!$localkeyvalid) {
$postfields["licensekey"] = $licensekey;
$postfields["domain"] = $_SERVER['SERVER_NAME'];
$postfields["ip"] = $usersip;
$postfields["dir"] = dirname(__FILE__);
if ($check_token) $postfields["check_token"] = $check_token;
if (function_exists("curl_exec")) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $whmcsurl."modules/servers/licensing/verify.php");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close($ch);
} else {
$fp = fsockopen($whmcsurl, 80, $errno, $errstr, 5);
if ($fp) {
$querystring = "";
foreach ($postfields AS $k=>$v) {
$querystring .= "$k=".urlencode($v)."&";
}
$header="POST ".$whmcsurl."modules/servers/licensing/verify.php HTTP/1.0\r\n";
$header.="Host: ".$whmcsurl."\r\n";
$header.="Content-type: application/x-www-form-urlencoded\r\n";
$header.="Content-length: ".#strlen($querystring)."\r\n";
$header.="Connection: close\r\n\r\n";
$header.=$querystring;
$data="";
#stream_set_timeout($fp, 20);
#fputs($fp, $header);
$status = #socket_get_status($fp);
while (!#feof($fp)&&$status) {
$data .= #fgets($fp, 1024);
$status = #socket_get_status($fp);
}
#fclose ($fp);
}
}
if (!$data) {
$localexpiry = date("Ymd",mktime(0,0,0,date("m"),date("d")-($localkeydays+$allowcheckfaildays),date("Y")));
if ($originalcheckdate>$localexpiry) {
$results = $localkeyresults;
} else {
$results["status"] = "Invalid";
$results["description"] = "Remote Check Failed";
return $results;
}
} else {
preg_match_all('/<(.*?)>([^<]+)<\/\\1>/i', $data, $matches);
$results = array();
foreach ($matches[1] AS $k=>$v) {
$results[$v] = $matches[2][$k];
}
}
if ($results["md5hash"]) {
if ($results["md5hash"]!=md5($licensing_secret_key.$check_token)) {
$results["status"] = "Invalid";
$results["description"] = "MD5 Checksum Verification Failed";
return $results;
}
}
if ($results["status"]=="Active") {
$results["checkdate"] = $checkdate;
$data_encoded = serialize($results);
$data_encoded = base64_encode($data_encoded);
$data_encoded = md5($checkdate.$licensing_secret_key).$data_encoded;
$data_encoded = strrev($data_encoded);
$data_encoded = $data_encoded.md5($data_encoded.$licensing_secret_key);
$data_encoded = wordwrap($data_encoded,80,"\n",true);
$results["localkey"] = $data_encoded;
}
$results["remotecheck"] = true;
}
unset($postfields,$data,$matches,$whmcsurl,$licensing_secret_key,$checkdate,$usersip,$localkeydays,$allowcheckfaildays,$md5hash);
return $results;
}
Yes, I can connect using the details above.
Query run:
SELECT * FROM `gj_Software`.`VersionCheck` where `Software`='RedemptionFee'
Result:
# Software, Version, URL
'RedemptionFee', '1.0', 'http://GJinternetSolutions.com/home/upgrade.php?type=package&id=660'
Hope this helps.
Ash
I am using the Twitter API to create a web application. However, I would like to be able to get a list of users that a specific user is following. I have looked at the documentation and I have not been able to find how to do this.
For example, I might be trying to get the users that baconman is following. How can I do this using the Twitter API?
<?php
$screen_name = 'baconman';
$url = 'https://api.twitter.com/1/followers/ids.json?cursor=-1&screen_name='.$screen_name;
$list = curl($url,'GET');
$followers_ids = json_decode($list);
$user_detail = 'https://api.twitter.com/1/users/lookup.json?user_id='.implode(',',$followers_ids->ids).'&include_entities=true';
$details = curl($user_detail,'GET');
function curl($url, $method = 'get', $header = null, $postdata = null, $includeheader=FALSE, $timeout = 60)
{
$s = curl_init();
curl_setopt($s,CURLOPT_URL, $url);
if ($header)
curl_setopt($s,CURLOPT_HTTPHEADER, $header);
/*if ($this->debug)*/
curl_setopt($s,CURLOPT_VERBOSE, FALSE);
curl_setopt($s,CURLOPT_TIMEOUT, $timeout);
curl_setopt($s,CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($s,CURLOPT_MAXREDIRS, 3);
curl_setopt($s,CURLOPT_RETURNTRANSFER, true);
curl_setopt($s,CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($s,CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($s,CURLOPT_COOKIEFILE, 'cookie.txt');
if(strtolower($method) == 'post')
{
curl_setopt($s,CURLOPT_POST, true);
curl_setopt($s,CURLOPT_POSTFIELDS, $postdata);
}
else if(strtolower($method) == 'delete')
{
curl_setopt($s,CURLOPT_CUSTOMREQUEST, 'DELETE');
}
else if(strtolower($method) == 'put')
{
curl_setopt($s,CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($s,CURLOPT_POSTFIELDS, $postdata);
}
curl_setopt($s,CURLOPT_HEADER, $includeheader);
//curl_setopt($s,CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1');
curl_setopt($s, CURLOPT_SSL_VERIFYPEER, false);
$html = curl_exec($s);
$status = curl_getinfo($s, CURLINFO_HTTP_CODE);
curl_close($s);
return $html;
}
So I have 100 different things going wrong in a piece of code. I recently switched from Apache and PHP to Node.js. I have a particular piece of code that merely duplicates a request that it receives. Basically, my web app posts a JSON request to my server (PHP or Node.js), then the server sends the exact same request to my Apache Camel configuration. In PHP, this worked perfectly. When switching to Node.js, I'm getting errors from Apache Camel.
Specifically, I have a piece of code that sends the exact same request twice almost instantaneously (I know how to fix it, just bear with me). In PHP, this code would work fine. In Node.js, the first request works fine, but the second one fails. Apache Camel receives a request with an empty body the second time. And to be honest, I'm 100% clueless.
What exactly could be going wrong here? Logic tells me that if it worked with PHP but not Node (same Camel code) that it has to be an issue with Node.js. But I had to mention Camel just in case, because Camel does a few weird things with requests sometimes.
I'm going to post my code below and maybe you can see an issue. I've been working on this for 3 days (on and off) and haven't found a problem yet. Also, bear in mind that I just started using node a few days ago.
PHP
<?php
require_once("globals.php");
//There's nested JSON here so I could include the destination address
$request = file_get_contents('php://input');
$json = json_decode($request);
$urlid = $json->{"urlid"};
$json = $json->{"data"};
if (session_start() === FALSE)
{
echo "{ \"postsuccess\": false, \"error\": -1 }";
return;
}
if(!isset($_SESSION["username"]) ||
!isset($_SESSION["expirationdate"]) ||
!isset($_SESSION["securitytoken"]) ||
$_SESSION["expirationdate"] <= time())
{
echo "{ \"postsuccess\": false, \"error\": -2 }";
return;
}
if(strtolower($_SESSION["username"]) != strtolower($_COOKIE["UserNameCookie"]))
{
echo "{ \"postsuccess\": false, \"error\": -3 }";
return;
}
$json->{"securitytoken"} = strtolower($_SESSION["securitytoken"]);
$json->{"username"} = strtolower($_SESSION["username"]);
$request = json_encode($json);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $URL[$urlid]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/plain; charset=utf-8"));
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$data = curl_exec($ch);
curl_close($ch);
echo $data;
?>
Node.js (Typescript)
function handler(request: ExpressServerRequest, response: ExpressServerResponse) {
try {
var json = (request.body || JSON.parse(request.rawBody));
var security_token = request.cookies.get(global.security_token_cookie, {signed: true});
var username = request.cookies.get(global.username_cookie, {signed: true});
var urlid = json.urlid;
json = json.data;
if (!security_token || !username) {
response.send({postsuccess: false, error: -2});
return;
}
json.securitytoken = security_token;
json.username = username;
var callback = function(data) {
response.json(data);
};
db.databaseRequest(urlid, json, callback);
} catch (e) {
console.error(e.stack);
response.send({postsuccess: false, error: -1});
}
}
//Was in a different module
function databaseRequest(url: number, data: any, callback: (any) => void) {
try {
var json = JSON.stringify(data);
var headers = {
"Content-Type": "application/json",
"Content-Length": json.length
};
var options = {
host: db_host,
port: db_port,
path: url_locations[url],
headers: headers,
method: "POST"
};
var request = http.request(options, function(response) {
response.setEncoding("utf8");
var returnData = "";
response.on("data", function(d) {
returnData += d;
});
response.on("end", function() {
if (returnData) {
callback(JSON.parse(returnData));
} else {
callback(null);
}
});
});
request.on("error", function(e) {
console.error("Error posting database request:");
console.error("Location: " + url_locations[url]);
console.error("Data: " + json);
console.error("Error Event: " + e);
});
request.write(json);
console.log("Sending: " + json + " to " + url_locations[url]);
request.end();
} catch (e) {
console.error(e.stack);
request.end();
callback({ "dberror" : true });
}
}
EDIT:
I'm going to keep this updated, but I honestly doubt anybody but me will ever have this issue. :/
I found the root of the problem. It turned out to be a concurrency issue. PHP submitted the requests linearly, while Node.js is non-blocking, so it send requests before the others got back. Essentially, I was dumb enough to store state information in a processor. My routes look something like this:
from("jetty:http://foo").process(new WorkProcessor()).to("direct:foo2");
My initial thinking was that "OK, a new WorkProcessor is created every time the route is triggered, so each message gets its own little sandbox". Unfortunately, that's not the case, it's only created once. I don't know why I would think that, but I did. :(
So I cleared up the issue by not storing info in Processor instances. It made my code a little longer, but it solved my issue.
The first code:
if(isset($_GET["hub_challenge"])) {
echo $_GET["hub_challenge"];
}
else {
}
$feeded = $_POST['feed'];
$ch = curl_init("http://pubsubhubbub.appspot.com");
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch,CURLOPT_POSTFIELDS,"hub.mode=subscribe&hub.verify=async&hub.callback=http://rssreaderbg.net/pubsubbub/example/index.php?url=$feeded&hub.topic=$feeded");
curl_exec($ch);
The callback code:
file_put_contents("logmeme.txt",$HTTP_RAW_POST_DATA,FILE_APPEND);
https://pubsubhubbub.appspot.com/topic-details?hub.url=http%3A%2F%2Frssreaderbg.net%2Fblog%2F%3Ffeed%3Drss2
https://pubsubhubbub.appspot.com/subscription-details?hub.callback=http%3A%2F%2Frssreaderbg.net%2Fpubsubbub%2Fexample%2Findex.php&hub.topic=http%3A%2F%2Frssreaderbg.net%2Fblog%2F%3Ffeed%3Drss2&hub.secret=
It can't reach the callback url or ?
Try explicitly setting the header to 2xx before echoing the challenge.
header('HTTP/1.1 204 "No Content"', true, 204);