所以我一直在尝试设置Paypal IPN,并尝试了大量不同的解决方案来让我的IPN验证。出于某种原因,当我使用Sanbox paypal时它工作正常,但是一旦我尝试使用实时版本,就没有任何反应。没有错误日志,没有IPN日志,没有。我迷失了。
我想知道是否有新眼睛会发现问题。这是我的paypal.php课程:
<?php
session_start();
$base = "/var/www/html/";
include("db.php");
require_once('paypal.class.php'); // include the class file
$p = new paypal_class; // initiate an instance of the class
//$p->paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; // testing paypal url
$p->paypal_url = 'https://www.paypal.com/cgi-bin/webscr'; // paypal url
// setup a variable for this script (ie: 'http://www.micahcarrick.com/paypal.php')
$this_script = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
// if there is not action variable, set the default action of 'process'
if (empty($_GET['action'])) $_GET['action'] = 'process';
if (empty($_GET['amm'])) $_GET['amm'] = '1';
$EMAIL = 'emailaddresshere';
switch ($_GET['action']) {
case 'process': // Process and order...
if (empty($_GET['prod'])){
header("Location: confirm-product.php"); //Was donate.php (but no file for that, so might be confirm-product)
exit;
}
if (empty($_GET['username'])){
if($_GET['action'] = 'process'){
header("Location: confirm-product.php"); // was donate.php as well
exit;
}
}
//if(!isset($_SESSION["username"])) {
// header("Location: login.php");
// exit;
//}
//include("include.php");
//die("donation is temporarily disabled!");
// There should be no output at this point. To process the POST data,
// the submit_paypal_post() function will output all the HTML tags which
// contains a FORM which is submited instantaneously using the BODY onload
// attribute. In other words, don't echo or printf anything when you're
// going to be calling the submit_paypal_post() function.
// This is where you would have your form validation and all that jazz.
// You would take your POST vars and load them into the class like below,
// only using the POST values instead of constant string expressions.
// For example, after ensureing all the POST variables from your custom
// order form are valid, you might have:
//
// $p->add_field('first_name', $_POST['first_name']);
// $p->add_field('last_name', $_POST['last_name']);
$price = '10.00';
if($_GET['prod'] == 1)
$price = '10.00';
if($_GET['prod'] == 2)
$price = '45.00';
if($_GET['prod'] == 3)
$price = '80.00';
if($_GET['prod'] == 4)
$price = '300.00';
if($_GET['prod'] == 5) //remove/change prod 5 after testing
$price = '0.01';
$name = '1K Donator Points';
if ($_GET['prod'] == 1)
$name = '1K Donator Points';
if ($_GET['prod'] == 2)
$name = '5K Donator Points';
if ($_GET['prod'] == 3)
$name = '10K Donator Points';
if ($_GET['prod'] == 4)
$name = '50K Donator Points';
if ($_GET['prod'] == 5)
$name = 'Testing Payment';
$p->add_field('custom', $_GET['username']);
$p->add_field('business', $EMAIL);
$p->add_field('return', $this_script.'?action=success');
$p->add_field('cancel_return', $this_script.'?action=cancel');
$p->add_field('notify_url', $this_script.'?action=ipn');
$p->add_field('item_name', ''.$name);
$p->add_field('item_number', $_GET['prod']);
$p->add_field('currency_code', 'USD');
$p->add_field('amount', $price);
//$p->add_field('quantity', $_GET['amm']);
$p->add_field('lc', 'GB');
$p->submit_paypal_post(); // submit the fields to paypal
// $p->dump_fields(); // for debugging, output a table of all the fields
break;
case 'success': // Order was successful...
// This is where you would probably want to thank the user for their order
// or what have you. The order information at this point is in POST
// variables. However, you don't want to "process" the order until you
// get validation from the IPN. That's where you would have the code to
// email an admin, update the database with payment status, activate a
// membership, etc.
//include("include.php");
echo "<h2>Donation Successful</h2><p>Your payment has been completed.</p>";
// You could also simply re-direct them to another page, or your own
// order status page which presents the user with the status of their
// order based on a database (which can be modified with the IPN code
// below).
break;
case 'cancel': // Order was canceled...
// The order was canceled before being completed.
//include("include.php");
echo "<h2>Payment Cancelled</h2><p>Your payment was cancelled.</p>";
break;
case 'ipn': // Paypal is calling page for IPN validation...
// It's important to remember that paypal calling this script. There
// is no output here. This is where you validate the IPN data and if it's
// valid, update your database to signify that the user has payed. If
// you try and use an echo or printf function here it's not going to do you
// a bit of good. This is on the "backend". That is why, by default, the
// class logs all IPN data to a text file.
if ($p->validate_ipn()) {
error_log("Made it to validating IPN", 3, "myerrors.log");
// Payment has been recieved and IPN is verified. This is where you
// update your database to activate or process the order, or setup
// the database with the user's order details, email an administrator,
// etc. You can access a slew of information via the ipn_data() array.
// Check the paypal documentation for specifics on what information
// is available in the IPN POST variables. Basically, all the POST vars
// which paypal sends, which we send back for validation, are now stored
// in the ipn_data() array.
if($p->ipn_data["payment_status"] != "Completed") die();
error_log("Payment Status = Completed, if this message shows - ", 3, "myerrors.log");
if($p->ipn_data["mc_gross"] > 0 && strcmp ($p->ipn_data["business"],$EMAIL) == 0) {
error_log("Blah blah blah 33", 3, "myerrors.log");
$user = $p->ipn_data["custom"];
$date = $p->ipn_data["payment_date"];
$prodid = $p->ipn_data["item_number"];
$amount = $p->ipn_data["mc_gross"];
$amountTickets = 1;
$user = str_replace("-", "_", $user);
$user = str_replace(" ", "_", $user);
$user = mysqli_real_escape_string($mysqli, $user);
$prodid = mysqli_real_escape_string($mysqli, $prodid);
$amount = mysqli_real_escape_string($mysqli, $amount);
$mysqli = new mysqli("host", "name", "pass", "db");
if ($mysqli->connect_error) {
// error_log("Connection Failed to Database", 3, "myerrors.log");
}
$query = "INSERT INTO donation (username, time, productid, price, tickets) VALUES ('".$user."', '".$date."', '".$prodid."', '".$amount."', '".$amountTickets."');";
$mysqli->query($query);
//
error_log("Passed through MySql Table insertion lines.", 3, "myerrors.log");
}
error_log(" - Finished validating IPN process.", 3, "myerrors.log");
}
break;
}
?>
这是我的paypal.class.php课程
<?php
/*******************************************************************************
* PHP Paypal IPN Integration Class
*******************************************************************************
* Author: Micah Carrick
* Email: email@micahcarrick.com
* Website: http://www.micahcarrick.com
*
* File: paypal.class.php
* Version: 1.3.0
* Copyright: (c) 2005 - Micah Carrick
* You are free to use, distribute, and modify this software
* under the terms of the GNU General Public License. See the
* included license.txt file.
*
*******************************************************************************
*/
class paypal_class {
var $last_error; // holds the last error encountered
var $ipn_log; // bool: log IPN results to text file?
var $ipn_log_file; // filename of the IPN log
var $ipn_response; // holds the IPN response from paypal
var $ipn_data = array(); // array contains the POST values for IPN
var $fields = array(); // array holds the fields to submit to paypal
public $timeout = 30;
private $post_data = array();
private $post_uri = '';
private $response_status = '';
private $response = '';
const PAYPAL_HOST = 'www.paypal.com';
function paypal_class() {
// initialization constructor. Called when class is created.
$this->paypal_url = 'https://www.paypal.com/cgi-bin/webscr'; //real one
// $this->paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; //testing one
$this->last_error = '';
$this->ipn_log_file = '.ipn_results.log';
$this->ipn_log = true;
$this->ipn_response = '';
// populate $fields array with a few default values. See the paypal
// documentation for a list of fields and their data types. These defaul
// values can be overwritten by the calling script.
$this->add_field('rm','2'); // Return method = POST
$this->add_field('cmd','_xclick');
}
public function getPostUri() {
return $this->post_uri;
}
function add_field($field, $value) {
// adds a key=>value pair to the fields array, which is what will be
// sent to paypal as POST variables. If the value is already in the
// array, it will be overwritten.
$this->fields["$field"] = $value;
}
function submit_paypal_post() {
// this function actually generates an entire HTML page consisting of
// a form with hidden elements which is submitted to paypal via the
// BODY element's onLoad attribute. We do this so that you can validate
// any POST vars from you custom form before submitting to paypal. So
// basically, you'll have your own form which is submitted to your script
// to validate the data, which in turn calls this function to create
// another hidden form and submit to paypal.
// The user will briefly see a message on the screen that reads:
// "Please wait, your order is being processed..." and then immediately
// is redirected to paypal.
echo "<html>\n";
echo "<head><title>Processing Payment...</title></head>\n";
echo "<body onLoad=\"document.forms['paypal_form'].submit();\">\n";
echo "<center><h2>Please wait, your order is being processed and you";
echo " will be redirected to the paypal website.</h2></center>\n";
echo "<form method=\"post\" name=\"paypal_form\" ";
echo "action=\"".$this->paypal_url."\">\n";
foreach ($this->fields as $name => $value) {
echo "<input type=\"hidden\" name=\"$name\" value=\"$value\"/>\n";
}
echo "<center><br/><br/>If you are not automatically redirected to ";
echo "paypal within 5 seconds...<br/><br/>\n";
echo "<input type=\"submit\" value=\"Click Here\"></center>\n";
echo "</form>\n";
echo "</body></html>\n";
}
function validate_ipn() {
// parse the paypal URL
// $url_parsed=parse_url($this->paypal_url);
error_log(" - Parsed URL.", 3, "myerrors.log"); //remove after
// generate the post string from the _POST vars aswell as load the
// _POST vars into an arry so we can play with them from the calling
// script.
$post_string = ''; //old
// $post_string="cmd=_notify-validate"; //new
foreach ($_POST as $field=>$value) {
$this->ipn_data["$field"] = $value;
$post_string .= $field.'='.urlencode(stripslashes($value)).'&'; //old
// $post_string .= '&' . $field.'='.urlencode(stripslashes($value)); //new
}
$post_string.="cmd=_notify-validate"; // append ipn command
error_log(" - Into ValidatingIPN, Line 187.", 3, "myerrors.log"); //remove after
// open the connection to paypal
// $fp = fsockopen($url_parsed['host'], 443, $errnum, $errstr, 30); //old real one
// $fp = fsockopen('ssl://www.paypal.com', 443, $errnum, $errstr, 30); //try this
// $fp = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30); //try this
// $fp = fsockopen('https://www.paypal.com', 443, $errnum, $errstr, 30);
// $fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); //testing one
/* if ($url_parsed['scheme'] == 'https') {
$url_parsed['port'] = 443;
$ssl = 'ssl://';
} else {
$url_parsed['port'] = 80;
$ssl = '';
}
$fp = fsockopen($ssl.$url_parsed['host'], $url_parsed['port'], $errnum, $errstr, 30); */
//Real One v2
$uri = 'ssl://www.paypal.com';
$port = '443';
$this->post_uri = $uri.'/cgi-bin/webscr';
$fp = fsockopen($uri, $port, $errno, $errstr, $this->timeout);
if(!$fp) {
throw new Exception("fsockopen error: [$errno] $errstr");
}
// Post the data back to paypal
// fputs($fp, "POST $url_parsed[path] HTTP/1.1\r\n"); //old
/* fputs($fp, "POST /cgi-bin/webscr HTTP/1.1\r\n");
fputs($fp, "Host: www.sandbox.paypal.com\r\n"); //sandbox - www.sandbox.paypal.com
fputs($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-Length: ".strlen($post_string)."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $post_string . "\r\n\r\n"); */
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Host: www.paypal.com\r\n"; //real - www.paypal.com
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: ".strlen($post_string)."\r\n";
$header .= "Connection: Close\r\n\r\n";
fputs($fp, $header.$post_string."\r\n\r\n");
error_log(" - Connected to paypal connection. Posted Data to paypal.", 3, "myerrors.log"); //remove after
// loop through the response from the server and append to variable
while(!feof($fp)) {
$this->ipn_response .= fgets($fp, 1024); //old
}
fclose($fp); // close connection
// if (eregi("VERIFIED",$this->ipn_response)) { //old
if (preg_match("VERIFIED", $this->ipn_response)) { //new ~VERIFIED~i for sandbox
// Valid IPN transaction.
error_log(" - Valid IPN Transaction.", 3, "myerrors.log"); //remove after
$this->log_ipn_results(true);
return true;
} else {
// Invalid IPN transaction. Check the log for details.
$this->last_error = 'IPN Validation Failed.';
error_log(" - IPN Validation Failed", 3, "myerrors.log"); //remove after
$this->log_ipn_results(true); //Default: false
return false;
}
}
function log_ipn_results($success) {
if (!$this->ipn_log) return; // is logging turned off?
// Timestamp
$text = '['.date('m/d/Y g:i A').'] - ';
// Success or failure being logged?
if ($success) $text .= "SUCCESS!\n";
else $text .= 'FAIL: '.$this->last_error."\n";
// Log the POST variables
$text .= "IPN POST Vars from Paypal:\n";
foreach ($this->ipn_data as $key=>$value) {
$text .= "$key=$value, ";
}
// Log the response from the paypal server
$text .= "\nIPN Response from Paypal Server:\n ".$this->ipn_response;
// Write to log
$fp=fopen($this->ipn_log_file,'a');
fwrite($fp, $text . "\n\n");
fclose($fp); // close file
}
function dump_fields() {
// Used for debugging, this function will output all the field/value pairs
// that are currently defined in the instance of the class using the
// add_field() function.
echo "<h3>paypal_class->dump_fields() Output:</h3>";
echo "<table width=\"95%\" border=\"1\" cellpadding=\"2\" cellspacing=\"0\">
<tr>
<td bgcolor=\"black\"><b><font color=\"white\">Field Name</font></b></td>
<td bgcolor=\"black\"><b><font color=\"white\">Value</font></b></td>
</tr>";
ksort($this->fields);
foreach ($this->fields as $key => $value) {
echo "<tr><td>$key</td><td>".urldecode($value)." </td></tr>";
}
echo "</table><br>";
}
}