use_ssl) { $uri = 'https://'.$this->getPaypalHost().'/cgi-bin/webscr'; $this->post_uri = $uri; } else { $uri = 'http://'.$this->getPaypalHost().'/cgi-bin/webscr'; $this->post_uri = $uri; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $uri); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded_data); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $this->follow_location); curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); if ($this->force_ssl_v3) { curl_setopt($ch, CURLOPT_SSLVERSION, 3); } $this->response = curl_exec($ch); $this->response_status = strval(curl_getinfo($ch, CURLINFO_HTTP_CODE)); if ($this->response === false || $this->response_status == '0') { $errno = curl_errno($ch); $errstr = curl_error($ch); throw new Exception("cURL error: [$errno] $errstr"); } } /** * Post Back Using fsockopen() * * Sends the post back to PayPal using the fsockopen() function. Called by * the processIpn() method if the use_curl property is false. Throws an * exception if the post fails. Populates the response, response_status, * and post_uri properties on success. * * @param string The post data as a URL encoded string */ protected function fsockPost($encoded_data) { if ($this->use_ssl) { $uri = 'ssl://'.$this->getPaypalHost(); $port = '443'; $this->post_uri = $uri.'/cgi-bin/webscr'; } else { $uri = $this->getPaypalHost(); // no "http://" in call to fsockopen() $port = '80'; $this->post_uri = 'http://'.$uri.'/cgi-bin/webscr'; } $fp = fsockopen($uri, $port, $errno, $errstr, $this->timeout); if (!$fp) { // fsockopen error throw new Exception("fsockopen error: [$errno] $errstr"); } $header = "POST /cgi-bin/webscr HTTP/1.0rn"; $header .= "Host: ".$this->getPaypalHost()."rn"; $header .= "Content-Type: application/x-www-form-urlencodedrn"; $header .= "Content-Length: ".strlen($encoded_data)."rn"; $header .= "Connection: Closernrn"; fputs($fp, $header.$encoded_data."rnrn"); while(!feof($fp)) { if (empty($this->response)) { // extract HTTP status from first line $this->response .= $status = fgets($fp, 1024); $this->response_status = trim(substr($status, 9, 4)); } else { $this->response .= fgets($fp, 1024); } } fclose($fp); } private function getPaypalHost() { if ($this->use_sandbox) return IpnListener::SANDBOX_HOST; else return IpnListener::PAYPAL_HOST; } /** * Get POST URI * * Returns the URI that was used to send the post back to PayPal. This can * be useful for troubleshooting connection problems. The default URI * would be "ssl://www.sandbox.paypal.com:443/cgi-bin/webscr" * * @return string */ public function getPostUri() { return $this->post_uri; } /** * Get Response * * Returns the entire response from PayPal as a string including all the * HTTP headers. * * @return string */ public function getResponse() { return $this->response; } /** * Get Response Status * * Returns the HTTP response status code from PayPal. This should be "200" * if the post back was successful. * * @return string */ public function getResponseStatus() { return $this->response_status; } /** * Get Text Report * * Returns a report of the IPN transaction in plain text format. This is * useful in emails to order processors and system administrators. Override * this method in your own class to customize the report. * * @return string */ public function getTextReport() { $r = ''; // date and POST url for ($i=0; $i<80; $i++) { $r .= '-'; } $r .= "n[".date('m/d/Y g:i A').'] - '.$this->getPostUri(); if ($this->use_curl) $r .= " (curl)n"; else $r .= " (fsockopen)n"; // HTTP Response for ($i=0; $i<80; $i++) { $r .= '-'; } $r .= "n{$this->getResponse()}n"; // POST vars for ($i=0; $i<80; $i++) { $r .= '-'; } $r .= "n"; foreach ($this->post_data as $key => $value) { $r .= str_pad($key, 25)."$valuen"; } $r .= "nn"; return $r; } /** * Process IPN * * Handles the IPN post back to PayPal and parsing the response. Call this * method from your IPN listener script. Returns true if the response came * back as "VERIFIED", false if the response came back "INVALID", and * throws an exception if there is an error. * * @param array * * @return boolean */ public function processIpn($post_data=null) { $encoded_data = 'cmd=_notify-validate'; if ($post_data === null) { // use raw POST data if (!empty($_POST)) { $this->post_data = $_POST; $encoded_data .= '&'.file_get_contents('php://input'); } else { throw new Exception("No POST data found."); } } else { // use provided data array $this->post_data = $post_data; foreach ($this->post_data as $key => $value) { $encoded_data .= "&$key=".urlencode($value); } } if ($this->use_curl) $this->curlPost($encoded_data); else $this->fsockPost($encoded_data); if (strpos($this->response_status, '200') === false) { throw new Exception("Invalid response status: ".$this->response_status); } if (strpos($this->response, "VERIFIED") !== false) { return true; } elseif (strpos($this->response, "INVALID") !== false) { return false; } else { throw new Exception("Unexpected response from PayPal."); } } /** * Require Post Method * * Throws an exception and sets a HTTP 405 response header if the request * method was not POST. */ public function requirePostMethod() { // require POST requests if ($_SERVER['REQUEST_METHOD'] && $_SERVER['REQUEST_METHOD'] != 'POST') { header('Allow: POST', true, 405); throw new Exception("Invalid HTTP request method."); } } } ?> use_sandbox = true; // try to process the IPN POST try { $listener->requirePostMethod(); $verified = $listener->processIpn(); } catch (Exception $e) { error_log($e->getMessage()); exit(0); } if ($verified) { $errmsg = ''; // stores errors from fraud checks // 1. Make sure the payment status is "Completed" if ($_POST['payment_status'] != 'Completed') { // simply ignore any IPN that is not completed exit(0); } // 2. Make sure seller email matches your primary account email. if ($_POST['receiver_email'] != 'mail@example.com') { $errmsg .= "'receiver_email' does not match: "; $errmsg .= $_POST['receiver_email']."n"; } // 3. Make sure the amount(s) paid match //if ($_POST['mc_gross'] != '9.99') { //$errmsg .= "'mc_gross' does not match: "; //$errmsg .= $_POST['mc_gross']."n"; //} // 4. Make sure the currency code matches if ($_POST['mc_currency'] != 'USD') { $errmsg .= "'mc_currency' does not match: "; $errmsg .= $_POST['mc_currency']."n"; } // 5. Ensure the transaction is not a duplicate. mysql_connect('dfdesignzstudiocom.ipagemysql.com','root2121','******') or exit(0); mysql_select_db('paypal') or exit(0); if (!empty($errmsg)) { // manually investigate errors from the fraud checking $body = "IPN failed fraud checks: n$errmsgnn"; $body .= $listener->getTextReport(); mail('myemail@example.com', 'IPN Fraud Warning', $body); } else { // add this order to a table of completed orders $payer_email = mysql_real_escape_string($_POST['payer_email']); $first_name = mysql_real_escape_string($_POST['first_name']); $last_name = mysql_real_escape_string($_POST['last_name']); $contact_phone = mysql_real_escape_string($_POST['contact_phone']); $item_name = mysql_real_escape_string($_POST['item_name']); $quantity = mysql_real_escape_string($_POST['quantity']); $mc_fee = mysql_real_escape_string($_POST['mc_fee']); $sql = "INSERT INTO orders (payer_email, first_name, last_name, contact_phone, item_name, quantity, mc_fee) VALUES ('$payer_email', '$first_name', '$last_name', '$contact_phone', '$item_name', '$quantity', '$mc_fee')"; if (!mysql_query($sql)) { error_log(mysql_error()); exit(0); } // send seller an email with buyer information $to = filter_var('myemail@example.com', FILTER_SANITIZE_EMAIL); $subject = "New Class Registration"; $message = "Registration Information: n$first_name $last_namen$payer_emailnItem Name: $item_name nQuantity: $quantitynTotal paid: $mc_fee"; mail($to, $subject, $message); $command="mysqldump --xml --host=dfdesignzstudiocom.ipagemysql.com --user=root2121 --password=****** paypal > database.xml"; system($command); } } else { // manually investigate the invalid IPN mail('myemail@example.com', 'Invalid IPN', $listener->getTextReport()); } ?>