我有一个 PayPal 捐赠 IPN 的监听器。然而,它没有被调用,PayPal 沙箱中也没有日志。代码是:
donations.php:
<?php
// For test payments we want to enable the sandbox mode. If you want to put live
// payments through then this setting needs changing to `false`.
$enableSandbox = true;
// Database settings. Change these for your database configuration.
$dbConfig = [
'host' => 'localhost',
'username' => 'xxxx',
'password' => 'xxxx',
'name' => 'xxxx'
];
// PayPal settings. Change these to your account details and the relevant URLs
// for your site.
$paypalConfig = [
'email' => $enableSandbox ? '[email protected]' : '[email protected]',
'return_url' => 'https://example.com/index.php?page=/donation-successful.php',
'cancel_url' => 'https://example.com/index.php?page=/donation-cancelled.php',
'notify_url' => 'https://example.com/donations.php',
];
$paypalUrl = $enableSandbox ? 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr' : 'https://ipnpb.paypal.com/cgi-bin/webscr';
function verifyTransaction($data) {
global $paypalUrl;
$req = 'cmd=_notify-validate';
foreach ($data as $key => $value) {
$value = urlencode(stripslashes($value));
//$value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i', '${1}%0D%0A${3}', $value); // IPN fix
$req .= "&$key=$value";
}
$ch = curl_init($paypalUrl);
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_SSLVERSION, 6);
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_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
$res = curl_exec($ch);
if (!$res) {
$errno = curl_errno($ch);
$errstr = curl_error($ch);
curl_close($ch);
throw new Exception("cURL error: [$errno] $errstr");
}
$info = curl_getinfo($ch);
// Check the http response
$httpCode = $info['http_code'];
if ($httpCode != 200) {
throw new Exception("PayPal responded with http code $httpCode");
}
curl_close($ch);
return $res == 'VERIFIED';
}
function checkTxnid($txnid) {
$db = new mysqli($dbConfig['host'], $dbConfig['username'], $dbConfig['password'], $dbConfig['name']);
$txnid = $db->real_escape_string($txnid);
$results = $db->query('SELECT * FROM `donations` WHERE txnid = \'' . $txnid . '\'');
return ! $results->num_rows;
}
function addPayment($data) {
$db = new mysqli($dbConfig['host'], $dbConfig['username'], $dbConfig['password'], $dbConfig['name']);
if (is_array($data)) {
if ($db->query("INSERT INTO 'donations' (txnid, payment_amount, payment_status, createdtime) VALUES('" . $data["txn_id"] . "', '" . $data["payment_amount"] . "', '" . $data["payment_status"] . "', '" . date("Y-m-d H:i:s") . "')")) {
return true;
}
}
return false;
}
// Check if paypal request or response
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$data = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2) {
$data[$keyval[0]] = urldecode($keyval[1]);
}
}
if (!isset($data["txn_id"]) && !isset($data["txn_type"])) {
// Set the PayPal account.
$data['business'] = $paypalConfig['email'];
// Set the PayPal return addresses.
$data['return'] = stripslashes($paypalConfig['return_url']);
$data['cancel_return'] = stripslashes($paypalConfig['cancel_url']);
$data['notify_url'] = stripslashes($paypalConfig['notify_url']);
// Set the currency so that these aren't overridden by the form data.
$data['currency_code'] = 'GBP';
// Build the query string from the data.
$queryString = http_build_query($data);
// Redirect to paypal IPN
header('location:' . $paypalUrl . '?' . $queryString);
exit();
} else {
// Handle the PayPal response.
// Create a connection to the database.
$db = new mysqli($dbConfig['host'], $dbConfig['username'], $dbConfig['password'], $dbConfig['name']);
// We need to verify the transaction comes from PayPal and check we've not
// already processed the transaction before adding the payment to our
// database.
if (verifyTransaction($data) && checkTxnid($data['txn_id'])) {
// Assign posted variables to local data array.
$data = [
'item_name' => $data['item_name'],
'item_number' => $data['item_number'],
'payment_status' => $data['payment_status'],
'payment_amount' => $data['mc_gross'],
'payment_currency' => $data['mc_currency'],
'txn_id' => $data['txn_id'],
'receiver_email' => $data['receiver_email'],
'payer_email' => $data['payer_email'],
];
if (addPayment($data) !== false) {
// Payment successfully added.
}
}
}
?>
替换了一些地方的敏感信息,但你明白了。 PayPal 日志中没有任何内容。我的捐赠数据库中没有添加任何内容。付款在交易列表中显示为已完成。